How to Pick photos from the Camera or Photo Library and use them in Sprite Kit with Swift 2

How to Pick photos from the Camera or Photo Library and use them in Sprite Kit with Swift 2
September 13, 2015 Justin at CartoonSmart

How to Pick photos from the Camera or Photo Library and use them in Sprite Kit with Swift 2

Learn how program a SpriteKit and Swift 2 based iOS9 app that allows user’s the option to add pictures from their camera or camera roll into their SpriteKit game or app, mask the images, then adjust the layout of the picture within the mask (zoom in / out, move it, rotate, squash and stretch it). The edited masked-image can then appear in ANY other scene throughout the lifespan of the app (Hint; it’s saved as an NSUserDefault).

Prefer reading your lessons? Okay….

To follow along, you should have a Sprite Kit based, Swift 2 project open. We’ll begin by modifying the GameScene.swift file, like so…Camera Roll Picker Swift SpriteKit

Cut and paste version...


import SpriteKit

class GameScene: SKScene, UIImagePickerControllerDelegate, UINavigationControllerDelegate {

Long story short, this bit of delegation makes it so our GameScene class is responsible for doing certain things when image picking occurs. Sometimes with delegation you’re required to include certain blocks of code, sometimes not. So if you get a warning at this point, thats why.

Next up, declare a variable named defaults so we can access the NSUserDefaults a little quicker. This will look no different whether you’re using Swift 1 or Swift 2.

Declare variable for standard NSUserDefaults in Swift 1

 

Cut and paste version...


