Swift Collection View: Phase 8/9

So far, you learned how to implement these features in the SwiftCollectionView application:

Today you will learn how to implement these feature in the SwiftCollectionView application:

  • Display the number of selected cells in the navigation bar.
  • Share selected collection view cell’s photos with friends.

Take a look at this video. It shows how the app will function on a real iOS device; from the moment you tap the share button to the moment you tap the Mail Composer’s Send button.


Video 8-1: App running on an iPhone 4s device

The image below shows what you’ll see when you run the app on the iOS Simulator and tap the share button.

swiftcv-figure8-1

Figure 8-1: Output on the iPhone 4s Simulator

Before You Begin

Before you begin, I assume the following:

  • You created a new branch from the collection-view-plist branch and you called it share-photos.
  • You will use Xcode Version 6.1.1 to implement the above features in the SwiftCollection project.
  • You’re a member of the Apple iOS Developer Program. If you aren’t, then you won’t be able to test the mailing feature of this version of the SwiftCollectionView app.
  • In Xcode Version 6.1.1 you have to update the lines that display errors in the  MasterViewController.swift file by adding an! at the end of self.collectionView. Here’s how to fix the first one.

Change the statement on line 32 from this:

self.collectionView.backgroundColor = UIColor(patternImage: UIImage(named: "purty_wood")!)

to this:

self.collectionView!.backgroundColor = UIColor(patternImage: UIImage(named: "purty_wood")!)

For remaining lines that have an error, add the ! as shown above.

Create and Connect The Share Button in IB

Here are the steps to create the share button on the navigation bar.

  • Click the Main.storyboard file to load it in Interface Builder.
  • Drag a Bar Button from the Object Library and drop it on the left corner of the Photos scene’s navigation Bar.
  • In the Attributes inspector, select Action from the Identifier menu.
  • Use the Assistant editor to create and connect an IBOutlet variable for the button.
  • Use the Assistant editor to create and connect an IBAction function for the shareButton; call it shareButtonTapped method. You should create the function at the end of the MasterViewController.swift file.

Add Two rightBarButtons on The Nav Bar

You have to modify the Photos scene’s navigation Bar so it displays two buttons on the right side of the navigation bar-see image below. Interface Builder allows you to add only one button on either end of the navigation bar. They are called leftBarButton and rightBarButton. To add two rightBarButtons on the navigation bar, you’ll have to add code in the MasterViewController.swift file’s viewDidLoad() function.

swiftcv-figure8-2

Start by deleting the Edit button from the Photos scene’s navigation bar. Also, delete text from the navigation’s Title field. Switch to the MasterViewController.swift file and delete the Edit button’s IBOutlet variable.

Here is the code to create and add the rightBarButtons on the photos scene’s navigation bar. Add the code in the MasterViewController.swift file’s viewDidLoad() function.

// Set two properties of the counterLabel object
counterLabel.textColor = UIColor(red:1.00, green:0.00, blue:0.50 ,alpha:1.00) // pink color
counterLabel.text = "0 photos selected"

//1. Create two bar Bar Button Items, connect only one of them to an IBAction function
photoCounterButton = UIBarButtonItem(customView: counterLabel)
editButton = UIBarButtonItem(title: "Edit", style: .Plain, target:self, action:"editButtonTapped:") 

//2. Add the buttons in the buttonArray variable
let buttonArray = [editButton, photoCounterButton] 

//3. Put the buttons on the Photos scene's nav bar
self.navigationItem.rightBarButtonItems = buttonArray

Remember; the photoCounterButton’s sole purpose is to display the number of collection view cells selected, so that’s why we did not connect it to an IBAction function. Later, you’ll add code in the MasterViewController.swift file to update the button’s counterLabel properties.

The last thing you have to do to complete the task of setting up the rightBarButtons on the Photos scene’s navigation bar is, add these variable declaration statements at the top of the MasterViewController.swift file.

var photoCounterButton: UIBarButtonItem!
var editButton: UIBarButtonItem!
var shareEnabled = false
var selectedCellItems = [String]()
var counterLabel = UILabel()

Run the application say, in the iPhone 4s simulator. You will only see the Share and edit button on the navigation bar. Later, when you add code to update the photoCounter button, the photoCounter button’s text shows up on the Photos view’s navigation bar-see above image. The Edit button should work as before; however, the share button doesn’t yet.

How The Share Button Will Work

