An Example iOS 10 iPhone Camera Application

From Techotopia
Revision as of 04:43, 10 November 2016 by Neil (Talk | contribs) (Designing the User Interface)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

PreviousTable of ContentsNext
Accessing the iOS 10 Camera and Photo LibraryiOS 10 Video Playback using AVPlayer and AVPlayerViewController


Learn SwiftUI and take your iOS Development to the Next Level
SwiftUI Essentials – iOS 16 Edition book is now available in Print ($39.99) and eBook ($29.99) editions. Learn more...

Buy Print Preview Book


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.


Contents


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

The next step in this tutorial is to design the user interface. This is a very simple user interface consisting of an image view, a toolbar and two bar button items. Select the Main.storyboard file and drag and drop components from the Object Library (View -> Utilities -> Show Object Library) onto the view. Position and size the components and set the text on the bar button items so that the user interface resembles Figure 92-1.


The user interface for the example iOS camera app

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
SwiftUI Essentials – iOS 16 Edition book is now available in Print ($39.99) and eBook ($29.99) editions. Learn more...

Buy Print Preview Book

Next, select the Image View object and, once again using the Add New Constraints menu, establish Spacing to nearest neighbor constraints on all four sides of the view, this time with the Constrain to margins option enabled.

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
SwiftUI Essentials – iOS 16 Edition book is now available in Print ($39.99) and eBook ($29.99) editions. Learn more...

Buy Print Preview Book

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
SwiftUI Essentials – iOS 16 Edition book is now available in Print ($39.99) and eBook ($29.99) editions. Learn more...

Buy Print Preview Book

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:


Xcode 8 ios 10 camera Access key.png

Figure 92-2

Learn SwiftUI and take your iOS Development to the Next Level
SwiftUI Essentials – iOS 16 Edition book is now available in Print ($39.99) and eBook ($29.99) editions. Learn more...

Buy Print Preview Book

Within the value field for the property, enter a message to display to the user when requesting permission to use the camera. For example:

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.


The iOS 10 Camera example app running

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:

Ios 8 camera roll.png

Figure 92-4


Learn SwiftUI and take your iOS Development to the Next Level
SwiftUI Essentials – iOS 16 Edition book is now available in Print ($39.99) and eBook ($29.99) editions. Learn more...

Buy Print Preview Book



PreviousTable of ContentsNext
Accessing the iOS 10 Camera and Photo LibraryiOS 10 Video Playback using AVPlayer and AVPlayerViewController