 var defaults:NSUserDefaults = NSUserDefaults.standardUserDefaults()

Next lets create an extension of the GameScene class. This will keep our code nice and organized, especially since accessing the camera roll / camera to pick photos is probably not directly related to whatever game you are hypothetically creating in the main part of the GameScene class. Creating an extension allows you to write the code in the same class, but not in the same Swift file.

So create a new Swift file, call it something like GameScene_CameraRoll.swift.  Then start by adding the code you see below…

Extending a file with Swift

 

Cut and paste version...


import Foundation
import SpriteKit

extension GameScene {

}

Now lets get down to actually opening the Camera Roll or take a photo with the Camera. Back in your main GameScene.swift file add the highlighted line someplace it will run. The didMoveToView statement is fine, or you could include it in your touchesBegan function…

Get Photo from Camera Roll with SpriteKit

Cut and paste version...


getPhotoFromSource(UIImagePickerControllerSourceType.PhotoLibrary)

Obviously, we still need to write the getPhotoFromSource function but take a second to look at the value we are passing in….

UIImagePickerControllerSourceType.PhotoLibrary

…this is an enum type variable specifying the source type to use when picking an image. Your three options are .PhotoLibrary, .Camera, and .SavedPhotosAlbum. Keep in mind, if you are testing on the Simulator the .Camera option is not available to test with.

So let’s write that function…

UIImagePickerControllerSourceType function

Cut and paste version...


func getPhotoFromSource(source:UIImagePickerControllerSourceType ){

if UIImagePickerController.isSourceTypeAvailable(source)
{

let imagePicker = UIImagePickerController()
imagePicker.modalPresentationStyle = .CurrentContext
imagePicker.delegate = self
imagePicker.sourceType = source
imagePicker.allowsEditing = false

if (source == .Camera){
imagePicker.cameraDevice = .Front
}

let vc:UIViewController = self.view!.window!.rootViewController!
vc.presentViewController(imagePicker, animated: true, completion: nil)

} }

You can watch the video tutorials for details on each line above, but briefly, the if statement in the function is checking if the source is available (for example, if you try to open the Camera on the Simulator, the else statement would run). If the source is available, we will create the imagePicker variable with a few options.  In particular, the interior if statement is checking to see if the source is the Camera and if so, it defaults to the front facing camera (assuming you want the user to take a picture of themselves). We’re also specifying that the delegate will be self. Remember how we did that delegation earlier, this is why.

And finally, focus on these two lines…

how to present modal view in spritekit scene

This is an important couple of lines for SpriteKit developers because it shows you how to present a modal view from a SpriteKit scene in Swift. A modal view basically just replaces the current view (with an animation sliding upwards) but maintains a connection to the original view (that ol’ delegate). So in the code above we are getting the rootViewController from our SpriteKit view then presenting the new view which is our imagePicker.

If you test the app now, tapping the screen will prompt you to allow access to the camera roll, and if you allow it, you’ll see the Simulator’s default images (or on your device, you’ll see your own images). By the way, if you want to add an image to the Simulator’s camera roll, simply drag any image into the Simulator.

Next up, lets add a function to handle the view being cancelled (meaning, the user decided not to pick a photo). Keep in mind, as soon as you start typing this function, you’ll notice Xcode will complete it. This is a standard function for handling a UIImagePickerController being cancelled.

imagePickerControllerDidCancel

Cut and paste version...


func imagePickerControllerDidCancel(picker: UIImagePickerController) {

picker.dismissViewControllerAnimated(true, completion: nil)
picker.delegate = nil

}

Got it? There’s not much there. We are simply dismissing the view and specifying that the delegate is nil (no longer self). We’ll do the same thing at the end of the next function, which handles what to do if we actually pick a photo.

Here goes…

Swift code for using the image data from CameraRoll

Cut and paste version...


func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {

if (picker.sourceType == UIImagePickerControllerSourceType.PhotoLibrary || picker.sourceType == UIImagePickerControllerSourceType.Camera ) {

//do something with the image we picked

if let cameraRollPicture = info[UIImagePickerControllerOriginalImage] as? UIImage {

defaults.setObject( UIImagePNGRepresentation(cameraRollPicture), forKey:”CameraRollPicture”)

}

}

picker.dismissViewControllerAnimated(true, completion: nil)
picker.delegate = nil

}

Again, we talk about this a lot more in the videos, but here’s the “highlights reel”…

Like the imagePickerControllerDidCancel the function is called automatically, and is standard fare for what happens after an image is selected or taken.

The if statement isn’t all that useful here, but perhaps for your app you might want to check if the source was a particular type (Camera, PhotoLibrary or SavedPhotosAlbum).

The important part begins with the if let cameraRollPicture… block. Basically we are checking to see if what was picked is a UIImage, and if so we save it to the defaults as a UIImagePNGRepresentation with a key of “CameraRollPicture”. Now the image data can be retrieved again and again, as long as the user does not delete the app. So even if the app closes completely, the data is still safe and sound in the NSUserDefaults.

We can access the image data from anywhere else in the app like so…

Reveal Image Picked From Camera Roll in SpriteKit

Cut and paste version...


func revealImage() {

if let imageDataAsDefaults:NSData = defaults.objectForKey(“CameraRollPicture”) as? NSData {

let someImage:UIImage = UIImage(data: imageDataAsDefaults)!

//check to see if there’s a placeholder namedCameraRollPlaceholder…
if let placeholder:SKSpriteNode = self.childNodeWithName(“CameraRollPlaceholder”) as? SKSpriteNode {

// create an SKTexture with UIImage…
let tex:SKTexture = SKTexture(image:someImage)

// add a new SKSpriteNode…
let newImage:SKSpriteNode = SKSpriteNode(texture: tex)
newImage.size = placeholder.size
newImage.zPosition = placeholder.zPosition
newImage.position = placeholder.position
self.addChild(newImage)

}
}
}

The first thing we do in this function is check to see if we can get NSData out of the defaults with an object key of “CameraRollPicture”. If the data is available, that obviously means someone had previously saved an image, and we can proceed. We then create a UIImage named someImage, from the image data stored in the defaults.

The rest of the function checks to see if there’s an SKSpriteNode already in the scene named  “CameraRollPlaceholder”. This could be any SKSpriteNode even just a simple color sprite with the alpha turned all the way down to zero. If one exists, we create an SKTexture from the UIImage, then create a new SKSpriteNode with the texture, and use some of the same properties as the placeholder for size, position, and z depth.

Add a placeholder in an SKScene

Obviously you could add the saved image to scene without a placeholder, but the placeholder can really fine tune where the image is added and sized, with very little work.

Mind you in our project so far, we haven’t actually called the revealImage function anywhere, so lets do that back in our function to handle what to do after picking the image. Just add the circled line below…

Reveal Image Picked From Camera Roll in SpriteKit 2

You could call revealImage() from anywhere anytime though.

Reveal image from Camera roll with Swift2 and SpriteKit

Want ALOT more???

Watch the video tutorials above and you’ll see how to mask the image using SKCropNode, and make adjustments within the mask to the position, size and zoom to really fine tune it.  And if you’re a CartoonSmart subscriber, you can watch every video tutorial here on the site, and download the image source project below.

This content is restricted to buyers of The CartoonSmart Subscription.

This same code is already part of our Story Tellers iOS Starter Kit 2. So if you have an interest in creating an iOS9 Children’s Book App, without ever writing code, this is the kit for you!

Never lose your place.

Sign up for the newsletter to get a free CartoonSmart account and track your progress in every course.

I'm cool. Sign me up!