In the first ever SwiftCast TV screencast. We will teach you how to build a Camera application that allows you to take a photo, select an existing photo, and view our selected photo. Let’s get started.
Create a new Application by clicking "Create a new Xcode project". When asked to Choose a template for your new project, we are going to select "Single View Application" under iOS/Application. Then click the "Next" button.
You will be prompted to Choose options for your new project. Our applications name is going to be Camera App. So in the field next to the label Product Name: enter, "Camera Application". For Organization Name, I'm going to use com.swiftcast.tv and the same for Organization Identifier. Ensure our Language is set to Swift, Devices is iPhone, and then click Next. You will be prompted to Save your application.
Let's get started by adding our first button to our Application. Click on Main.storyboard. Here we can configure the way our Application looks visually by dropping elements on to it. We are going to be adding a button from the Object library located in the Utilities Pane.
Pro Tip: To toggle the Utilities pane, press CMD + OPTION + 0.
PRO TIP: To select the Object library, press CTRL + OPTION + COMMAND + 3. You can navigate the other libraries by pressing CTRL + OPTION + COMMAND + 1-4
From the Object library we will select a button to add to our View. Scroll down till you see Button or in the search box, type "button". Drag the button on to the view and position it at the top, right of the view. We now want to give our button a meaningful title. Double-click the button and type "Choose Existing Photo". You can also change the title of a button from the Attributes inspector, which is located at the top of the Utilities pane. It is represented by a down arrow.
PRO TIP: To select the Attributes inspector, press OPTION + CMD + 4. You can navigate the other inspectors by using OPTION + CMD + 1-6
We are now going to start programming. From the Project Navigator, select ViewController.swift. This is where we will be putting all the code for our Application. This is not a suggested practice when building real-world applications.
To get started we need to conform from two Protocols. UIImagePickerControllerDelegate and UINavigationControllerDelegate. Do not worry about what a Protocol is, nor what the Delegate means in the class name. We will get to that shortly.
In our code after UIViewController, we need to inherit from our two protocols. To inherit from more than one object, we just need to separate the names with a comma. Let's do that now. Our ViewController class should now look like this.
import UIKit
class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
As stated in the Swift Programming Language Book, “A protocol defines a blueprint of methods, properties, and other requirements that suit a particular task or piece of functionality”.
A Protocol doesn't provide us any implementation, but it describes what the implementation will look like.
As stated in the The Swift Programming Language book, “Delegation is a design pattern that enables a class or structure to hand off (or delegate) some of its responsibilities to an instance of another type”
As you will see our UIViewController will act as the delegate object for UIImagePickerController. When a user picks an image from their Photo Library, our UIImagePickerController instance will then send a message to our UIViewController "imagePickerController:didFinishPickingMediaWithInfo".
UIImagePickerControllerDelegate defines methods that our delegate object must implement to interact with the image picker interface.
UINavigationControllerDelegate defines methods that our delegate object must implement to allow us to modify the behavior when a view controller is pushed or popped from the navigation stack of a UINavigationController object.
UINavigationController comes in to existence when we create an instance of the UIImagePickerController class, as UIImagePickerController inherits UINavigationController.
We need to connect our button to a bit of functionality. At the current moment clicking our button does absolutely nothing. When a user clicks the button we would like to see our existing photos that a user can select.
To accomplish this we will create an IBAction in our UIViewController class that will create an instance of UIImagePickerController, set the delegate to UIViewController, set the sourceType to our photo library, and then display our photo library. We will call this IBAction chooseExisitingPhoto.
Our method will look like the following
func chooseExistingPhoto() {
let picker = UIImagePickerController()
picker.delegate = self
picker.sourceType = .PhotoLibrary
self.presentViewController(picker, animated: true, completion: nil)
}
Now that we have our IBAction, we need to hook it up to our button. Let's navigate back to our Main.storyboard. Then we will right click our "Choose Existing Photo" button, drag to First Responder and select our IBAction method name chooseExistingPhoto. To ensure this is working correctly, let's build and run our application.
When we run our application and click our "Choose Existing Photo" button, we see that it is indeed working as we expected.
Let's go ahead and add the rest of the functionality.
Navigating back to our Main.storyboard, we are going to add our Camera button. We will do exactly as we did before, select a button from the object library, and drag it on to our view. Let's position this at the top left of our view.
Let's now open our UIViewController and add the code to make this function. We will do exactly as we did in our chooseExistingPhoto method, but we will change the sourceType to our camera. Let's call this method chooseFromCamera.
Our method looks like the following.
func chooseFromCamera() {
let picker = UIImagePickerController()
picker.delegate = self
picker.sourceType = .Camera
self.presentViewController(picker, animated: true, completion: nil)
}
We now need to make the connection between this IBAction and our camera button. Navigate back to our Main.storyboard, right click our camera button, drag it to First Responder, and select chooseFromCamera.
We will not be able to test this in the simulator due to it lacking camera functionality. You can plug in your iOS device and run this on your device.
The last bit of functionality we will be building is viewing the image we took with our camera and or selected from our photo library. To do this we will add an ImageView to our View. From the object library drag an Image View to our view. To be able to interact with our new Image View we need to connect it with an IBOutlet. An IBOutlet is a pointer to an object.
Let's navigate back to our UIViewController and after our class definition add the following code.
@IBOutlet var imageView: UIImageView!
Now we need to make the connection between this IBOutlet and our Image View. Let's go back to our Main.storyboard, press ctrl + click on either the View Controller button (the circle with a square in it) or the View Controller text and drag to the Image View. Select our IBOutlet imageView and now the connection is made.
The last step to hooking all of this up is to display the image in our Image View. As we discussed before, when a user selects an image our delegate object will receive the message imagePickerController:didFinishPickingMediaWithInfo, which will give us the object containing our picked image.
To display it, we just need to set the image attribute of our imageView and then close the Image Picker.
This is how our method should look.
func imagePickerController(picker: UIImagePickerController!, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]!) {
imageView.image = info[UIImagePickerControllerOriginalImage] as UIImage
dismissViewControllerAnimated(true, completion: nil)
}
Now when we run our application, after selecting an image from our Photo Library our selected image will display in our Image View.
Here is what our final UIViewController should look like
import UIKit
class ViewController: UIViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
@IBOutlet var imageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
@IBAction func chooseExistingPhoto() {
let picker = UIImagePickerController()
picker.delegate = self
picker.sourceType = .PhotoLibrary
presentViewController(picker, animated: true, completion: nil)
}
@IBAction func chooseFromCamera() {
let picker = UIImagePickerController()
picker.delegate = self
picker.sourceType = .Camera
presentViewController(picker, animated: true, completion: nil)
}
func imagePickerController(picker: UIImagePickerController!, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]!) {
imageView!.image = info[UIImagePickerControllerOriginalImage] as UIImage
dismissViewControllerAnimated(true, completion: nil)
}
}
Challenge: When a user closes the Image Picker without selecting an image, show something silly in the Image View
That wraps it up for our first SwiftCast TV screencast. Thanks for watching.
I was watching the video.
Right at the end, I get an error for
it tells me "Treating a forced downcast to 'UIImage' as optional will never produce 'nil'". Xcode 6 Beta 7 tells me to do one of two things.
"Fix-it - Use 'as?' to perform a conditional downcast to 'UIImage'" "Fix-it - Add parentheses around the cast to silence this warning".
Which should I go for?
I see that your github says I should type in imageView!.image instead of imageView.image. However, that does not seem to affect anything.