An Example iOS 10 iPhone Camera Application
Previous | Table of Contents | Next |
Accessing the iOS 10 Camera and Photo Library | iOS 10 Video Playback using AVPlayer and AVPlayerViewController |
Learn SwiftUI and take your iOS Development to the Next Level |
In the chapter entitled Accessing the iOS 10 Camera and Photo Library we looked in some detail at the steps necessary to provide access to the iOS camera and photo libraries in an iOS 10 application. The purpose of this chapter is to build on this knowledge by working through an example iOS application designed to access the device’s camera and photo libraries.
An Overview of the Application
The application user interface for this example will consist of an image view and a toolbar containing two buttons. When touched by the user, the first button will display the camera to the user and allow a photograph to be taken which will subsequently be displayed in the image view. The second button will provide access to the camera roll where the user may select an existing photo image. In the case of a new image taken with the camera, this will be saved to the camera roll.
Since we will be covering the playback of video in the next chapter (iOS 10 Video Playback using AVPlayer and AVPlayerViewController) the camera roll and camera will be restricted to still images in this example. The addition of video support to this application is left as an exercise for the reader.
Creating the Camera Project
Begin the project by launching Xcode and creating a new Universal iOS application project named Camera using the Single View Application template with the Swift language option selected.
Designing the User Interface
Figure 92-1
In terms of Auto Layout constraints, begin by selecting the toolbar view and clicking on the Add New Constraints menu in the toolbar located in the lower right-hand corner of the storyboard canvas and establish Spacing to nearest neighbor constraints on the bottom and two side edges of the view with the Constrain to margins option switched off.
Learn SwiftUI and take your iOS Development to the Next Level |
Finally, with the Image View still selected, display the Attributes Inspector panel and change the Content Mode attribute to Aspect Fit.
Select the image view object in the view canvas and display the Assistant Editor panel. Ctrl-click on the image view object and drag to a position just below the class declaration line in the Assistant Editor. Release the line and, in the resulting connection dialog, establish an outlet connection named imageView.
With the Assistant Editor still visible, establish action connections for the two buttons to methods named useCamera and useCameraRoll respectively (keeping in mind that it may be necessary to click twice on each button to select it since the first click will typically select the toolbar parent object).
Close the Assistant Editor, select the ViewController.swift file and modify it further to add import and delegate protocol declarations together with a Boolean property declaration that will be required later in the chapter:
import UIKit import MobileCoreServices class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate { @IBOutlet weak var imageView: UIImageView! var newMedia: Bool? . .
Learn SwiftUI and take your iOS Development to the Next Level |
Implementing the Action Methods
The useCamera and useCameraRoll action methods now need to be implemented. The useCamera method first needs to check that the device on which the application is running has a camera. It then needs to create a UIImagePickerController instance, assign the cameraViewController as the delegate for the object and define the media source as the camera. Since we do not plan on handling videos the supported media types property is set to images only. Finally, the camera interface will be displayed. The last task is to set the newMedia flag to true to indicate that the image is new and is not an existing image from the camera roll. Bringing all these requirements together gives us the following useCamera method:
@IBAction func useCamera(_ sender: AnyObject) { if UIImagePickerController.isSourceTypeAvailable( UIImagePickerControllerSourceType.camera) { let imagePicker = UIImagePickerController() imagePicker.delegate = self imagePicker.sourceType = UIImagePickerControllerSourceType.camera imagePicker.mediaTypes = [kUTTypeImage as String] imagePicker.allowsEditing = false self.present(imagePicker, animated: true, completion: nil) newMedia = true } }
The useCameraRoll method is remarkably similar to the previous method with the exception that the source of the image is declared to be UIImagePickerControllerSourceType.photoLibrary and the newMedia flag is set to false (since the photo is already in the library we don’t need to save it again):
@IBAction func useCameraRoll(_ sender: AnyObject) { if UIImagePickerController.isSourceTypeAvailable( UIImagePickerControllerSourceType.savedPhotosAlbum) { let imagePicker = UIImagePickerController() imagePicker.delegate = self imagePicker.sourceType = UIImagePickerControllerSourceType.photoLibrary imagePicker.mediaTypes = [kUTTypeImage as String] imagePicker.allowsEditing = false self.present(imagePicker, animated: true, completion: nil) newMedia = false } }
Learn SwiftUI and take your iOS Development to the Next Level |
Writing the Delegate Methods
As described in Accessing the iOS 10 Camera and Photo Library, in order to fully implement an instance of the image picker controller delegate protocol it is necessary to implement some delegate methods. The most important method is didFinishPickingMediaWithInfo which is called when the user has finished taking or selecting an image. The code for this method in our example reads as follows:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) { let mediaType = info[UIImagePickerControllerMediaType] as! NSString self.dismiss(animated: true, completion: nil) if mediaType.isEqual(to: kUTTypeImage as String) { let image = info[UIImagePickerControllerOriginalImage] as! UIImage imageView.image = image if (newMedia == true) { UIImageWriteToSavedPhotosAlbum(image, self, #selector(ViewController.image(image:didFinishSavingWithError:contextInfo:)), nil) } else if mediaType.isEqual(to: kUTTypeMovie as String) { // Code to support video here } } } func image(image: UIImage, didFinishSavingWithError error: NSErrorPointer, contextInfo:UnsafeRawPointer) { if error != nil { let alert = UIAlertController(title: "Save Failed", message: "Failed to save image", preferredStyle: UIAlertControllerStyle.alert) let cancelAction = UIAlertAction(title: "OK", style: .cancel, handler: nil) alert.addAction(cancelAction) self.present(alert, animated: true, completion: nil) } }
The code in this delegate method dismisses the image picker view and identifies the type of media passed from the image picker controller. If it is an image it is displayed on the view image object of the user interface. If this is a new image it is saved to the camera roll. The didFinishedSavingWithError method is configured to be called when the save operation is complete. If an error occurred it is reported to the user via an alert box.
It is also necessary to implement the imagePickerControllerDidCancel delegate method which is called if the user cancels the image picker session without taking a picture or making an image selection. In most cases all this method needs to do is dismiss the image picker:
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) { self.dismiss(animated: true, completion: nil) }
Seeking Camera and Photo Library Access
Access to both the camera and the photos stored on the device require authorization from the user. This involves the declaration of two usage keys within the project Info.plist file.
Select the Info.plist file, locate the bottom entry in the list of properties and hover the mouse pointer over the item. When the plus button appears, click on it to add a new entry to the list. From within the dropdown list of available keys, locate and select the Privacy – Camera Usage Description option as shown in Figure 92-2:
Figure 92-2
Learn SwiftUI and take your iOS Development to the Next Level |
This app allows you to take photos and store them in the photo library.
Before closing the Info.plist file, now is also a convenient point to add an entry for the NSPhotoLibraryUsageDescription key, since the app will also need access to the photo library in order to search for images. Repeating the above steps, add a new entry for Privacy – Photo Library Usage Description with a suitable description string value. For example:
This app accesses your photo library to search and display photos.
Building and Running the Application
In order to experience the full functionality of this application it will be necessary to install it on a physical iOS device with a camera.
Assuming certificates and provisioning are configured, click on the Xcode run button to launch the application. Once the application loads, select the Camera button to launch the camera interface.
Figure 92-3
Once the picture has been taken and selected for use in the application, it will appear in the image view object of our application user interface.
Selecting the Camera Roll button will provide access to the camera roll and photo stream on the device where an image selection can be made:
Figure 92-4
Learn SwiftUI and take your iOS Development to the Next Level |
Previous | Table of Contents | Next |
Accessing the iOS 10 Camera and Photo Library | iOS 10 Video Playback using AVPlayer and AVPlayerViewController |