Before I show you the share button’s code; I’ll explain how it will work. In a nutshell, the share button’s job is to put the app in “edit mode” so you can select one more collection view cells’ photos and email them to one or more friends. The share button is connected to the shareButtonTapped() function. The code you’ll add in the function will perform several tasks. Here is a list of the most important ones:

  • Put the app in sharing mode.
  • Create an object called mailComposer from the MFMailComposeViewController class.
  • Construct an email for the MailComposer view.
  • Display the mailComposer’s view on the device’s screen.
  • Wait for you to enter one or more email addresses in the To: field and to tap/click the send button.
  • Once you tap/click the mailComposer view’s Send button. The app responds by checking the device’s type. If its a real device; the app sends your email to the recipient’s email address. You will hear a swooshing sound-assuming your device’s speaker isn’t muted. If the device is an iOS Simulator, the app will display a message in an alert view.

A note about the last item in the above list. If you try to send an email using an iOS Simulator, the app will crash. That’s because the iOS Simulator can’t send emails; only a real iOS device can.

Configure The MasterViewController Class to Send Mail

When you tap the share button, code in the shareButtonTapped() function will pass control to an instance of the MFMailComposerViewController class. In code, we’ll call that instance mailComposer. Its job is to present its view on the device’s screen so you can send mail. Before you can use the MFMailComposerViewController class in the MasterViewController.swift file, you have to configure it to use the MFMailComposerViewController class.

Start by executing these steps, which import the MessageUI.framework in the project. The framework has three header files, one of them is the MFMailComposerViewController.h file.

  • Click the root project folder in the project navigator panel.
  • Click the Build Phases tab.
  • Expand the Link Binary With Libraries item. Click the + button.
  • Type mes in the popup window’s search box.
  • Select the MessageUI.framework in the search results list, then click the Add button. Xcode add the framework in the project.

Now, you have to conform the MasterViewController.swift class file to the MFMailComposeViewControllerDelegate protocol. You do that by changing the class file’s header to this:

class MasterViewController: UICollectionViewController, MFMailComposeViewControllerDelegate {

Finally, you have to import the MessageUI.h file in the MasterViewController.swift file. You do that by adding this import statement in the MasterViewController.swift file.

import MessageUI

Ok, so you’ve configured the MasterViewController.swift class file to send mail. You are ready to add code in the shareButtonTapped() function.

Add Code in The shareButtonTapped() Function

Here is the first set of code to add in the shareButtonTapped() function. It checks to see if the device is an iOS Simulator or not. If it is, then code in the if statement block is executed. If it isn’t, then only the print() statement is executed.

@IBAction func shareButtonTapped(sender: AnyObject) {
if deviceIsSimulator() {
  let alertView = UIAlertController(title: nil, message: "Your device can't send mail", preferredStyle: .Alert) 

  alertView.addAction(UIAlertAction(title: "Ok", style: .Default, handler: nil))
  presentViewController(alertView, animated: true, completion: nil)

  // This prevent code below from executing
  return
}

print("The device is not a simulator and shareEnabled = \(shareEnabled)")
}

Notice how the deviceIsSimulator() function is called in the if statement. Here is the code to implement the function. Add the code below the shareButtonTapped() function’s code.

// This function check to see if the current device is an iPhone or iPad Simulator.
// If so, then return the Boolean value true, otherwise return false
func deviceIsSimulator() -> Bool {
  var isSimulator = false
  if UIDevice.currentDevice().model == "iPhone Simulator" || UIDevice.currentDevice().model == "iPad Simulator" {
    isSimulator = true
  } 

  return isSimulator
}

Test The Share Button Code

Now is a good time to run the app in the iPhone 4s simulator to test the share button code. You should see output shown in Figure 8-1 above on the simulator’s screen when you click the share button. Test the app on a real device, you’ll have to enroll in Apple’s iOS Developer Program. Assuming you’re a member of Apple’s iOS Developer Program, here’s how to test the app on your device.

Connect your real device to your Mac, hit the run button in Xcode. Wait for Xcode to launch the app on your device. Once the app is running on your device, tap the share button. You won’t see the above alert view message on your device’s screen; however, you will see the print() function’s message in Xcode’s Debugger window. The reason for this is because the if statement evaluates to false and its code block isn’t executed. 

Add More Code in The shareButtonTapped() Function

Now, delete the print() function statement you added in the shareButtonTapped() function. Next, add this code in the function. Add it below the if statement block’s closing } bracket.

if shareEnabled == true {

} else { 

}

Ok, above code snippet is saying this, if the app is in sharing mode, do this. Otherwise, do that. When is the app put in sharing mode and taken out of sharing mode? The first time you tap the share button, the app is put in sharing mode. When you tap the share button again; the app is taken out of sharing mode. Here is the code to add in the above if statement block.