Quantcast
Channel: Kodeco | High quality programming tutorials: iOS, Android, Swift, Kotlin, Unity, and more
Viewing all 4370 articles
Browse latest View live

Sprite Kit for Kids with Swift

$
0
0

Hi! My name is Ajay, and I am a 13 year old iOS developer.

I enjoy making iOS games using Sprite Kit, Apple’s 2D game programming framework. I know a lot of kids are interested in learning how to do this too, so I thought I’d make this tutorial!

In this tutorial, I’ll show you how to make a simple game called Space Monkey. It will teach you the basics of making your own iPhone game, and hopefully get you excited ’bout learning more.

So strap on your jet boosters, and let’s get started!

Note: This tutorial assumes you know the basics of programming with Swift. If you are new to Swift, check out our book the iOS Apprentice or check out our video tutorials on Swift.

Getting Started

The first thing you need to do is to install Xcode – Apple’s free tool for developing iOS and Mac apps.

If you don’t have Xcode installed already, download it from the App Store. If you already have Xcode, make sure you have the latest version installed (Xcode 6 at the time of writing this tutorial).

Xcode

Once you have Xcode installed, download this starter project, unzip it, and double click SpaceMonkey.xcodeproj.

This will open the project in Xcode. Click the Play button to see what you’ve got so far:

SpaceMonkeyStarter

You will see a blank black screen:

LandscapeBlank

This starter project is a nice blank slate for you to start working on your game. I’ve already pre-included some art and sounds for you in the project, which you can find in the Sounds and sprites.atlas folders.

Let’s put that art to good use – starting with the space monkey!

Adding your Monkey

In Sprite Kit, to add an image (like the space monkey) to the game, you need to do three things:

  1. Create the sprite. A sprite is a copy of an image that you can move around in your game. Your first step is to create one of these, using the SKSpriteNode class.
  2. Position the sprite. The second thing you need to do is set the position of your sprite somewhere on the screen. In this game, you want the space monkey to start to the left hand side of the screen, toward the middle.
  3. Add the sprite to the scene. Creating the sprite isn’t enough – to display the sprite, you need to add it to the scene.

Let’s try this out step by step. Open GameScene.swift and replace the contents with the following code:

import SpriteKit
 
class GameScene: SKScene {
 
  // 1 - Create the sprite
  let player = SKSpriteNode(imageNamed:"spacemonkey_fly02")
 
  override func didMoveToView(view: SKView) {
 
    // 2 - Position the sprite
    player.position = CGPoint(x:frame.size.width * 0.1, y: frame.size.height * 0.5)
    // 3 - Add the sprite to the scene
    addChild(player)
 
    // 4 - Set scene background color to black
    backgroundColor = SKColor.blackColor()
  }
 
}

Let’s go over this code step by step.

  1. Create your SKSpriteNode with the monkey image given in the Art Folder, using SKSpriteNode(imageNamed:). Note you are storing the sprite in a property on the class, so you can refer to it later.
  2. didMoveToView(_:) is called when your scene is first presented, so it’s a good place to add initial setup code. Here you set your sprite’s position near the left hand side of the screen.
  3. Add the sprite to the scene by calling addChild() with the name of your sprite.
  4. Set the scene’s background color to black, to give a sense that the monkey is flying in space.

Build and run, and see your space monkey flying on the screen:

SpaceMonkeyOnScreen

Time to add some enemies!

Adding your Enemies!

Enemies will work a bit differently because you need more than one and you need them to spawn in different areas of the screen.

First, you’ll need some methods to create some random numbers. Add these new methods to GameScene.swift, right after didMoveToView(_:) (but before the final curly brace):

func random() -> CGFloat {
  return CGFloat(Float(arc4random()) / 0xFFFFFFFF)
}
 
func random(#min: CGFloat, max: CGFloat) -> CGFloat {
  return random() * (max - min) + min
}

random() returns a random decimal value between 0 and 1. random(min:max:) returns a random number within a specified range. For this tutorial, you don’t need to understand how these work; you can just use them as helper methods.

Next, add this new method right after random(min:max:):

// 1
func spawnEnemy() {
  // 2
  let enemy = SKSpriteNode(imageNamed: "boss_ship")
  // 3
  enemy.name = "enemy"
  // 4
  enemy.position = CGPoint(x: frame.size.width, y: frame.size.height * random(min: 0, max: 1))
  // 5
  addChild(enemy)
}

Let’s go over this line by line:

  1. Here you create a method named spawnEnemy().
  2. Here you create a sprite like you did before when you added the monkey, by calling SKSpriteNode(imageNamed:) and adding the image name of the image.
  3. Here you add a name to the sprite – this will make it easy to find the sprite by name later on.
  4. Here you set the enemies X position to the right of the screen, but the Y position to a random value using random().
  5. Lastly you just add the sprite to the parent/scene using addChild().

Now all you need to do is call this method a bunch of times! To do this, you will create a sequence of actions to make the enemies spawn periodically over time.

Add these lines to the end of didMoveToView(_:):

runAction(SKAction.repeatActionForever(
  SKAction.sequence([
    SKAction.runBlock(spawnEnemy),
    SKAction.waitForDuration(1.0)])))

Here you create an action with a sequence which repeats itself over and over. The sequence consists of calling spawnEnemy() and a wait duration of 1 second. This makes an enemy spawns every second.

At this point, your file should look like this (with the comments deleted):

import SpriteKit
 
class GameScene: SKScene {
 
  let player = SKSpriteNode(imageNamed:"spacemonkey_fly02")
 
  override func didMoveToView(view: SKView) {
 
    player.position = CGPoint(x:frame.size.width * 0.1, y: frame.size.height * 0.5)
    addChild(player)
    backgroundColor = SKColor.blackColor()
 
    runAction(SKAction.repeatActionForever(
      SKAction.sequence([
        SKAction.runBlock(spawnEnemy),
        SKAction.waitForDuration(1.0)])))
  }
 
  func random() -> CGFloat {
    return CGFloat(Float(arc4random()) / 0xFFFFFFFF)
  }
 
  func random(#min: CGFloat, max: CGFloat) -> CGFloat {
    return random() * (max - min) + min
  }
 
  func spawnEnemy() {
    let enemy = SKSpriteNode(imageNamed: "boss_ship")
    enemy.name = "enemy"
    enemy.position = CGPoint(x: frame.size.width, y: frame.size.height * random(min: 0, max: 1))
    addChild(enemy)
  }
 
}

Build and run your app. You should start seeing enemies appear on the right hand side at random spots:

iOS Simulator Screen Shot Feb 25, 2015, 12.36.33 PM

Now let’s make them move!

Making your Enemies Move

First, let’s tweak the enemies so when they spawn they are fully offscreen (rather than being halfway visible on the screen). This will make the player not realize they’re popping in from nowhere!

To fix this, update the line in spawnEnemy() that sets the enemy sprite’s position to the following:

enemy.position = CGPoint(x: frame.size.width + enemy.size.width/2, 
  y: frame.size.height * random(min: 0, max: 1))

Now, let’s make your game a bit more interesting by making your enemies move from one side of your screen to the other by using more actions.

Add this line to the end of spawnEnemy():

enemy.runAction(
  SKAction.moveByX(-size.width - enemy.size.width, y: 0.0, 
    duration: NSTimeInterval(random(min: 1, max: 2))))

Let me explain this code to you :

  1. It runs an SKAction on the enemy sprite.
  2. This SKAction contains a moveByX() method which tells the enemy to move on the X axis by a certain amount. Here you set it to move the entire length of the screen to the left (-size.width) and also the full length of the sprite (-enemy.size.width).
  3. The SKAction has a duration parameter which indicates how long it should take for the sprite to move that amount. Here, you set it to move a random value between 1-2 seconds, so some enemies will be faster than others.

Build and run your app to see if the enemies are moving to the end of your screen and disappearing completely. It should look something like this:

Screen Shot 2015-03-02 at 10.38.34 pm

Now you need to make your player move with physics!

Moving Sprites with Physics

In this game, you are going to make it so that the monkey falls to the bottom of the screen, unless you tap the screen – in which case the monkey will jump up.

You could do this by moving the monkey with a SKAction, just like you did for the enemies, but it’s easier to let Sprite Kit’s built-in physics engine move the monkey instead.

Let’s try this out. Still in GameScene.swift, and add the following code to the end of didMoveToView(_:):

player.physicsBody = SKPhysicsBody(circleOfRadius:player.frame.size.width * 0.3)
player.physicsBody?.allowsRotation = false

The first line creates a physics body for the monkey. This tells the physics engine to start controlling the monkey’s movement, making him “fall” over time according to gravity and other forces.

Note the shape of the physics body is a circle, that roughly matches up to the monkey. You don’t need physics shapes to match exactly, just whatever works for your game. You also specify that the physics body shouldn’t rotate.

Build and run, and watch as your monkey falls down and off the screen. Cool, huh?

Demo of dragging art directly into Scene

Physics Impulses

It’s no fair if the monkey falls right off the screen, so you’re going to use physics to make the monkey jump.

To do this, add this new method after spawnEnemy():

func jumpPlayer() {
  // 1
  let impulse =  CGVector(dx: 0, dy: 75)
  // 2
  player.physicsBody?.applyImpulse(impulse)
}

Let’s go over this line by line:

  1. First you need to specify the amount to make the monkey jump, by creating a CGVector with an impulse amount. I came up with these values by trial and error.
  2. Then you use applyImpulse(), passing in the impulse you provided earlier. This will convert the impulse into both linear and angular velocity so it will move through space and also rotate, that’s why you locked the rotation earlier.

This code has not been called yet so you cannot make your player jump yet. To actually make your player jump you need to override a method that is called when the player taps the screen. Copy this code under jumpPlayer():

override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
  jumpPlayer()
}

This simply calls the method you wrote whenever the user taps.

Almost done – add this code to the end of didMoveToView(_:):

// 1
let collisionFrame = CGRectInset(frame, 0, -self.size.height * 0.2)
// 2
physicsBody = SKPhysicsBody(edgeLoopFromRect: collisionFrame)

This code creates a special physics body on the edge of the screen so the monkey doesn’t fly or fall of into space. Let’s review this line by line:

  1. First you create a rectangle that specifies the bounds of the monkey’s movement. CGRectInset() allows you to grow or shrink a rectangle; you use it to grow the frame of the screen by 20% above and below the area, to let the monkey go slightly offscreen but not a crazy amount.
  2. You then set the physics body of the scene itself. Last time you created a physics body that was a circle shape; here you make it an edge loop, which is a fancy way of saying “the edges of a rectangle”.

Build and run your project, and you should see the following:

Demo of dragging art directly into Scene

Holy bouncing monkey!

Collision Detection

Now you can jump to avoid enemies… but if you crash into them, nothing happens.

You need to add collision detection into your game. To do this, here’s what you need to do:

  1. Create a physics body for each sprite: Right now, you’ve created a physics body for your space monkey, but you haven’t created one for the enemies – so you’ll need to create physics bodies for them too.
  2. Set category and contacts for each physics body: Next you need to set a category on each physics body, which tells Sprite Kit which group the sprite is in. This way, you can have one category for the player and one category for the enemy. You can also configure your physics body to register “contacts” with certain other groups of physics bodies.
  3. Set Contact Delegate: Using the Contact Delegate you can set a contact delegate on the world to be told when two physics bodies contact with each other. Then you find out which category the physics body is in, and if it is the Enemy and the Monkey. Game Over!

Remember how you added the physics body to your monkey? Well now you need to add it to your enemy sprite so they can actually collide.

Start by adding this enumeration to the very top of GameScene.swift.

enum BodyType: UInt32 {
  case player = 1
  case enemy = 2
  case ground = 4
}

All you do here is create categories for each sprite. The ground number is not for a sprite but is instead for the frame of the app so if the monkey collides with the frame it bounces of the frame so the monkey will not keep falling!

Note: Note how each number you add to this list is the previous number, multiplied by 2. The reasoning for this is beyond the scope of this tutorial, but if you want to learn more, check out this video tutorial on bitmasks.

Next, mark GameScene as implementing the SKPhysicsContactDelegate protocol:

class GameScene: SKScene, SKPhysicsContactDelegate {

You can think of a protocol as a promise that your class will implement certain methods. Here you’re promising that you’ll be implementing a method that handles when two physics bodies contact each other.

After this make the contactDelegate of the physics world equal to self. Add this code to the end of didMoveToView(_:):

physicsWorld.contactDelegate = self

This tells the physics world to call a method on your class when two physics bodies contact each other (the one you will write soon).

Now add this code to the end of spawnEnemy():

// 1
enemy.physicsBody = SKPhysicsBody(circleOfRadius: enemy.size.width/4)
// 2
enemy.physicsBody?.dynamic = false
// 3
enemy.physicsBody?.affectedByGravity = false
// 4
enemy.physicsBody?.allowsRotation = false
// 5
enemy.physicsBody?.categoryBitMask = BodyType.enemy.rawValue
// 6
enemy.physicsBody?.contactTestBitMask = BodyType.player.rawValue
// 7
enemy.physicsBody?.collisionBitMask = 0

Let me explain this code a little.

  1. Creates a physics body for the enemy. Physics bodies don’t have to be an exact match to the shape of the sprite; just an estimate. Here you use a circle shape, setting the radius to 1/4’s of the sprite’s width to make the collision a bit forgiving.
  2. Turns dynamic off. This allows the physics to control the sprite.
  3. Stops sprite from being affected by gravity. This is self explanatory, basically the enemy sprite will not be affected by gravity produced by the physics.
  4. Stops sprite from rotating. This code will stop the object from rotating when collided by other physics bodies.
  5. Sets the category bit mask to be the enemy category you defined earlier.
  6. This instructs Sprite Kit to notify you when an enemy contacts a player.
  7. The collisionBitMask means, if you for example set the collisionBitMask to the player, the player and the enemy will bounce of each other. You don’t want anything to bounce of anything so you set it to 0.

Now add this to the end of didMoveToView(_:):

physicsBody?.categoryBitMask = BodyType.ground.rawValue
 
player.physicsBody?.categoryBitMask = BodyType.player.rawValue
player.physicsBody?.contactTestBitMask = BodyType.enemy.rawValue
player.physicsBody?.collisionBitMask = BodyType.ground.rawValue

This sets up the categories and collision bit masks for the player and ground so they collide with each other, and sets the player to register a “contact” with enemies.

Now for the most important part. Actually doing something about the collision. For this, you need to implement the method you “promised” to implement earlier to handle contacts:

func didBeginContact(contact: SKPhysicsContact) {
  let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask
  switch(contactMask) {
  case BodyType.player.rawValue | BodyType.enemy.rawValue:
    let secondNode = contact.bodyB.node
    secondNode?.removeFromParent()
    let firstNode = contact.bodyA.node
    firstNode?.removeFromParent()
  default:
    return
  }
}

Since you set the scene as the contactDelegate of the physics world earlier, this method will be called whenever two physics bodies collide.

This method combines the two bitmasks into a single contact mask, and checks to see if they are the combination of the player and the enemy. If so, it removes the player and the enemy from the scene.

Build and run, and you’ll see the following:

Demo of dragging art directly into Scene

That is AWESOME!!!

In the next section you have to quite a lot of work, you have to change basically everything. Well thats going to be fun. You will mainly add a game over screen.

Game Over!

In this section you will display a game over Screen to the player when your player either collides with an enemy or falls out of the screen. You will also create a start screen where the user is instructed to Touch the screen to begin! :]

Start by adding all these variables to the top of GameScene, right after the line let player = SKSpriteNode(imageNamed:"spacemonkey_fly02"):

// 1
var gameOver = false
// 2
let endLabel = SKLabelNode(text: "Game Over")
let endLabel2 = SKLabelNode(text: "Tap to restart!")
let touchToBeginLabel = SKLabelNode(text: "Touch to begin!")
let points = SKLabelNode(text: "0")
// 3
var numPoints = 0
// 4
let explosionSound = SKAction.playSoundFileNamed("explosion.mp3", waitForCompletion: true)
let coinSound = SKAction.playSoundFileNamed("coin.wav", waitForCompletion: false)

Let’s review this section by section:

  1. First you create a bool called gameOver to keep track whether the game is over or not.
  2. Next you create a few label nodes, which is how you display text to the screen in Sprite Kit.
  3. Next you create an integer to store the amount of points you have. Note you mark this with var, not let, because you want to be able to change the value after creating it.
  4. Last you create some actions you will use later to play some sound effects.

Next create a new method called setupLabels() :

func setupLabels() {
  // 1
  touchToBeginLabel.position = CGPoint(x: frame.size.width/2, y: frame.size.height/2)
  touchToBeginLabel.fontColor = UIColor.whiteColor()
  touchToBeginLabel.fontSize = 50
  addChild(touchToBeginLabel)
 
  // 2  
  points.position = CGPoint(x: frame.size.width/2, y: frame.size.height * 0.1)
  points.fontColor = UIColor.whiteColor()
  points.fontSize = 100
  addChild(points)
}

Let’s review this section by section:

  1. You position the “touch to begin” label to the center of the screen, with a white color, and 50pt font size.
  2. You set the position label toward the bottom of the screen, with a white color and a font size of 100.

Now call the setupLabels() in didMoveToView(_:):

setupLabels()

Now delete touchesBegan(_:withEvent:) and replace it with this :

override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
  // 1
  if (!gameOver) {
    if player.physicsBody?.dynamic == false {
      player.physicsBody?.dynamic = true
      touchToBeginLabel.hidden = true
      backgroundColor = SKColor.blackColor()
 
      runAction(SKAction.repeatActionForever(
        SKAction.sequence([
          SKAction.runBlock(spawnEnemy),
          SKAction.waitForDuration(1.0)])))
    }
    // 2
    jumpPlayer()
 
  }
  // 3
  else if (gameOver) {
    let newScene = GameScene(size: size)
    newScene.scaleMode = scaleMode
    let reveal = SKTransition.flipHorizontalWithDuration(0.5)
    view?.presentScene(newScene, transition: reveal)
  }
}

Let’s review this section by section:

  1. If the game isn’t over, and the player isn’t dynamic (i.e. moved by the physics engine) yet, then that means the game hasn’t started yet. So you set dynamic to true, hide the label, and begin spawning enemies.
  2. You call the jumpPlayer anyway because it will only work if dynamic is set to true.
  3. If the game is over, you start the game over by creating a new instance of your GameScene and presenting that new scene..

Next, add this new method to your class:

override func update(currentTime: CFTimeInterval) {
  //1
  if !gameOver {
    //2
    if player.position.y <= 0 {
      endGame()
    }
    //3
    enumerateChildNodesWithName("enemy") {
      enemy, _ in
      //4
      if enemy.position.x <= 0 {
        //5
        self.updateEnemy(enemy)
      }
    }
  }
}

Let’s review this section by section:

  1. You check if gameOver is false and if it is then you check if the player is out of the screen, if the player is out of the screen it calls endGame which you will add later.
  2. Your tell enumerateChildNodesWithName to find every single child in the scene with the name of “enemy”. For each enemy, you check if any of the enemies position is out of the screen and if it is, it calls updateEnemy() which you will also add later.

Now you will add the method called updateEnemy(). This which will be called before every frame is rendered so if any enemy leave the screen you can give a point to the user:

func updateEnemy(enemy: SKNode) {
  //1
  if enemy.position.x < 0 {
    //2
    enemy.removeFromParent()  
    //3
    runAction(coinSound)
    //4
    numPoints++
    //5
    points.text = "\(numPoints)"  
  }
}

Let’s review this line by line:

  1. Checks if the enemy position is out of the screen in x axis.
  2. If it is, it removes the enemy from the parent (removes the enemy from the game).
  3. Adds a point to the numPoints which holds the amount of points you have.
  4. Converts points into a string and inserts that string into the points label.

Now you have to change didBeginContact(_:) a little bit. Add this line of code after you remove the first node from parent:

endGame()

Now for the part you have all been waiting for – the endGame method:

func endGame() {
  // 1
  gameOver = true
  // 2
  removeAllActions()
  // 3
  runAction(explosionSound)
 
  // 4
  endLabel.position = CGPoint(x: frame.size.width/2, y: frame.size.height/2)
  endLabel.fontColor = UIColor.whiteColor()
  endLabel.fontSize = 50
  endLabel2.position = CGPoint(x: frame.size.width/2, y: frame.size.height/2 + endLabel.fontSize)
  endLabel2.fontColor = UIColor.whiteColor()
  endLabel2.fontSize = 20
  points.fontColor = UIColor.whiteColor()
  addChild(endLabel)
  addChild(endLabel2)
}

Let’s review this section by section:

  1. You set gameOver to true.
  2. You remove all actions in the scene, to stop any further animation.
  3. Runs the explosion sound.
  4. Position and adds the endLabels to the scene.

Now go to didMoveToView(_:) and remove this block of code :

backgroundColor = SKColor.blackColor()
 
runAction(SKAction.repeatActionForever(
  SKAction.sequence([
    SKAction.runBlock(spawnEnemy),
    SKAction.waitForDuration(1.0)])))

Finally add this line in its place:

player.physicsBody?.dynamic = false

This sets the player so he doesn’t move at the start of the game until you tap.

Build and run, and you have a completely playable game!

OMG – that’s your game done, good job! :D

Gratuitous Background Music

But wait, there’s one more thing!

Open ViewController.swift and add this new property:

var backgroundMusicPlayer: AVAudioPlayer!

Also add this new method:

func playBackgroundMusic(filename: String) {
  let url = NSBundle.mainBundle().URLForResource(
    filename, withExtension: nil)
  if (url == nil) {
    println("Could not find file: \(filename)")
    return
  }
 
  var error: NSError? = nil
  backgroundMusicPlayer =
    AVAudioPlayer(contentsOfURL: url, error: &error)
  if backgroundMusicPlayer == nil {
    println("Could not create audio player: \(error!)")
    return
  }
 
  backgroundMusicPlayer.numberOfLoops = -1
  backgroundMusicPlayer.prepareToPlay()
  backgroundMusicPlayer.play()
}

This is a handy helper method to play some background music – you don’t need ot know how it works for this tutorial.

Using it is simple. Add this line the viewWillLayoutSubviews(), right after the line skView.presentScene(scene):

playBackgroundMusic("BackgroundMusic.mp3")

Build and run, and enjoy your awesome music made by yours truly… aww yeah!

Where To Go From Here?

Here is the final example project that you created in this tutorial.

Congratulations, you have made your own game! From here, feel free to modify it however you’d like.

If you want to learn more about Sprite Kit, check out some of our other Sprite Kit Tutorials, or check out our book iOS Games by Tutorials.

Happy gaming! :]

Sprite Kit for Kids with Swift is a post from: Ray Wenderlich

The post Sprite Kit for Kids with Swift appeared first on Ray Wenderlich.


React Native with Nick Lockwood – Podcast S04 E02

$
0
0
Find out what the buzz is about React Native!

Find out what the buzz is about React Native!

Welcome back to season 4 of the raywenderlich.com podcast!

In this episode, we are joined by special guest Nick Lockwood to talk about React Native, Facebook’s new framework that lets you build native iOS applications with JavaScript.

[Subscribe in iTunes] [RSS Feed]

Our Sponsor

  • Wired In: Wireless Productivity Sign With Arduino & HomeKit.

Interested in sponsoring a podcast episode? We sell ads via Syndicate Ads, check it out!

Links

Contact Us

Where To Go From Here?

We hope you enjoyed this episode of our podcast. Be sure to subscribe in iTunes to get notified when the next episode comes out.

We’d love to hear what you think about the podcast, and any suggestions on what you’d like to hear next season. Feel free to drop a comment here, or email us anytime at podcast@raywenderlich.com.

React Native with Nick Lockwood – Podcast S04 E02 is a post from: Ray Wenderlich

The post React Native with Nick Lockwood – Podcast S04 E02 appeared first on Ray Wenderlich.

Video Tutorial: Unity Basics Part 2: GameObjects and Prefabs

Video Tutorial: Unity Basics Part 3: Introduction to Scripting

Arduino Tutorial: Networked Temperature Sensor with Swift

$
0
0
Monitor the temperature around you from your iPhone!

Monitor the temperature around you from your iPhone!

Update note: Team member Tony Dahbura has updated this tutorial for iOS 8 and Swift! If you already built the circuit from the previous tutorial, you can skip ahead to the Swift portion of this tutorial.

If you’re like me, you wonder whether you should wear a jacket before heading outside. You might not have time to check outside your front door, but you always have time to check your iPhone! :]

The problem is, most weather apps tell you about the temperature in a nearby city or suburb – but not necessarily about local conditions. And what about that aquarium you would like to monitor, or your mini indoor greenhouse?

This is a job for the latest open source microcontroller – the Arduino.

In this tutorial, you’ll build a networked temperature-monitoring station with multiple temperature probes you can place in different locations. To tie it all together, you’ll also build the companion iPhone app to check the readings.

This tutorial assumes you have been through some of the earlier tutorials on the Arduino. If not, you may want to check out our beginner Electronics for iPhone Developers tutorial series before starting.

Getting Started

First things first, download the starter project and components for this tutorial from here. The zip file includes various libraries you’ll need and a starter iPhone Swift project for later.

This tutorial requires some specific hardware components to interface with the temperature probes. You’ll be making use of a microcontroller (the Arduino), an Ethernet interface, and connecting status and temperature probes. If you’ve completed other Arduino tutorials on the site, you should have some of these parts – and as a budding electronics hobbyist, now is your chance to begin a collection of reusable modules!

Buildallthethings

The full parts list of required components is below, with URLs to purchase them. The total cost of all the parts is approximately $160 USD. If this seems like a lot of money, remember that you are stocking yourself with plenty of components that you can tinker with beyond this tutorial. If you’ve done previous tutorials, then you already have an Inventor’s Kit and maybe the Ethernet Shield, which drops the total price to $38.00.

For the cheaper components, it makes sense to order a few extra to have around and use for other projects.

Parts List

Once you’ve gathered your parts together, it’s time to get started!

Installing the Arduino IDE

You need to install the Arduino Integrated Development Environment if you haven’t already. The IDE is available at http://arduino.cc/en/main/software. Download the appropriate version for your platform, Mac OS X of course!

Note:There is a version of the IDE for OS X that supports JDK 1.6 and an experimental version for Java 7+. I recommend using the experimental version for Java 7+.

Install the IDE by unzipping the file and placing it in your Applications folder. The IDE does require Java, so if you don’t have Java installed, open a Terminal window and type java -version to have your Mac prompt to install the language. At the prompt click the More Info… button and you will be taken to the Java download site. Download the JDK download button and select the version for Mac OS X x64. Download the latest JDK and install it.

javainstall

A couple of seconds later, you’ll see a dialog on your screen asking if you want to download and install Java. Click the Install button.

A Little Electronics Theory

Your project will make use of Arduino shields. Shields are special boards you can purchase that support a specific function, analogous to classes when building a program.

The Grove Shield brings a bunch of connectors to the board, allowing you to plug in many different sensors using one common connector.

groveshield

Alternatively, you could wire your sensors directly to the breadboard, but these connectors ensure you don’t plug the wrong wires into the wrong pins and keep things looking neat. Seeed Studio makes many other Grove connectors that you can try out once you get the hang of working with the Arduino.

Your temperature probe uses a technology called 1-Wire bus. This technology is a bus system originally designed by Dallas Semiconductor that allows multiple devices to reside on a single data pin. The bus has a single master – the Arduino – and various workers that each sit on the bus and are identified by their own unique 64-bit serial number.

Using 1-Wire bus, each digital pin can support up to 255 devices! For more on 1-Wire bus, see this wiki page.

Relax – there is a library to handle all the timing for you!

HardwareYes

OK, enough theory! Let’s get back to building your temperature-monitoring station.

Installing the Libraries

While you’re waiting for all packages to arrive in the mail, you can install the various libraries you’ll need to talk to the shields. The Arduino IDE already includes the libraries for communicating with the Ethernet Shield.

The temperature sensors need a library for the 1-Wire portion, and Dallas Semiconductor has some useful routines specifically for the probes. These libraries are all in the tutorial download in the folder Arduino_Libraries.

To install the libraries, first find the Arduino_Libraries folder in the resources you downloaded earlier and double click both files to unzip them into folders:

Unzipping files

Then select the icon for the SDK and Show Package Contents. The window will display a folder called Contents. Install the DallasTemperature and OneWire folders in the Contents/Java/libraries folder, as shown:

arduino_libraryinstalled

If you had the Arduino IDE open, Quit and restart to have it load the new libraries. That’s it! Check to see if they’ve loaded successfully by going to File/Examples and looking for DallasTemperature and OneWire in the menu.

arduino_menu_sdk

Now it’s time to do some wiring!

Wiring It All Together

First, if you haven’t already, assemble the Arduino UNO and breadboard based on instructions that come from Sparkfun.

Next, look on the bottom of the Ethernet board for the MAC address and write it down, you’ll need to include it in the code you write to control the interface.

ethernetshield_mac

Then plug the Ethernet Shield into the header pins on the Arduino board. Note that there are six pins on the back of the Ethernet Shield that also connect to the UNO board. Slide the board into place carefully and the Ethernet jack should be above the USB connector.

Installing the Grove Shield

You might have initially thought about plugging the Grove Shield in first, then placing the Ethernet Shield on top of that. Unfortunately, this won’t work due to the Grove Shield not passing the 6 pins on the back through to the front.

This brings up an important point regarding Arduino shields: they are not built identically. Many times you need to come up with creative ways to mix and match different shields. The stackable headers lift the boards far enough apart to avoid shorting pins.

Insert the four stackable headers into the header pins on the Ethernet Shield. You need these because the Ethernet Shield’s RJ45 connector is large enough to short out the headers on the Grove Shield (basically, an electric charge might flow from the metal of the RJ45 connector to the Grove Shield, causing major problems!)

Each header matches the pin counts on one of the Ethernet Shield’s headers. When you’re done, your board should look like this:

stackableheadersinstalled

Carefully place the Grove Shield board in place onto the stackable headers without bending or missing any pins. The Grove Shield has only six pins going into the right and left headers, which have eight on the Ethernet Shield. Align the back pins away from the RJ45 connector and don’t worry about the two missing pins.

After installation, the Grove Shield should look like this:

groveshieldsideviewarrows

Note the two missing pins on the side facing you (indicated by the arrows) and on the opposite side. All other pins should be seated inside of the headers.

Now you will wire in the LED as a status indicator. Besides, what’s an electronics project without some blinking LEDs? :]

  1. Connect a blue wire to one of the connectors in the blue row on the breadboard.
  2. Connect an orange wire to row J, column 16 on your breadboard.
  3. Connect a 330-ohm resistor (orange/orange/brown) to row J, column 17. Connect the other end of the resistor in the blue row for column J.
  4. Connect the longer lead (+) of a green LED to row F, column 16 and the shorter lead (-) to row F, column 17.

Once you’ve completed the above, your breadboard should look like this:

breadboardLED

Looking down on the Grove Shield, connect your two LED wires. Plug the blue (GND) wire into the fifth pin from the front on the right side. Insert the orange wire into the ninth pin from the front on the left side (the first pin in the second connector).

LEDwiringongrovewitharrows

Plug the two temperature sensors into the jacks labeled D5 and D6, respectively. The connectors will only go in one way. The jacks are circled in the image below.

LEDwiringongroved5d6marked

As I mentioned in the beginning of this tutorial, you’ll need a port available on your network switch or wireless hub and to be close enough to run a cable from it to your Ethernet shield. So go ahead and run an Ethernet cable from the RJ-45 jack on the Ethernet Shield to your switch or hub.

Connect the USB cable to power and program the circuit into your computer. You may be prompted by your Mac about a new network interface, just click Cancel.

Talking to the Network

Let’s get this circuit talking to your network!

In the downloads folder are various sketch programs to assist. Find the LEDBlinkAndEthernetStarter folder and open LEDBlinkAndEthernetStarter.ino. The file will open in the Arduino IDE and you’ll see this starter code:

#include <SPI.h>
#include <Ethernet.h>
 
const int ledPin = 7;  //1
byte mac[] = { 0x90, 0xA2, 0xDA, 0x0D, 0x7D, 0x54 };  //2
 
EthernetServer server(80);  //3

Here’s what’s going on in this starter sketch:

  1. The line that declares the pin of your status LED.
  2. This refers to the MAC address you recorded earlier, which is unique to your Ethernet Shield. Replace this value shown with your value.
  3. Here you create a server object and instruct it to listen on port 80.

A server object? On a microcontroller? Yes, most libraries for the Arduino are written in C++. If you’re curious about how it works, you can peruse the source where you installed the other libraries earlier – look for the folder called Ethernet.

Note: If you would like to review the APIs for the included libraries with the Arduino IDE you can get to them here.

Select File/Upload to compile and load your code into the Arduino.

Once it’s done, select Tools/Serial Monitor and make sure the window has a baud rate of 9600. You should see some messages coming into the window as the system executes the code:

serialmonitordhcp

Note: If you do not have DHCP services on your network, you can assign an IP address to the server using the following code right after the line declaring your MAC address:

IPAddress ip(192,168,1, 121);  //pick some value on your network

Then replace Ethernet.begin(mac) with this:

Ethernet.begin(mac, ip);

If your LED didn’t come on briefly and then turn out, there could be a few problems :

  • You may have the wires in the wrong header pins. Double check the pictures above.
  • Make sure that all of the pins for the Grove Sheild and stackable headers are in their slots, and that none are bent (missing their slots).
  • You might not have pushed the Grove Shield or Stackable Headers down firmly enough.

If you aren’t sure if they are connected correctly, open the TestLEDOnPin7 sketch in the downloads folder and upload it. The LED should blink as before.

If the LED keeps blinking it means you could not get an IP address correctly. Check your MAC address values and/or router settings.

Whoohoo! You have all of the pieces in place to start reading the temperatures.

Server Setup

Now let’s get the server to handle inbound requests! This is where loop() comes to life. Add the following after the end of setup(), replacing the current function stub:

void loop(void) {
  // listen for incoming clients
  EthernetClient client = server.available();
 
  if (client) {
    Serial.println("new client");
    //an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        Serial.write(c);
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("Connnection: close");
          client.println();
          client.println("<!DOCTYPE HTML>");
          client.println("<html><body>HELLO</body></html>");
          break;
        }
        if (c == '\n') {
          currentLineIsBlank = true;
        } 
        else if (c != '\r') {
          //you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(1);
    // close the connection:
    client.stop();
    Serial.println("client disonnected");
    blinkLED();
  }
 
}

loop() checks if a connection has come in and displays all the connection data sent by the client and responding with a HELLO.

The code reads one character at a time, looking for the blank line on the request. At the conclusion of all this, you quickly blink the LED and wait for more connections.

Compile and upload the code by selecting File/Upload.

Let’s give the web server a spin! First reopen the Serial Monitor window by selecting Tools/Serial Monitor. Then using a browser on your Mac, open the URL: http://[the IP displayed in the Serial Monitor].

Your Serial Monitor output should show something similar to the following:

serialmonitorhtmloutput

And your browser should say HELLO, which is what you put in the loop code to display!

htmlbrowserhello

Serving Up Some JSON

The wonderful thing about the server is that you can control what it serves. And you need to serve JSON-formatted data to make reading and parsing it by external callers as easy as possible.

Back in loop(), fix the code to produce JSON by adding two variables at the top of the method:

//two variables to hold your temperatures
float temperatureIndoor;
float temperatureOutdoor;

Further down, where the same method outputs HTML, find the if statement that checks for newlines. Replace it along with its entire code block with the following:

if (c == '\n' && currentLineIsBlank) {
  // send a standard http response header
  client.println("HTTP/1.1 200 OK");
  client.println("Content-Type: application/json;charset=utf-8");
  client.println("Server: Arduino");
  client.println("Connnection: close");
  client.println();
 
  temperatureIndoor = 22.77;
  temperatureOutdoor = 15.55;
 
  client.print("{\"arduino\":[{\"location\":\"indoor\",\"celsius\":\"");
  client.print(temperatureIndoor);
  client.print("\"},");
  client.print("{\"location\":\"outdoor\",\"celsius\":\"");
  client.print(temperatureOutdoor);
 
  client.print("\"}]}");
  client.println();
  break;
}

Select File/Upload to compile and upload the code again to the Arduino. Open your Serial Monitor.

Using your web browser, reload the HTML page. You should see JSON output similar to this:

{"arduino":
	[   {"location":"indoor","celsius":"22.77"},
            {"location":"outdoor","celsius":"15.55"}
	]
}

Save this sketch as LEDBlinkAndEthernetFakeTemperatureJSON.

Take a break and enjoy the fruits of your labor. You have an Arduino microcontroller talking JSON and serving content on your network. Try pressing the reset button on the Ethernet Shield and give the system a second – it will come right back up, ready to serve up more content!

Reading Temperatures

Open the LEDBlinkAndEthernetFakeTemperatureJSON sketch and File/Save As… as LEDBlinkAndEthernetTemperatureJSON. This file is where you’re going to interface with the temperature sensors.

At the top of the sketch file, add the following code (replacing the current lines up until setup):

#include <SPI.h>
#include <Ethernet.h>
#include <OneWire.h>   //1
#include <DallasTemperature.h>
 
//2
#define TEMPERATURE_INDOOR 5
#define TEMPERATURE_OUTDOOR 6
 
const int ledPin = 7;
byte mac[] = { 0x90, 0xA2, 0xDA, 0x0D, 0x7D, 0x54 };
 
//3
OneWire oneWireIndoor(TEMPERATURE_INDOOR);
DallasTemperature sensorIndoor(&oneWireIndoor);
 
//4
OneWire oneWireOutdoor(TEMPERATURE_OUTDOOR);
DallasTemperature sensorOutdoor(&oneWireOutdoor);
 
EthernetServer server(80);
  1. Include the headers for the OneWire and DallasTemperature libraries.
  2. Declare two constants indicating to which pins the temperature sensors are wired.
  3. Declare an object to communicate with the indoor sensor using a OneWire object and passing it to the DallasTemperature library.
  4. Repeat the code to create an object for the outdoor sensor.

The sensor on pin 5 will be your indoor sensor, while the sensor on pin 6 will be placed outdoors.

The DallasTemperature object uses pieces of the Arduino OneWire library to support communications on the bus. Hence, you need to define both objects.

Inside setup(), add calls to sensorIndoor.begin() and sensorOutdoor.begin():

void setup(void) {
  pinMode(ledPin, OUTPUT);
  Serial.begin(9600);
  Serial.println("LED Pin setup for output on pin ");
 
  digitalWrite(ledPin, HIGH);
 
  sensorIndoor.begin();
  sensorOutdoor.begin();
 
  // start the Ethernet connection and the server:
  Serial.println("Trying to get an IP address using DHCP");

Now on to the loop() code, which does the heavy lifting of responding to user requests and getting the temperature results.

Earlier in the JSON section, you had two variables, temperatureIndoor and temperatureOutdoor, that for testing purposes had hard-coded temperature values. Now comes the magic of the sensors: you’ll use these same variables, but store real temperatures in them.

Change the two lines that set values for temperatureIndoor and temperatureOutdoor to instead call the readTemperatureCelsius() subroutine:

client.println();
 
temperatureIndoor = readTemperatureCelsius(sensorIndoor);
temperatureOutdoor = readTemperatureCelsius(sensorOutdoor);
 
client.print("{\"arduino\":[{\"location\":\"indoor\",\"celsius\":\"");

You may be wondering about the source of this magical subroutine readTemperatureCelsius. Scroll down in the sketch and insert that subroutine above the blinkLED subroutine:

float readTemperatureCelsius(DallasTemperature sensor) {
  sensor.requestTemperatures();
  float temperature = sensor.getTempCByIndex(0); 
  Serial.print("Celsius Temperature for device is: ");
  Serial.println(temperature);  //zero is first sensor if we had multiple on bus
  return temperature;
}

This subroutine takes a DallasTemperature sensor object and executes a requestTemperature command on the proper bus. It returns the temperature as a floating point value using sensor.GetTempCByIndex(). This method requests the Arduino to signal the bus and communicate with the first probe present (position 0) on the bus.

Since you only have one probe on the bus, it will return the temperature of that probe in Celsius.

Note: The GitHub source to the Dallas Temperature library is here. There is no API reference per se, but if you peruse the DallasTemperature.h file you will see some great comments on the different method calls available.

The server for this tutorial uses Celsius as the standard format (just a choice on my part). The temperature conversion to Fahrenheit is done on the iPhone if the user wants that.

Save the sketch and upload to your Arduino by clicking File/Upload. Hit the server with a browser. Open the Serial Monitor to watch the output. You should see the temperature of the room in which you’re working!

Try holding your hand around one of the sensors and reading the temperature a couple of times to watch it rise. Let go of the sensor to see the temperature fall :].

Note the slight delay on the reads, as the Arduino probes the bus and gets the results back before it can send them out. Also note that your browser sometimes sends multiple GET requests each time you browse to a URL (behind the scenes, it is trying to find a icon for the web page, which of course doesn’t exist in your case). Your iOS application will be more efficient than this!

At this point you have a dedicated hardware-assembled temperature monitor. WOOHOO!


Icanprobe

iOS and Swift Integration

Now comes the iOS! You will build an iPhone app to get your temperatures. To start things off, open the included Xcode project from the tutorial download. You can find it in the folder ArduinoTemperatureSwift Starter. The starter project has the following functionality:

  • It provides a simple user interface for the application.
  • The supported interface orientation is set to portrait.
  • It includes a custom open-source digital-looking font to show temperatures.
  • It contains a configuration/settings screen.
  • It provides methods to save and load your settings, including the URL and the temperature display format.

Open the project in Xcode and build and run. You should see the following:

initial_run_nosettings

This project uses a basic Application model including a flip view for settings. You will handle the communications and parse the results.

Tap the info button at the bottom of the screen and input the URL for your Arduino server:

configscreenios

Click the Done button and on the main screen, tap Update. You should see a message to the debug window telling you that your settings have been saved, but wait… there are no temperatures from your new circuit!

This is where you come in. Open ViewController.swift and locate performRestCall(). Inside this method, place the code needed to communicate over the network with the Arduino:

var url = NSURL(string: theURL)
 
if (url == nil || theURL == "") {
  showAlert("Invalid or no URL entered!")
  return
}
 
updateButton.enabled = false
 
var request = NSMutableURLRequest(URL: NSURL(string: theURL)!)
request.HTTPMethod = "GET"
request.setValue("application/json; charset=utf=8", forHTTPHeaderField: "Content-Type")
request.setValue("application/json", forHTTPHeaderField: "Accept")
request.cachePolicy = NSURLRequestCachePolicy.ReloadIgnoringLocalAndRemoteCacheData
 
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue(),
  completionHandler:{ (response:NSURLResponse!, data: NSData!, error: NSError!) -> Void in
 
  dispatch_async(dispatch_get_main_queue(), {
    if let anError = error {
      //error getting data
      self.showAlert(error.localizedDescription)
    } else {
      //process JSON
      self.handleResultsOfWebCall(data)
    }
    self.updateButton.enabled = true
  })
  return
})

This code simply takes the URL you provided to talk to the Arduino and sets up a background HTTP request using an Operation Queue. We utilize Swift closures to handle the results of the background web request.

The code receives the results and calls handleResultsOfWebCall(_:) on the main thread. This method parses and displays the results.

Let’s get to that now!

Find handleResultsOfWebCall(_:) and add the following implementation inside the method:

var error : NSError?
 
var jsonResults = NSJSONSerialization.JSONObjectWithData(theData, options: nil, error: &error) as! NSDictionary
if let jsonError = error  {
  println("JSON Error \(error!.localizedDescription)")
  showAlert("Error retrieving results-check the URL or Server!")
} else {
  let theSensors = jsonResults["arduino"] as! NSArray
  for i in 0..<theSensors.count {
    let sensor = theSensors[i] as! NSDictionary
    let location = sensor["location"] as! String
    let temperature = sensor["celsius"] as! NSString
 
    if (location == "indoor") {
      indoorTemperatureCelsius = temperature.floatValue
    } else {
      outdoorTemperatureCelsius = temperature.floatValue
    }
  }
  lastUpdate = NSDate() 
  saveSettings()  
  updateDisplayWithCurrentReadings()
}

This method to see if any data was returned, you use the built-in NSJSONSerialization handler to get the results into a NSDictionary object. From there, you read the values returned from the sensors and save them as Celsius values.

Next the settings are saved for display later when the application starts up again. Finally, you call updateDisplayWithCurrentReadings() to show the temperature values.

Build and run the application, and enjoy!

samplescreenshotwithtemps

Congratulations! You have a mobile application and temperature server that lets you read temperatures from sensors you can place anywhere. My setup has one sensor outside of a window and one inside. It’s really nice to be able to check the temperature quickly in the morning before heading out the door.

Where to Go from Here?

Here’s the download for the completed Xcode project from this tutorial.

You will notice the display shows the temperatures in different colors, based on the range of the value. This color handling is in the setFieldColor method. Feel free to change them for your climate.

You also may not like the sensor changing the IP address if it reboots, based on your DHCP settings. If that’s the case, modify the Arduino code to include a predefined IP address. This was described earlier in the tutorial, but for reference, you need to add a line near the top of the LEDBlinkAndEthernetTemperatureJSON file, like this:

byte mac[] = { 0x90, 0xA2, 0xDA, 0x0D, 0x7D, 0x54 };  
IPAddress ip(192,168,1, 121);  //or some value you want

Then replace the if (Ethernet.begin(mac) == 0) line with:

Ethernet.begin(mac, ip);  //in place of Ethernet.begin(mac).

What you’ve done in this tutorial is easily adapted to many other sensors!

I hope you enjoyed this tutorial and that it has inspired you to continue with your Arduino investigations. In the meantime, if you have any questions or comments, please join the forum discussion below!

Arduino Tutorial: Networked Temperature Sensor with Swift is a post from: Ray Wenderlich

The post Arduino Tutorial: Networked Temperature Sensor with Swift appeared first on Ray Wenderlich.

RWDevCon Inspiration Talk – Cognition by Cesare Rocchi

$
0
0

Note from Ray: At our recent RWDevCon tutorial conference, in addition to hands-on tutorials, we also had a number of “inspiration talks” – non-technical talks with the goal of giving you a new idea, some battle-won advice, and leaving you excited and energized.

We recorded these talks so that you can enjoy them, even if you didn’t get to attend the conference. Here’s our next talk – Cognition, by Cesare Rocchi – I hope you enjoy!


Transcript

Everything starts like this:

Attribution: talkgraphics.com

Attribution: talkgraphics.com

A blank canvas, a scary blank canvas.

In front of this, you can:

  • Follow your inspiration, or your gut feelings
  • Look at other applications to follow their design
  • Follow Apple’s guidelines
  • Follow the latest trends

Or instead, you could start asking yourself, “What is the customer trying to accomplish and how can I improve his or her journey towards their goal?”

You put the user in the middle and adopt a user-centric approach. You have to ask, “How does my customer think?”

Meet Giotto

Meet Giotto, the most famous painter and architect in the middle ages.

Screen Shot 2015-05-03 at 11.36.48 PM

In spite of that, the Pope got in touch saying something along the lines of, “Hey dude.” (The Pope was living in California at that time.) “Hey dude, I might have a gig for you, but you should show me your drawing skills.”

Giotto took a blank canvas and drew a perfect red circle and sent that as a sample and he got the gig. He could have taken three months off and painted a master piece, but he instead drew just the circle.

Cognitive science was not around at that time, it was not formalized, but he exploited many of the tricks that are in cognitive science.

What Is Cognitive Science?

Cognitive science is a whole field devoted to human beings, to the study of the way we perceive. There’s lots going on, perceptual representation, language processing. Many of our senses are involved in the many different situations of our daily lives, even in passive situations like watching a TV.

Edward Tufte is an information visualization guru and said:

“It is worthwhile to understand universal cognitive tasks in order to design our displays in accord with those tasks”. – Edward Tufte

He’s right. Without an understanding of the tasks that our customers are trying to accomplish, it’s pretty hard to come up with a good UI.

I’m going to touch on three aspects of cognitive science:

  1. Human Computer Interaction
  2. Perception
  3. Schemas

Let’s start with the first.

Human Computer Interaction

Human Computer Interaction (HCI) is the applied branch of cognitive science. It’s the guys that try to prove all the fancy theories that cognitive scientists come up with. It’s like theoretical physics and applied physics if you like.

HCI investigates the dialog between human and machines and models the dialog as two ongoing computations.

This is exactly what happens during conversation:

  • I say something, that’s an input to you.
  • You elaborate that.
  • Then you say something and that’s an input to me.
  • And I elaborate that.

The same happens with machines:

  • I type something in a form and that’s an input to the machine.
  • The machine shows a spinner and that’s a feedback to me saying, “Let’s wait a bit.”
  • Then after a while, I get my results.

There’s turn taking even when we interact with machines, much like when we interact with human beings.

Note from Ray: This same feedback loop applies to games. Learn more in my Adding Juice to Your Games talk!

Perception

One key aspect of this very complicated process is perception. The way we mentally organize our experiences.

You just did the laundry. You’re in front of a pile of messy clothes.

Attribution: flickr.com

Attribution: flickr.com

You pick up a T-shirt, you fold it, you put in a pile, and then you pick up undies and you fold them and you put in a second pile. You have two piles because you do not want to mix them up, and you want to put them in two different drawers.

This is perception. The T-shirt is the input, the piles are the working memory, and the drawer is the long term memory.

Gestalt

It’s impossible to not mention Gestalt whenever you talk about cognitive science. Gestalt is a school born in Germany at a beginning of the last century, and they focused a lot on modeling perception, trying to investigate the way we think, especially visual perception.

They came up with this linear model.

Screen Shot 2015-05-03 at 11.37.34 PM

Visual perception starts with a something that hits my retina and ends up in my brain.

Going back to the laundry example, for example the light hits the T-shirt and that triggers something on my retina and that triggers something in my brain.

This is a pretty simplistic model though, which does not allow to model highly interactive situations.

Neisser’s Perceptual Cycle

In fact somebody elaborated and came up with a different model, claiming that perception does not begin or if you like, begins the very first second you’re born and goes on as a loop. This is called Neisser’s Perceptual Cycle.

Screen Shot 2015-05-03 at 11.38.28 PM

This loop model has three nodes:

  • The environment modifies my knowledge.
  • My knowledge directs my exploration of the world.
  • Exploration samples my environment.

Perception is a constant loop. Now, we’re talking! Now, we can model highly interactive situations. for instance how we can foresee where a rolling ball is going to end up. Even in very complicated situation, this model helps a lot.

Perception is Selective

Another feature of perception is that it is highly selective.

This happens for example at conferences, and that’s great. During breaks, people form groups and start talking.

Screen Shot 2015-05-03 at 11.38.14 PM

When you’re part of a conversation, you are totally able and often unconsciously able to ignore any other conversation going on nearby.

You wouldn’t have the power to process all the conversation in the hall.

This exemplifies how perception is very, very, very selective. It is selective when we use applications as you will see.

Schemas

Going back to the loop model, it is clear that we are the knowledge node. What do we put in this node? Schemas.

Unfortunately, the literature is very, very complicated, so I’m going to use the term schemas, but you will probably stumble upon terms like mental models, frames, glance.

What are schemas? They are recipes that we use to extract information from the world. They drive our eye movement, hand movement, and so on and so forth.

I like to think of schemas as scaffolding on which we hang up our knowledge.

This metaphor allows me also to simply explain what’s difference between a beginner and an expert. A beginner simply has a smaller scaffolding.

Working Vs. Long Term Memory

A key aspect of perception is working memory. When working memory is overwhelmed you will experience cognitive load, which is not nice at all.

Cognitive load happens because:

  • our working memory can hold four to five bits of information (that’s not a lot)
  • this lasts ten seconds (that’s not a lot).

I can’t think of a better metaphor than Sax Parsing, in which you process a document line by line, and you forget about everything that you did before.

If you didn’t experience cognitive overload recently, try to go back to the first time you started driving a car.

Attribution: flickr.com

Attribution: flickr.com

It’s a new situation and there’s lots going on all at once.

  • How much pressure should I put on the gas pedal?
  • How much on the clutch?
  • Is the light red or green?
  • Is somebody crossing at a pedestrian cross?

You are overwhelmed. You don’t understand anything. Where am I? What should I do?

Nowadays, you’re an experienced driver. You have better engrained schemas to help you complete the task of driving. Now it’s not as overwhelming and while you drive:

  • You can talk to the phone.
  • You talk to passengers.
  • You sing out loud.
  • You send text messages.

You drive by default. You’re not using your working memory anymore. You’re using your long term memory, and so that allows you to use very low computational power in your brain.

How Does All This Apply to Apps?

I’ve touched several topics: human computer interaction, perception, and schemas, which I think are three relevant aspects of the way we perceive.

Now, let’s see how we can apply all this to the design of user interfaces. I’m going to touch on five tips and tricks:

  • chunking
  • white space
  • color
  • shape
  • first impressions

Let’s start with the first.

Chunking

I’m going to show you a number and I’m going to give you five seconds to memorize it. Ready? Do you have your timer set for five seconds?

Screen Shot 2015-05-03 at 11.39.37 PM

Do you have it? Probably not since it’s pretty hard.

There’s a key behind the number, and this is chunking. Once you know the key, you do not even need to remember the number. You have

  • 60 seconds/minute
  • 60 minutes/hour
  • 24 hours/day
  • 30days/month
  • 365days/year

Now it’s much easier to remember the number. This is the power of chunking.

Ever wondered why credit card numbers are four chunks or four digits?

Attribution: flickr.com

Attribution: flickr.com

This is because it’s easier to move a four by four number to a form or line on paper. It’s way, way more complicated to copy a 16 digit number.

White Space

This goes hand in hand with the concept of white space. White space is like pauses for music. There’s no song that makes sense without pauses. There’s no UI that makes sense without white space.

You may say “I’m a developer. I have no idea what’s white space. I have no idea how to use it.” But you use it every single day, every time you format your code.

required init(coder aDecoder: NSCoder) {
  super.init(coder: aDecoder)
}
 
override func viewDidLoad() {
  super.viewDidLoad()
}
 
override func didReceiveMemoryWarning() {
  super.didReceiveMemoryWarning()
}

This is good usage of white space, because you want to make your code more readable.

Now, let’s look at the mail app. I went on and deleted the separators in the cell, and the app is still perfectly usable, just to show you a good usage of white space:

Screen Shot 2015-05-03 at 11.41.18 PM

White space can also be used as a marketing tool. If you look at this screenshot of iPhone OS 201, so the first time that the app store was released, there are two empty slots down there.

Screen Shot 2015-05-03 at 11.41.42 PM

Our mind is great at gap filling. How do you fill those slots? You’ll have to buy some applications. White space can be used as a means to trick people or as a marketing tool.

Let’s look at some real world examples. If you look at the showcase, it’s perfectly clear what you should expect if you step in the shop.

Attribution: flickr.com

Attribution: flickr.com

I’m sure they’re going to sell more and different items than those, but I have a crystal clear idea of what you should expect.

Take instead the showcase of a funky bazaar.

Attribution: flickr.com

Attribution: flickr.com

What are they selling? I don’t know. This is pretty similar to the first time I started driving, right? I have no idea what’s going on.

To give you a digital example, this is an app that is meant to rename files.

Screen Shot 2015-05-03 at 11.44.09 PM

One simple task and yet things don’t look so simple here.

Color

Let’s move to color. Color is a visually selective variable, which means it’s fundamental for symbolication of an object, and I’ll show you how.

This is a little game. I’m going to show you a bunch of letters, and I’m going to ask you to count a specific type of letter. Once you think you got the right count, shout it out loud. There’s also give away. There’s a prize, a free license for PaintCode, so pay attention.

This is the image. How many red letters?

Screen Shot 2015-05-03 at 11.46.56 PM

If you said eight, you were correct. It took the group at my talk around three seconds to arrive at the right answer.

Let’s play another round of the same game. We’ll use the same image. How many Ws?

Screen Shot 2015-05-03 at 11.46.56 PM

If you counted eight, then you were correct! But did you notice that it took you longer this time?

Exactly the same image, exactly the same numbers, eight and eight, but it took the group at my talk around seven to eight seconds to get the answer.

It takes way longer to go by shape, and it’s way easier to go by color. That’s why color is a visually selective variable.

Whenever you need to group objects, use color instead of shape.

Screen Shot 2015-05-03 at 11.44.54 PM

You see this principle here, whenever you use a navigation tab bar. The non-selected items are grey and the selected shows up in blue. We might argue that the difference between the selected and the non-selected is not clear immediately, but still the principle is in place in this example.

Shape

Let’s move to shape, which you can couple with color. Look at this wonderful recycle bin.

Screen Shot 2015-05-03 at 11.45.12 PM

I have no idea where I should put paper for example. Sure, it’s a great industrial design. I could put labels for paper, glass, and so on and so forth.

But this is way better:

Attribution: wikimedia.org

Attribution: wikimedia.org

They’re better because here you see affordance. Say I’m walking on a sidewalk with a newspaper that I’ve read. It’s immediately clear to me that it goes in the blue bin because the shape of the hole affords a piece of paper, much like a handle affords twisting or a cup handle affords grabbing.

This is a great example of coupling color and shape.

First Impression

Last example is first impression. A few years ago Blink was a massive success.

It’s a book that claims that when we meet a person or buy a new object or live a new experience, our mind starts thing slicing very fast, because the mind needs a way to classify something new quickly, and not using the whole thing but just slices of that.

Unfortunately, that happens also with applications or digital products in general. How many times have we been dumped on the first screen of an application with no idea of the actions that we can make?

What can I tap? What happens if I tap this or that? I wander around and see how it goes.

Even if you’re building the simplest application that allows to perform very well know tasks like checking email or to-do list apps, it’s always a good idea to provide a good onboarding.

Screen Shot 2015-05-03 at 11.46.05 PM

Tell the user which are the key actions that can be performed on every screen.

Cognitive Science and You

Going back to the initial quote, let’s restate it:

“It is worthwhile to understand universal cognitive tasks in order to design our displays in accord with those tasks.”- Edward Tufte

Another quote by a famous guy (Me, right now!):

“Building an app is building a perceptual loop.” – Me

To keep users engaged the fewer surprises such as breaking expectations, and the lower interaction overload going on, the higher the chance that users are going to go back to our app and open it again.

Going back to the blank canvas, it’s not blank anymore.

Screen Shot 2015-05-03 at 11.46.21 PM

It’s not scary anymore, because now we have tips and tricks like:

  • chunking
  • white space
  • color
  • shape
  • the superpower of a first impression

These are all of the things that Giotto exploited, and now you can too.

Note from Ray: Did you enjoy this inspiration talk? If so, sign up to our RWDevCon newsletter to be notified when RWDevCon 2016 tickets go on sale!

RWDevCon Inspiration Talk – Cognition by Cesare Rocchi is a post from: Ray Wenderlich

The post RWDevCon Inspiration Talk – Cognition by Cesare Rocchi appeared first on Ray Wenderlich.

PaintCode Tutorial for Designers: Getting Started

$
0
0
Make a stopwatch in PaintCode!

Make a stopwatch in PaintCode!

PaintCode is a fantastic little Mac app that turns your vector graphic designs into Core Graphics code you can easily use in your iOS apps.

Not only does it create all of the code to support your lovely vector graphics, but these graphics can be dynamic, which means you can change their color, size, layout, and more, all from within your code.

In this tutorial, you’ll learn how to create two static assets — a stopwatch image and a stopwatch hand — which you’ll export to a StyleKit that you can use in your app.

StyleKits keep track of all the things such as colors, gradients and shadows that you use in your project. If you make any changes to your assets in PaintCode, you simply have to export the StyleKit again and your project will be updated in a snap.

Note: This tutorial does not require any coding experience or any prior experience with PaintCode.
PaintCode Stopwatch

Here’s what you’ll make!

Getting Started

First make sure you have a paid copy of PaintCode. The free trial will not work for this tutorial; it has a number of restrictions such as the inability to copy/paste, the inability to export code, and more.

Open PaintCode; a new document should open automatically, but if not, simply select File\New.

PaintCode new document

Check out the Canvas panel on the right-hand side of the screen; this is the Inspector pane, which you can use to change the attributes of your selection:

InspectorPane

In the Canvas section, rename the canvas to Stopwatch, change both the width and height of the canvas to 250, and change the Code Export dropdown to StyleKit Drawing & Image Method as shown below:

DrawingMethod

This generates two methods in the StyleKit class; one to perform the actual drawing, and another to return a UIImage representation of the drawing.

Note: The top-left of your canvas is the master origin; the locations of all object origins will be calculated from this point in pixels. You simply create your art in PatinCode in non-Retina sizes, and the code takes care of creating the Retina-sized assets.

Creating the Stopwatch

Next, choose Oval from the Toolbar at the top of the screen:

04

Click and drag a circle onto the canvas – the exact shape doesn’t matter as you’ll modify the values next.

With the circle selected, head back to the Inspector and set both the width and height of your Oval to 220, the X position to 15 and the Y position to 30:

Drawing a circle in PaintCode

This moves your object’s origin down and over a little to (15, 30); by default the origin of your object is at (0, 0).

Click the Fill dropdown in the Inspector and select Add new Color…:

AddNewColor

In the resulting menu, change the name of your color to Base Color and the hex value to #118DDA:

PaintCode color settings

Click anywhere outside of the menu to close it.

Next, go up to the Toolbar and choose Rect. Drag out a rough rectangle at the top of the circle, and modify the position and size of your Rectangle as follows:

  • X: 114
  • Y: 2
  • W: 22
  • H: 34

Your Canvas should now look like the following:

PaintCode draw rectangle

Next, drag out another Rect on your Canvas that’s 30 wide and 20 — the exact position doesn’t matter right now. You should have something like the image below:

PaintCode create rectangle

Now drag out another Rect, but hold down Shift to keep the aspect ratio 1:1 and drag out to a size of 10 x 10:

PaintCode create rectangle

Click the + button at the bottom right of the canvas area to see your rectangles up close; you can also pan around by holding the spacebar and clicking and dragging your mouse.

Now you need to rotate the rectangle by -45 degrees. Click on the rectangle to ensure it’s selected, then go to the Inspector and click on Transforms to expand the panel. Enter -45 for the Rotation:

Rotation

Move the square so the upper right point of the square intersects the diagonal right side of the rectangle as shown below:

SquarePlacement

Hold down Shift, and click on both the rectangle and the square to select them. Now click Union in the toolbar to combine the two rectangles into a single shape like so:

Union

Position the shape at X 200, Y 30, either manually or by setting the X and Y coordinates in the Inspector:

PaintCode position

Okay — that takes care of the main body and buttons of your stopwatch. Zoom out so you can see the entire stopwatch; it should look something like the following:

PaintCode stopwatch

Save your project before you move on: click File\Save or press Command-S, name your project PaintCodeTutorial and click Save.

Creating the Stopwatch Hand

You know what a stopwatch is without a second hand? Really inaccurate. :]

Creating a stopwatch hand would be the next logical step.

You’ll eventually place the second hand on a new canvas, but you’ll first create the hand on the old canvas so you can position it properly over the stopwatch.

First, create the new canvas. Right-click anywhere outside of the current canvas in the central portion of your window. Select Add New Canvas, and you’ll see a menu pop up. There are plenty of iOS device resolutions to choose from, but look at the top of the menu where you’ll see one of two things: either (200×200) Default, or (250×250) Size of Stopwatch:

PaintCode new canvas

If you had the Stopwatch canvas selected when you right-clicked outside the window (you’d know this as the canvas would be outlined in blue rather than grey), you’d see the (250 x 250) Size of Stopwatch option. If the Stopwatch canvas wasn’t selected, you’d see the (200 x 200) Default option instead.

In this tutorial choosing one over the other doesn’t make a lot of difference, but this demonstrates an easy way to create a new canvas with the same dimensions as another canvas: click on the canvas to select it, then right-click outside the canvas to create a new one.

In either case, select the first option in the list.

You can move the canvas around by clicking and dragging the title at the top of the canvas. The position of the canvas is not important, but if you don’t like where PaintCode chose to put the canvas, you can move it around to suit.

Change the title of the canvas to Stopwatch_Hand, the width to 250, and the height to 220. Since your stopwatch hand will be white, a darker canvas color will make it easier to see what you’re drawing. Click the white color rectangle next to Background and select black to change the background color. Leave the StyleKit option as Drawing Method.

Your canvas and Inspector should look like the following image:

PaintCode new canvas

Note that the actual canvas color does not affect the code at all.

Now head back to the Stopwatch canvas, choose Oval from the Toolbar and hold down Shift while you drag out a circle like so:

PaintCode circle

Click the Fill dropdown and click the white circle from the list of selections to set the circle’s color:

PaintCode color settings

Change both the Height and Width to 30, then manually center the circle on the stopwatch’s blue circle face. Purple guides will pop up to help you position the circle. When you’re done, the circle’s origin should be at X 110, Y 125:

PaintCode position

Now for the hand itself. Click Rect in the Toolbar and drag out a white rectangle of Width 8 and Height 115. You can always tweak the rectangle’s color, width, and height in the Inspector if necessary.

Drag the rectangle over the white circle and position it as shown below:

PaintCode draw rectangle

You are going to combine the two shapes, but first you have to set the circle shape’s origin appropriately so that the hand will rotate around the center of the circle.

Shift-click both the white circle and rectangle and expand the Transforms section in the inspector to see their respective origin points:

PaintCode shape origins

You want the origin of the combined shape to be in the center of the circle — but you need to know exactly where that point is. You can’t just guess.

Click away from the shapes to deselect them. Click the circle to select it, then click Transforms in the Inspector. Hover over the green circle and your cursor will turn into a hand. Click and drag the green origin marker to the center of the circle; the origin marker should snap to the center. Failing that, you can manually move the origin by entering -15 into both the X and Y values of Offset in the Transforms panel:

25

Take note of the origin’s X and Y position: 125, 140. You’ll need to enter this later.

PaintCode shape origins

Now you’ll union the two shapes. Shift-click the white circle and the white rectangle, and click Union in the Toolbar. Now click Transforms — you’ll notice that the white shapes have been combined into a new shape with the origin at the top left:

PaintCode shape union

If you left the origin in its current position, the hand would rotate around that point, rather than around the center of the circles. Click and drag the green origin circle until its X and Y values are 125 and 140 respectively:

PaintCode shape origin

In this case, you can’t edit these values from the Inspector or it will move the shape along with the origin — which is not what you want!

The only thing left to do is move your new stopwatch hand back to its own canvas. Select the shape and press Command-X to cut the stopwatch hand.

Click the Stopwatch_Hand canvas, then press Command-V to paste the hand shape; it will automatically place itself onto the new canvas with its origin at the same position as it was on the old canvas: X 125, Y 140.

PaintCode paste on black canvas

Since the new canvas is only 220 pixels high, instead of 250 high like the Stopwatch canvas, your shape is no longer located correctly. Since the hand’s canvas is 30 pixels shorter, the hand needs to be located 30 pixels closer to the origin in the Y direction..

Select the hand shape, then use the Inspector to change the position to (125, 110) as shown below:

PaintCode position

That’s the last bit of pixel-pushing! Time to give yourself…a hand! ;]

All that’s left to do is export this StyleKit project so you can use it in your code.

Exporting to StyleKit

Click the StyleKit tab, shown below:

PaintCode StyleKit tab

This tab lists the the Colors, Gradients, Shadows, Images, and Drawing Methods available to export. For this tutorial, you’re only concerned with Colors and Drawing Methods.

At this point, no colors are listed:

PaintCode StyleKit colors

You need to add your Base Color to the list so that you can eventually change the base color of the stopwatch in your app.

Click Add Color; a menu pops up with the one color you defined in your project — Base Color:

PaintCode StyleKit colors

Select Base Color, and it will appear in your list of StyleKit Colors like so:

PaintCode StyleKit colors

Scroll down and look at the two available Drawing Methods, one for the Stopwatch, and one for the Stopwatch Hand:

35

These have been included for you automatically, so you don’t need to do anything else here — you’re ready to export!

In the right panel, fill out the StyleKit information as appropriate; note that the Project field will be the filename of your export:

PaintCode StyleKit export

Take a deep breath — you’re nearly there! Click the big blue Export button:

PaintCode StyleKit export

You’ll see a popup window like the one below:

ExportWindow

Click Export, and then Save. Open up the folder you saved it to, and you’ll see PaintCodeTutorial.swift: this contains the Core Graphics code to draw the stopwatch that you will use in your app.

PaintCode StyleKit export

Where to Go From Here?

The fun doesn’t stop here!

Head on over to PaintCode Tutorial for Developers: Getting Started, where you’ll use these assets to create a stopwatch app with an animated hand.

Best of all, these graphics will be created in your app as vectors, so they will be super-crisp on any device.

For more PaintCode practice, I highly recommend going through the Tutorials and Documentation on PaintCode’s website.

If you have any questions or comments about this tutorial, feel free to join the discussion in the forums below!

PaintCode Tutorial for Designers: Getting Started is a post from: Ray Wenderlich

The post PaintCode Tutorial for Designers: Getting Started appeared first on Ray Wenderlich.

Video Tutorial: Unity Basics Part 4: Animation


Video Tutorial: Unity Basics Part 5: Sounds

PaintCode Tutorial for Developers: Getting Started

$
0
0

Animate a stopwatch created in PaintCode!

PaintCode is a fantastic little Mac app that turns your vector graphic designs into Core Graphics code you can easily use in your iOS apps.

PaintCode has always been great, but the recent release of PaintCode 2 has made it even greater, with a bunch of great new features like Swift code generation and StyleKits.

In this tutorial, you’ll learn how to integrate an stopwatch control made by a designer built in PaintCode into your own app. If you’d like to learn how to make the control yourself, check out our PaintCode Tutorial for Designers: Getting Started.

Note: This tutorial assumes you are an intermediate to advanced iOS developer and are familiar with Auto Layout, so some instructions are abbreviated. If you are new to iOS development or Auto Layout, check out some of our other iOS tutorials first.

Getting Started

Download the starter project for this tutorial here.

Open up the project in Xcode and check out the basic structure and contents of the app. Main.storyboard has a tab bar controller with three view controllers. In this tutorial, you will only be working with the first view controller, where you will put the stopwatch control.

ThreeVCs

A Note on StyleKit

StyleKit is a recent feature in PaintCode that allows you to export your drawing methods, color, gradients, and assets into an easily reusable class that you can add to your project.

PaintCode StyleKit

StyleKit gives you a few advantages over the old way of doing things in the previous version of PaintCode:

  • You no longer need to manually copy and paste your drawing code from PaintCode into a subclass.
  • You can easily make tweaks in PaintCode, re-export those changes, and immediately see results in your project.
  • You’re provided with an improved, faster workflow for designing and prototyping your assets.
  • You have new, powerful variables for your generated controls or assets, standard colors that other elements in your app can access and use, along with cleaner source files.

Adding the StyleKit

Imagine your designer has already created a stopwatch control for you in PaintCode, and has exported the StyleKit for your use.

For this tutorial, you have two choices:

  1. If you did not do our PaintCode Tutorial for Designers: Getting Started: Download this pre-exported code and add it to your project.
  2. If you did our PaintCode Tutorial for Designers: Getting Started: Add the file you exported from in the previous tutorial into your project.

Once you’ve added the Swift file to your project, create a new Swift file named . Open it and replace the contents with the following:

import UIKit
 
@IBDesignable
class Stopwatch: UIView {
  override func drawRect(rect: CGRect) {
    PaintCodeTutorial.drawStopwatch()
  }
}

This uses the StyleKit helper code generated by PaintCode to draw the stopwatch body. Easy, eh? :]

Create another new Swift file named . Open it and replace the contents with the following:

import UIKit
 
@IBDesignable
class StopwatchHand: UIView {
  override func drawRect(rect: CGRect) {
    PaintCodeTutorial.drawStopwatch_Hand()
  }
}

As you can see, using StyleKits saves you save tons of code in your subclasses, and working with custom views becomes a breeze.

Build your project just to make sure that everything compiles correctly. Your next step is to set up views for each element in the storyboard.

Modifying the Storyboard

Open Main.storyboard; you’ll be dealing with the Asset View Controller scene (the “First View”). Delete the “First View” label as you won’t need that anymore.

Drag a view into the scene for the stopwatch (the size and position doesn’t matter), and set the following constraints on this view:

  • Width Equals: 250
  • Height Equals: 250
  • Align Center X to: Superview
  • Top Space to: Top Layout Guide

Update the frame of your view, and set the class to Stopwatch in the Identity Inspector. Because you marked the class as @IBDesignable, you’ll see a preview instantly!

StopwatchPreview

Now, drag a second view onto the scene for the stopwatch hand and size it to be the same size/location as the stopwatch. Change the view’s background color to a clear color, and give it the following constraints:

  • Width Equals: 250
  • Height Equals: 222
  • Align Center-X to: Stopwatch
  • Align Bottom to: Stopwatch

Set the class to StopwatchHand, and you should see the following:

StopwatchHand

Build and run your project to ensure that everything is lined up correctly, and that you are not seeing any Auto Layout errors or problems with your storyboard.

Animating the Watch

Next it’s time to animate the watch! Open AssetViewController.swift and add the following outlet to the top of the implementation block:

@IBOutlet weak var stopWatchHandView: UIView?

Switch over to Main.storyboard one last time and connect the smaller view to the stopWatchHandView outlet.

Back in AssetViewController.swift, add the following methods:

override func viewWillAppear(animated: Bool) {
  rotateStopWatchHand()
}
 
func rotateStopWatchHand() {
  UIView.animateWithDuration(2.0, delay: 0, options: .CurveLinear, animations: {
    self.stopWatchHandView!.transform =
      CGAffineTransformRotate(self.stopWatchHandView!.transform, CGFloat(M_PI_2))
  }, completion: { finished in
    self.rotateStopWatchHand()
  })
}

rotateStopWatchHand simply rotates the hand 45 degrees to the right, and you call this continuously.

Build and run your app; check out the results of your animated stopwatch:

Stopwatch

Voila! The stopwatch hand is animating. And you barely, BARELY wrote any code :]

Where to Go From Here?

You can download the final project here.

I’ve only scratched the surface of PaintCode in this tutorial; to learn more check out the great PaintCode tutorials at www.paintcodeapp.com.

If you have any questions or comments on this tutorial, feel free to join the discussion below in the forums!

PaintCode Tutorial for Developers: Getting Started is a post from: Ray Wenderlich

The post PaintCode Tutorial for Developers: Getting Started appeared first on Ray Wenderlich.

Video Tutorial: Unity Basics Part 6: Conclusion

RWDevCon Inspiration Talk – Starting Over by Ellen Shapiro

$
0
0

Note from Ray: At our recent RWDevCon tutorial conference, in addition to hands-on tutorials, we also had a number of “inspiration talks” – non-technical talks with the goal of giving you a new idea, some battle-won advice, and leaving you excited and energized.

We recorded these talks so that you can enjoy them, even if you didn’t get to attend the conference. Here’s our next talk – Starting Over, by Ellen Shapiro – I hope you enjoy!


Transcript

We’ve all had times in our lives where we wonder in frustration, “How did I wind up here?”

Maybe you’re:

  • Working a job that drives you bananas.
  • Living in a city or with a person that just isn’t the right fit.
  • Still in the industry that you started out in, but it’s turning into a burnt out husk of its former self.

What I’m talking about isn’t something where you get transferred or your significant other gets transferred or some other force from outside comes along and makes this decision to start over for you.

I’m talking about something where you drive the decision making process. You decide to start over.

Just the mere mention of starting over make some people cringe and I don’t blame them because starting over voluntarily is terrifying.

Attr:

Attribution: flickr.com

If you’re starting over professionally, you go over from being someone with lots of experience in your field to someone with zero experience in your field. If you’re starting over personally you can wind up in a city or a state or even a country where you don’t know anyone.

I’m here today to tell you that some of the things that make you fear starting over are myths. If you let yourself be paralyzed by these myths, you can miss out on a fantastic new chapter in your life.

Yes, starting over is scary, but it is not as scary as you think.

A Tale of Three Careers

I want to start by telling you my story because I have gone through three major phases in my life, all of them fairly different from the previous one.

  1. First I was a songwriter.
  2. Then I worked in television production.
  3. Now I’m an iOS engineer.

Every time I made one of these changes I learned a lot of things along the way and I want to share some of my story with you. I call it a tale of three careers.

My First Career: Songwriter

Let us go back in time to a magical place known as the 1990s.

My first career was as a songwriter. I started playing the guitar when I was 10 years old and by the time I was 18 I had a couple of regular gigs here in my hometown of DC. All I wanted was to be the next Sheryl Crow or the next Melissa Etheridge.

I poured so much energy into songwriting. I took all the money that I’d gotten at my bat mitzvah and I combined with a couple of years worth of allowance and I put out an album on my 18th birthday.

Screen Shot 2015-05-10 at 10.25.41 PM

You can still listen to it on Rdio or Spotify. It is called Bridge Over Bottled Water because my humor has not changed. I will warn you that my lyrics contain a heaping helping of teenage angst because I was, well, a teenager, but I’m still very, very proud of that album.

Even after I went to college in Chicago, I spent an enormous amount of my free time playing and writing. I started to pull together a little bit of success. I got my first showcase in a big music conference and I started to book some bigger gigs in Chicago.

As I started to really pour myself into the work that it took to become a successful working musician, I realized, “This is going to make me absolutely hate music.”

It wasn’t the musicians that I played with, they were great, but so many people that I dealt with in the music business were, to put it very mildly, colossal jerks. They treated everyone around like dirt at best.

The toxic attitude that they projected seemed to get exponentially worse as you got even incrementally more successful.

I can't take it anymore!

I can’t take it anymore!

You had to really, really love music to keep loving it after coming into contact with these people. Not loving music anymore was not a possibility that I was willing to accept.

I finally realized making music professionally was not for me and this was a terrifying realization. I had built my entire social identity around being a songwriter and I had poured years of effort and thousands of dollars in trying to make it as a professional.

How was I going to move forward from that?

My Second Career: Television Production

My second career in television production actually started as a result of my interest in music being so strong. My parents, including my mom who’s here today, were generous enough to say, “We will pay for your education, as long as you study something that is not music.”

I had realized that film school could actually be a great way to learn about audio engineering and pick up some practical, creative skills that easily transferred back to music.

Once I decided that a career at music wasn’t going to be for me, I found that I was really enjoying working with audio in a more filmic fashion.

Screen Shot 2015-04-26 at 7.47.40 PM

I was the sound recordist during shooting or post-production sound editor on several films that my friends directed and I had a lot of fun. I learned a lot about how to make things sound really great.

In September of 2003, I moved out to Los Angeles to try and break into the business. When the timing for purely audio based internships didn’t work out, I started applying for internships at pretty much anything that looked remotely interesting.

I got a bite from this brand new talk show that had only been on the air for about six weeks.

Screen Shot 2015-05-10 at 10.25.04 PM

I wound up working at the Ellen DeGeneres Show for almost two years and I absolutely loved it. I worked at House for a couple of years. I also worked on a show called Trust Me for six months.

Then I worked at a whole bunch of failed pilots. Pilots are the first episode of the TV show and here’s how they work:

  • If the network likes the pilot, then they order a full series and it becomes a TV show.
  • If the network doesn’t like the pilot or any of a million other things go wrong, the pilot fails and then it’s essentially locked away in a vault never to be seen again.

Screen Shot 2015-05-11 at 4.42.21 PM

The failed pilots for me were the hardest because as a crew we would all work ourselves into the ground to try and to help make something good and then it was all suddenly gone.

It was like all of that work had disappeared into thin air. No one would ever see what we made. If you’ve ever had a client pull the plug midway into a project, you know exactly how frustrating this is.

I finally got so frustrated with this happening over and over and over again that I realized I had completely lost my passion for what I was doing. If you’re not passionate about what you’re doing, the entertainment industry will completely crush your soul.

I knew I was going to have to start over again but this time it was a lot scarier. I had absolutely no idea what I was going to be able to transfer the very industry specific skills that I had picked up over to something completely different.

I also now had rent to pay and my lovely cat who I had to feed. I had to feed him and me and here he is sitting in a box of his expensive prescription food:

Screen Shot 2015-05-10 at 10.24.31 PM

For a while, I couldn’t even decide what it was that I wanted to do with my life.

I finally noticed during my downtime when my friends were off writing screenplays or shooting YouTube videos, I was trying to figure out how my phone worked. I realized, “Maybe this is what I should actually be doing.”

My Third Career: iOS Engineer

This led to my third career as an actual nerd. I decided to be a professional nerd because I had always been good at tech stuff, at least in comparison to the rest of the entertainment business.

When I first started at Ellen in 2003, I was the only person who knew how to hook up a Mac to a network printer. As I moved from show to show, people started to figure out that I was often a reasonable substitute for calling IT.

Attr:

Attribution: flickr.com

I was good enough at IT stuff that I actually put together a decent little side business fixing computers and networking issues for writers and producers and other sorts of people who had a lot more money than time.

I knew I can easily go into IT professionally, but I wanted something more challenging. I realized I didn’t want to be fixing other people’s mistakes. I wanted to be making my own mistakes, damn it.

I was so fascinated by smartphones and their inherent potential that I knew, I just knew I had to learn how they worked.

I found a program through UCLA extension that quickly taught me the basics of object oriented programming and showed me how to make very rudimentary iPhone and Android apps. That confirmed to me, this is what I want to do.

I kept building stuff.

Screen Shot 2015-05-10 at 10.23.52 PM

I made three iOS apps and two Android apps on my own and it was hard, especially back in the dark ages of 2010 an 2011. I found raywenderlich.com and I inhaled tutorials from this site like air.

I finally got a job and I moved back to Chicago and I kept learning. I kept learning and I kept learning and I worked every spare second I had to keep getting better and I continue to do that every single day.

Four years after I first learned how to program, I am here speaking about how to do it and I am building tools and writing tutorials to make it easier for other people to learn. :]

Screen Shot 2015-05-10 at 10.29.02 PM

Now that you have heard what is essentially my entire life story, I want to take some of the lessons that I learned and make them actionable for you. I want to share the five most important things I learned from starting over, and over.

Lesson 1: What You Are Passionate About Can Change

The first lesson is: The thing that you are passionate about can change and that is okay.

You always hear all sorts of your advice about following passion and this is really, really easy if the thing that you are passionate about is easy to get into and pays a zillion dollars.

It’s a lot harder if the thing that you’re passionate about is difficult or it puts a mental or financial strain on you or your family or if you’re working against any kind of entrenched system that tells you that for whatever reason, what you’re doing is not good enough.

The fact of the matter is the thing that you are passionate about at 10, the thing that you’re passionate about 22, the thing that you’re passionate about at 40 and the thing that you’re passionate about at 65 can all be very, very different.

If you’re doing something because you’re passionate, not just because you want to pick up a paycheck, you have to constantly challenge that passion. Life is short and the time that we have to make an impact can be even shorter if you need good health to do it.

You have to ask yourself the hard question, “Is this still what I want to do with my life?”

thinking-above-clouds

Failing to ask that question and ask it regularly can lead to years of dissatisfaction because you are doing what you dreamed of doing, but you don’t realize that the dream belong to a different version of you.

The answer to, “Is this still what I want to be doing with my life,” can remain yes for a really long time. Simply asking that question is a really helpful way to push yourself to work on the things that you’re most passionate about and really get the most out of your life.

But you also have to be okay with the answer to that question being no. You have to be willing to use that response as a jumping off point to figure out, “Well, what do I want to do with my life?”

Lesson 2: Making Lemonade Out Of Lemons

When you get to the point that you realized no, you’re not doing what you want to be doing with your life, you can feel like life handed you a lemon. This is when: Making lemonade out of lemons is a necessity.

In my case, this actually happened both literally and figuratively.

In the literal case, this is a lemon.

Screen Shot 2015-05-10 at 10.23.27 PM

Despite its size being what it is, it is definitely a lemon. It almost hit me in the head when I was walking home from the gym one day.

Any time you have a set back it can be very, very frustrating. It’s like almost getting hit in the head with a giant lemon.

You have to be able to look at a set back and say, “Well, that sucked but it happened and I can’t change that. How can I move forward from here?”

You could spend all your time:

  • Looking at the lemon that almost hit you
  • Lamenting how heavy or how sour it is
  • Thinking about how much better it would be if it was an orange

If you do this, you’re not able to look at the opportunities that the lemon itself provides.

Instead you could say, “Okay, I have this gigantic lemon. What on earth am I going to do with this?”

Sometimes you can actually wind up with a lot of delicious lemonade.

Screen Shot 2015-05-10 at 10.23.15 PM

In the literal case, one giant lemon, it turns out, can make more than half a gallon of lemonade.

In the figurative case, I’d actually originally intended to go back to school and get my master’s in computer science, but I quickly realized when I went to do this that I was not academically qualified. To get academically qualified was going to take years if it could be done at all.

I was crushed for a while after I found this out. Then I realized that moping was going to do me about as much good as staring at a lemon wishing it were lemonade. I had to regroup.

I did some research and I found a more professionally targeted UCLA extension program and I realized I have this lemon of not being able to get a master’s in computer science, but I have this other opportunity that could get me to be a working software engineer much faster. The figurative lemonade has really been my entire iOS career.

Lesson 3: Change Does Not Mean You Failed

The third lesson may not apply to everyone, but for those of us who it does apply to it is a big one: Change is not an admission of failure.

I have always been terrified of failure. I was a go-getter. I was a grade-grubber. I was a goody-two-shoes. Forty other synonyms for complete nerd.

Attribution: flickr.com

Attribution: flickr.com

A grade of ‘B’ in school meant that I was slacking. The couple of times I got a ‘C’ it was as if the world had fallen apart, broken until that got pushed back up to at least an ‘A-‘.

I’ve always been raised with the idea that if I tried hard enough, I could make anything happen.

Part of why I was so terrified of starting over was the implicit acknowledgement that what I had been trying before just wasn’t working no matter how hard I tried. I thought that it was admitting that I failed.

It took the benefit of hindsight to realize that it wasn’t an admission of failure. It was simply an admission that what I had been trying before wasn’t for me.

When I released myself from the expectation that I had to succeed at every single thing that I tried, starting over with a different thing became far, far easier.

Lesson 4: You Never Know What Transfers

The fourth lesson I learned is: You never know what transfers.

As an example, when I worked in a television industry I’ve worked with a lot of big personalities. People who wanted things the way they wanted them and wanted them that way yesterday. From working with these people I learned the absolutely critical nature of expectation setting.

For the demanding people that I worked for,

  • if you told them something was going to happen to make them happy and then it did not happen, they were furious.
  • If you told them the incremental steps that were going to happen and you did not over commit, they were always happy because they were informed about the progress of what was happening. They could follow that progress.

Screen Shot 2015-05-11 at 5.05.34 PM

I haven’t dealt with anybody in tech nearly as nuts as some of the folks that I worked with in the entertainment industry. Anybody here who’s had to work with a client is probably nodding in recognition right now because that technique that I learned to cope working for total Looney Tunes proved really, really useful in simply dealing with businesses who need to make decisions based on the schedule that you give them.

You will find that when you start over you have skills that transfer over in complete unexpected ways. The things that you learned that you think are very specific to your industry, especially when it comes to dealing with people, can help you out immensely.

Lesson 5: You Can Learn Anything

Finally, this leads into the most important thing that I learned: You can learn anything as long as you know how to learn.

One of the things that always terrified me about starting over was the idea that I would be throwing away everything that I had learned about the thing that I had already been doing.

  • How did knowing how to tune a guitar apply to ordering film?
  • How did knowing how to find a three-foot technocrane the day before our shoot transfer to building a UI pop over controller replacement?

What I realized was that in all of my attempted careers, I’d actually learned how to research things.

Research champion

Research champion!

I learned how to word Google searches very precisely so that it would always give me back exactly what I was looking for. Whether it was:

  • How to play a given song on the guitar
  • How to install a firmware update for a particular Windows machine
  • The exact wording of a very, very long UIGestureRecognizerDelegate method

When I started programming I was already miles ahead of other people in my classes because I could coax useful information out of the Apple and Android docs, Stack Overflow, and other online resources way more efficiently.

The power of learning has become newly clear with Swift.

swift-logo

We have all had to start over again. To come from a very traditionally object oriented language to a more functional one; to learn an entire new syntax, one that sometimes requires us to tie our pinkies to our ring fingers to keep from typing semicolons.

It’s been hard, but if you’ve learned how to learn, and not just how to do one specific thing, you can do this, and we will. I, for one, am so, so excited to be learning this new language.

Starting Over Is Exciting

In conclusion, I really hope that I have inspired you all:

  • To challenge your passion
  • To realize that you know so much more than you think you do
  • To remember you can learn even more than you already know

The next time you wonder, “How heck did I wind up here,” I hope you can remember not to see change as failure and instead to make lemons into lemonade.

The fact of the matter is that while starting over can be terrifying, it’s also the most exciting thing in the world.

Note from Ray: Did you enjoy this inspiration talk? If so, sign up to our RWDevCon newsletter to be notified when RWDevCon 2016 tickets go on sale!

RWDevCon Inspiration Talk – Starting Over by Ellen Shapiro is a post from: Ray Wenderlich

The post RWDevCon Inspiration Talk – Starting Over by Ellen Shapiro appeared first on Ray Wenderlich.

Video Tutorial: CALayer Part 0: Introduction

$
0
0

Challenge

Your challenge is to watch the rest of the series and practice what you’ve learned at the end of each video by completing the challenges there.

Download lecture slides

We’ve added a new feature to our newest videos, English subtitles! You can now click the ‘CC’ button in the video player bar to turn subtitles on or off.

Video Tutorial: CALayer Part 0: Introduction is a post from: Ray Wenderlich

The post Video Tutorial: CALayer Part 0: Introduction appeared first on Ray Wenderlich.

ResearchKit Tutorial with Swift: Getting Started

$
0
0

researchkit_logo

In April 2015, Apple enacted its vision to advance medical research by sharing ResearchKit, a new open source framework which includes all the elements you need to create an app for a medical study. Within moments, your study can be available to millions of potential test subjects who have a powerful iOS device with them at all times!

And since the main competitors of ResearchKit in the study-recruitment space are the tabbed fliers posted in cafés and on college bulletin boards, Apple is well-poised to make a significant impact in the area of large-scale research studies.

But you can share in this opportunity and build your own research app — and even to contribute to ResearchKit itself!

This ResearchKit tutorial will show you how to verify user consent, collect qualitative and quantitative information with a survey, and use an active task to record audio clips with the iPhone microphone.

But first, a few points about what ResearchKit is and isn’t:

  • It is a tool for research studies, not for medical treatment itself.
  • It does help you easily obtain user consent, but does not replace HIPAA or IRB approval. You are responsible for ensuring your app follows all applicable laws. Note that Apple’s Review Guideline 27.10 specifically requires you obtain IRB approval.
  • It does help you collect data, but does not provide mechanisms for getting this data to your secure server.
  • It uses data from public HealthKit and CoreMotion APIs, but does not collect background sensor data directly.
Note: For more info on HealthKit integration, see HealthKit Tutorial with Swift: Getting Started

Getting Started

This tutorial’s sample app, Camelot, simulates a research study delving into the following question: “Does one’s name, quest, or favorite color affect vocal chord variations?” Just to keep things simple, the airspeed velocity of an unladen swallow is assumed to be a constant in this case. :]

To begin, create a new project in Xcode using File\New\Project and choose Single View Application. Name the product Camelot, select Swift for the language, and choose iPhone for the device as shown below:

Create a Swift project

Next, you’ll need to include ResearchKit in your project. If you prefer to use a dependency manager such as CocoaPods or Carthage, you can follow the directions for these tools in the ResearchKit docs and bypass the rest of this section.

Note: Need an introduction to CocoaPods? Take a look at the Introduction to CocoaPods Tutorial on this site.

To proceed without a dependency manager, simply clone or download ResearchKit on GitHub. This specific commit was used when writing this tutorial – if you’re having problems, you may wish to use that version rather than the latest content of the master branch.

The repository includes the following:

  • The ResearchKit core framework, including modules contributed by Apple and other developers.
  • A sample project entitled ORKCatalog.
  • Documentation for the framework and for the module types.

Drag ResearchKit.xcodeproj from Finder into your Xcode project. Your Project Navigator should now look like this:

Project structure

Next, select Camelot.xcodeproj in the Project Navigator, choose the Camelot target and the General tab, and then click +under Embedded Binaries, shown below:

3_add_embedded_binary

Finally, select ResearchKit.framework and click Add:

4_add_researchkit_framework

ResearchKit is now included in your project and ready for use. To make sure it’s been included correctly, add the following import to the top of ViewController.swift:

import ResearchKit

Build your project; if your build succeeds, you’re ready to start using the ResearchKit framework!

5_build_success

Informed Consent

A crucial piece of a medical research study is the consent of the test subject. This is an ethical mandate that dates all the way back to the Hippocratic Oath over two thousand years ago; this mandate has been supplemented with modern laws that may vary among the regions where your app is available.

It’s your job to make sure your study obtains consent in a legal manner, and the Consent Module included in ResearchKit is a great place to start as you can spell out the goals and requirements of the study in a series of views with simple, engaging animations.

To begin, create a new, empty Swift file named ConsentDocument.swift, then add to it the following code:

import ResearchKit
 
public var ConsentDocument: ORKConsentDocument {
 
  let consentDocument = ORKConsentDocument()
  consentDocument.title = "Example Consent"
 
  //TODO: consent sections
 
  //TODO: signature
 
  return consentDocument
}

Here, you’ve created an ORKConsentDocument, ResearchKit’s representation of the informed consent document for your study. Think of it as the stack of papers on the clipboard handed to you when you arrive at the lab, ready for your signature at the bottom of each page.

6_orkconsentdocument

Consent Document Contents

The first thing you’ll need to do is define the series of steps you need to spell out the ways this study might impact the user. In ConsentDocument.swift, replace //TODO: consent sections with the following code:

let consentSectionTypes: [ORKConsentSectionType] = [
  .Overview,
  .DataGathering,
  .Privacy,
  .DataUse,
  .TimeCommitment,
  .StudySurvey,
  .StudyTasks,
  .Withdrawing
]

An ORKConsentSectionType is an enum that designates a pre-fab page that covers part of the consent document. You’ve simply defined an array of these enums you’ll use when creating consent sections for displaying the various pages.

Note: If you order the ORKConsentSectionType array in the specific order given above, the pages will automatically have smooth, animated transitions as the user navigates forward. They look quite fancy, if you ask me! :]

These sections are only recommended, though, not mandatory. If your study doesn’t need any or all of these sections, you can remove them as required, or use one of the following options for ORKConsentSectionType:

  • .Custom: These sections have no default content, so you can add anything you need with text, images, or HTML.
  • .OnlyInDocument: These sections aren’t displayed to the user, but their contents are included in the summary document for the user’s approval.

Now that you’ve identified the section types to use, you need to create them and give them some content.

Add the following code just below the spot where you defined consentSectionTypes:

var consentSections: [ORKConsentSection] = consentSectionTypes.map { contentSectionType in
  let consentSection = ORKConsentSection(type: contentSectionType)
  consentSection.summary = "If you wish to complete this study..."
  consentSection.content = "In this study you will be asked five (wait, no, three!) questions. You will also have your voice recorded for ten seconds."
  return consentSection
}
 
consentDocument.sections = consentSections

Here you iterate through the consentSectionTypes array and create an ORKConsentSection for each type. These sections correspond to pages in the consent form. Each section has a default image based on the type, which you can change by setting the customImage property.

The textual content is set by the summary and content properties which provide the title and text for each section. In a real app, you’d definitely use different text on each page, according to its purpose. But for this tutorial, you can simply add the same summary and content to each section.

Collecting a Consent Signature

Signature collection comes built-in with ResearchKit — how easy is that? :]

Replace the //TODO: signature line in ConsentDocument.swift with the following:

consentDocument.addSignature(ORKConsentSignature(forPersonWithTitle: nil, dateFormatString: nil, identifier: "ConsentDocumentParticipantSignature"))

Yup — that’s all the code you need! The only parameter required to create an ORKConsentSignature is identifier, which is a unique String that will distinguish this signature from any other potential signatures that could be present in the document.

Note: An ORKConsentSignature can also be pre-populated with a name, image and date. This is useful when you need to include a copy of the principal investigator’s signature in the consent document.

The Consent Task

Now that you have the consent document defined, you have to add it to a task in order to present it to the user. Tasks are broken down into two categories: Visual Consent, which are the screens defined by your ORKConsentSections; and Consent Review which involve collection of the signature.

To start, create a new Swift file named ConsentTask.swift, and add to it the following code:

import ResearchKit
 
public var ConsentTask: ORKOrderedTask {
 
  var steps = [ORKStep]()
 
  //TODO: Add VisualConsentStep
 
  //TODO: Add ConsentReviewStep
 
  return ORKOrderedTask(identifier: "ConsentTask", steps: steps)
}

This is the first direct appearance of an ORKTask: a protocol which is one of the core organizational units of ResearchKit. Tasks in ResearchKit act as a collection of steps, and an ORKOrderedTask is a common class that implements the ORKTask protocol by presenting its steps in a fixed order.

Note: The "ConsentTask" identifier serves to distinguish this task for the purposes of handling its results. The results are outside the scope of this tutorial, but I encourage you to take note of the task identifiers in the sample code and try to retrieve the results yourself.

Now you need to add your Visual Consent Step.

Still in ConsentTask.swift, replace //TODO: Add VisualConsentStep with the following code:

var consentDocument = ConsentDocument
let visualConsentStep = ORKVisualConsentStep(identifier: "VisualConsentStep", document: consentDocument)
steps += [visualConsentStep]

Here, you make use of the ConsentDocument from above and use it to create an ORKVisualConsentStep. In other words, you’re telling ResearchKit to create a visual representation of the consent document sections.

Next up is the Consent Review Step.

Replace //TODO: Add ConsentReviewStep with the following code:

let signature = consentDocument.signatures!.first as! ORKConsentSignature
 
let reviewConsentStep = ORKConsentReviewStep(identifier: "ConsentReviewStep", signature: signature, inDocument: consentDocument)
 
reviewConsentStep.text = "Review Consent!"
reviewConsentStep.reasonForConsent = "Consent to join study"
 
steps += [reviewConsentStep]

The ORKConsentReviewStep sets up screens to summarize the consent document, to determine if the user agrees or disagrees to the terms, and to obtain the user’s signature. Just like the ORKConsentSections you defined earlier, the consent review section requires you to set text for the page.

You’ve added both steps to the consent task — all that’s left for the consent portion of your app is to show this task to your user and handle the results.

Presenting the Consent Task

This is a job for your view controller, so open ViewController.swift and add the following:

extension ViewController : ORKTaskViewControllerDelegate {
 
  func taskViewController(taskViewController: ORKTaskViewController, didFinishWithReason reason: ORKTaskViewControllerFinishReason, error: NSError?) {
    //Handle results with taskViewController.result
    taskViewController.dismissViewControllerAnimated(true, completion: nil)
  }
 
}

Your view controller now implements ORKTaskViewControllerDelegate by handling task results in taskViewController:didFinishWithReason:error:. These results could be in the form of a signed consent document, survey responses, or sensor data. For now, you are simply dismissing the task’s view controller when the task finishes.

How, then, can you present the task? Add the following method to the ViewController class:

@IBAction func consentTapped(sender : AnyObject) {
  let taskViewController = ORKTaskViewController(task: ConsentTask, taskRunUUID: nil)
  taskViewController.delegate = self
  presentViewController(taskViewController, animated: true, completion: nil)
}

This is a simple method in which you create an ORKTaskViewController with your consent task. ResearchKit will create the UI all on its own from the information contained in the task you pass in.

Once you’ve set the view controller as the task view controller’s delegate, you present the view controller. Now all that remains is to trigger consentTapped!

Open Main.storyboard and add a UIButton to the lone view.

Then, set the button’s title to Consent and connect the button to consentTapped: in your view controller as shown below:
7_consent_tapped

It’s the moment you’ve been waiting for!

Build and run your app; first, page through the cool-looking consent flow:

8_consent_task

Take note of all the nice UI presentation and animations that you get for free with ResearchKit; in particular, check out the study detail modal screens. Note how ResearchKit displays your sample text, and how it orders the pages as you defined them.

Once you’ve run through the consent pages, test out the signature screen:

Drawing on the simulator with a trackpad was harder than I had anticipated.

Drawing on the simulator with a trackpad was harder than I had anticipated.

Note: You may notice that the console outputs several log statements as you test your application. These only happen in DEBUG mode, but you can optionally remove these by clearing the definition for ORK_Log_Debug in ORKHelpers.h within ResearchKit.

The Survey Module

Now that you’ve set up the consent portion of your app, you can move on to the meat of your app: the survey. In this section, you’ll create a survey task and present it the same way you did with your consent task.

Create a new Swift file in your project named SurveyTask.swift and populate it with the following code:

import ResearchKit
 
public var SurveyTask: ORKOrderedTask {
 
  var steps = [ORKStep]()
 
  //TODO: add instructions step
 
  //TODO: add name question
 
  //TODO: add 'what is your quest' question
 
  //TODO: add color question step
 
  //TODO: add summary step
 
  return ORKOrderedTask(identifier: "SurveyTask", steps: steps)
}

You might have already guessed that your survey would be an ORKOrderedTask, just like your ConsentTask. The difference lies in the steps that you’ll be adding.

Instructions Step

The first step simply displays your survey’s instructions to the user. Replace //TODO: add instructions step with the following:

let instructionStep = ORKInstructionStep(identifier: "IntroStep")
instructionStep.title = "The Questions Three"
instructionStep.text = "Who would cross the Bridge of Death must answer me these questions three, ere the other side they see."
steps += [instructionStep]

This creates and adds an ORKInstructionStep, which is a simple yet highly useful screen you can use any time you need to present instructions to your user. You can optionally include an image via the image property, but that’s not necessary here.

Text Input Question

Next up is your first question, which is an open-ended question that permits user input. Replace //TODO: add name question with the following:

let nameAnswerFormat = ORKTextAnswerFormat(maximumLength: 20)
nameAnswerFormat.multipleLines = false
let nameQuestionStepTitle = "What is your name?"
let nameQuestionStep = ORKQuestionStep(identifier: "QuestionStep", title: nameQuestionStepTitle, answer: nameAnswerFormat)
steps += [nameQuestionStep]

An ORKQuestionStep, like the one you created in the previous section, presents the user with a single question. The answer: parameter, which is of type ORKAnswerFormat, determines the UI for the user input. You’ve used ORKTextAnswerFormat, which lets the user type in their name using the keyboard.

Text Choice Question

Next up is a question where the user must choose among several predefined options. Replace //TODO: add 'what is your quest' question with the following:

let questQuestionStepTitle = "What is your quest?"
let textChoices = [
  ORKTextChoice(text: "Create a ResearchKit App", value: 0),
  ORKTextChoice(text: "Seek the Holy Grail", value: 1),
  ORKTextChoice(text: "Find a shrubbery", value: 2)
]
let questAnswerFormat: ORKTextChoiceAnswerFormat = ORKAnswerFormat.choiceAnswerFormatWithStyle(.SingleChoice, textChoices: textChoices)
let questQuestionStep = ORKQuestionStep(identifier: "TextChoiceQuestionStep", title: questQuestionStepTitle, answer: questAnswerFormat)
steps += [questQuestionStep]

This time, the answer format is ORKTextChoiceAnswerFormat. You define the possible choices for the user, create the question step and then add it to the task.

Note: The ORKTextChoiceAnswerFormat format is flexible, and allows for either single-choice or multiple-choice. In this example, you’ve specified .SingleChoice

Image Choice Question

The last question of your survey is similar to the text choice format, in that it requires the user to choose among several predefined options, but with one key difference: the choices are represented by images, not just text.

Download and unzip this pack of six PNG images. Then, add them to your Xcode project in Images.xcassets:

10_add_images

Once you’ve added the images to your project, return to SurveyTask.swift and replace //TODO: add color question step with the following:

let colorQuestionStepTitle = "What is your favorite color?"
let colorTuples = [
  (UIImage(named: "red")!, "Red"),
  (UIImage(named: "orange")!, "Orange"),
  (UIImage(named: "yellow")!, "Yellow"),
  (UIImage(named: "green")!, "Green"),
  (UIImage(named: "blue")!, "Blue"),
  (UIImage(named: "purple")!, "Purple")
]
let imageChoices : [ORKImageChoice] = colorTuples.map {
  return ORKImageChoice(normalImage: $0.0, selectedImage: nil, text: $0.1, value: $0.1)
}
let colorAnswerFormat: ORKImageChoiceAnswerFormat = ORKAnswerFormat.choiceAnswerFormatWithImageChoices(imageChoices)
let colorQuestionStep = ORKQuestionStep(identifier: "ImageChoiceQuestionStep", title: colorQuestionStepTitle, answer: colorAnswerFormat)
steps += [colorQuestionStep]

The key to this question is, again, the answer’s format. Here, you’ve used ORKImageChoiceAnswerFormat, which you initialized with an array of image choices of type ORKImageChoice.

Each ORKImageChoice instructs the step to display an image; when the user selects an image, the step displays the image’s text from the name property and passes the image’s value to the results. ResearchKit takes it from here, and constructs your screen using these images to display a series of buttons.

Summary Step

It’s a good practice to notify your user when the survey is complete; therefore, you’ll need to add a summary step.

Replace //TODO: add summary step with the following:

let summaryStep = ORKCompletionStep(identifier: "SummaryStep")
summaryStep.title = "Right. Off you go!"
summaryStep.text = "That was easy!"
steps += [summaryStep]

Here you create and add an ORKCompletionStep, which is essentially the same as an ORKInstructionStep, except with a nice animated checkmark in the center to thank your user for completing the survey.

Presenting the Survey

Presenting the the survey task is identical to the way you present the consent task. Open ViewController.swift and add the following method:

@IBAction func surveyTapped(sender : AnyObject) {
  let taskViewController = ORKTaskViewController(task: SurveyTask, taskRunUUID: nil)
  taskViewController.delegate = self
  presentViewController(taskViewController, animated: true, completion: nil)
}

Again, you create an ORKTaskViewController, set the current view controller as its delegate, and finally present it.

Open Main.storyboard, add a UIButton with the title Survey, and connect it to surveyTapped: as shown below

11_survey_tapped

Build and run your app; work through your survey and you will see the instruction and summary steps, followed by your three survey questions:

Uses ORKTextAnswerFormat

Uses ORKTextAnswerFormat

Uses ORKTextChoiceAnswerFormat

Uses ORKTextChoiceAnswerFormat

Uses ORKImageChoiceAnswerFormat

Uses ORKImageChoiceAnswerFormat

Active Tasks

Active Tasks use on-device sensors, such as the accelerometer, gyroscope, microphone and even the touchscreen, to record data for analysis purposes. In this example, you’ll use the iPhone’s microphone to record audio samples for your study.

Create a new Swift file in your project and name it MicrophoneTask.swift. Populate it with the following code:

import ResearchKit
 
public var MicrophoneTask: ORKOrderedTask {
  return ORKOrderedTask.audioTaskWithIdentifier("AudioTask", intendedUseDescription: "A sentence prompt will be given to you to read.", speechInstruction: "These are the last dying words of Joseph of Aramathea", shortSpeechInstruction: "The Holy Grail can be found in the Castle of Aaaaaaaaaaah", duration: 10, recordingSettings: nil, options: nil)
}

Here you’re using an ORKOrderedTask with a custom initializer which produces an audio task that displays your instructions and records the user’s voice for a length of time.

Yup, it’s that simple — you simply specify the instructions and the duration of your task, and ResearchKit provides the rest of the UI for free! :]

The final step is to connect this task to your UI. Add the following method to ViewController.swift:

@IBAction func microphoneTapped(sender : AnyObject) {
  let taskViewController = ORKTaskViewController(task: MicrophoneTask, taskRunUUID: nil)
  taskViewController.delegate = self
  taskViewController.outputDirectory = NSURL(fileURLWithPath: NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as! String, isDirectory: true)
  presentViewController(taskViewController, animated: true, completion: nil)
}

This should look familiar by now, except for one new line where you specify a valid NSURL to taskViewController.outputDirectory. The ResearchKit documentation states the following: “If no output directory is specified, active steps that require writing data to disk, such as those with recorders, will typically fail at runtime.”

Finally, open Main.storyboard, add a third UIButton titled Microphone, and connect it to microphoneTapped: as shown below:

15_microphone_tapped

Build and run your app; tap the Microphone button to try out your new task. In the simulator, the task will simply count down, but if you run your app on a real device you can watch the waveform react to your voice:

16_microphone_waveform

Where to Go From Here?

You can download or clone the fully finished sample project here.

In this tutorial you covered all three ResearchKit modules: surveys, informed consent, and active tasks. These all have the end goal of obtaining data from the user, which is what ResearchKit is all about! :]

There are, of course, additional steps in a real-world study. You’d likely need to schedule these tasks to run on a recurring basis, and you’d need to get this data to a server where it could be aggregated and studied. Neither of these are built into ResearchKit at the time of this writing, but Apple and/or the ResearchKit community could certainly add this in the future.

ResearchKit is capable of far more than the topics covered in this tutorial. Try out the ORKCatalog project included with ResearchKit to see additional possibilities for your research apps, such as result analysis, other types of sensor data, and more.

ResearchKit is already being used in the following active research studies:

You may want to join one of these studies, if you’re eligible to participate, and form a stronger concept of the desired user experience in ResearchKit apps. Of course, your participation may also help advance some important research!

ResearchKit is an open source framework, so if you want to request a feature or even contribute, simply open an issue or submit a pull request on GitHub. You can learn more about how to contribute here.

Remember that ResearchKit does not replace approval from an institutional review board or ethics committee, and compliance with HIPAA guidelines and international regulations is something you’ll have to handle on your own, if your study requires it.

Thank you for working through this ResearchKit tutorial — and I’m excited to see all the contributions you’ll make to future research studies. If you have any questions about this tutorial, feel free to join the discussion below!

ResearchKit Tutorial with Swift: Getting Started is a post from: Ray Wenderlich

The post ResearchKit Tutorial with Swift: Getting Started appeared first on Ray Wenderlich.

Video Tutorial: CALayers Part 1: Getting Started


Standing Out In the Crowd with Brian Mueller – Podcast S04 E03

$
0
0
Learn how to make your apps stand out from the crowd!

Learn how to make your apps stand out from the crowd!

In this episode, we chat with Brian Mueller, indie iOS developer and creator of the popular CARROT apps, about how you can make your apps stand out in the App Store.

[Subscribe in iTunes] [RSS Feed]

Our Sponsor

Interested in sponsoring a podcast episode? We sell ads via Syndicate Ads, check it out!

Links

Contact Us

Where To Go From Here?

We hope you enjoyed this episode of our podcast. Be sure to subscribe in iTunes to get notified when the next episode comes out.

We’d love to hear what you think about the podcast, and any suggestions on what you’d like to hear next season. Feel free to drop a comment here, or email us anytime at podcast@raywenderlich.com.

Standing Out In the Crowd with Brian Mueller – Podcast S04 E03 is a post from: Ray Wenderlich

The post Standing Out In the Crowd with Brian Mueller – Podcast S04 E03 appeared first on Ray Wenderlich.

Readers’ App Reviews – May 2015

$
0
0
MonsterTrucks

May the apps be with you!

May is here and so are many of our Apple Watches. Many of you have been hard at work to make sure us early adopters don’t have empty watches. The first raywenderlich.com tutorial-driven Apple Watch apps are here!

This month we’ve got a full roster of apps:

  • A Mac app we can all appreciate
  • Apps for your Apple Watch
  • Some apps to get us out and about
  • And of course, much more!

Read on to see a portion of what the community is building this month.

LinuxDocs

LinusDocs
As developers man pages have a special place in our hearts. The time inevitably comes when we need to sprinkle some incantations into the terminal and hope for the best. But those commands don’t need to be a mystery, LinuxDocs is here to help.

LinuxDocs brings a huge collection of manpages right to your iPhone. They’re stored offline so you never have to worry about being without. You’ll be able to easily search and filter them. But if you just need a quick fix, cheatsheets are the tldr version build right in the app with common commands and combinations shown.

Bit Journey

BitJourney
Bit Journey drops you into a huge open world filled with opportunities and enemies. The world is filled with travel vortexes spawning endless enemies seeking to dominate the world. You’re left to survive as long as you can against the army of enemies filling the world.

You can command one of three heroes to survive the world. Choose from a ninja, soldier, or medieval warrior. Everything is destructible. Burrow into the ground to avoid enemies but be careful, skeletons lurk below. Conquer secret bases, accomplish difficult missions, and improve your character’s skills.

Paste

Paste
Copy and Paste as a longtime feature on Macs hasn’t changed much over the years. Paste is a powerful clipboard manager for your Mac that teaches your computer some fancy new tricks.

Paste saves a history of all the things you’ve copied for later. A simple keystroke shows everything you’ve copied in a beautiful fullscreen interface. You can select individual copies to paste them or even share them with other applications You can search your history by content, type, and application it was copied in.

Moon Tunes

MoonTunes
Moon Tunes is a Music App replacement designed specially for kids. Rather than relying heavily on text that requires children be able to read, Moon Tunes relies entirely on color and symbols. Parents can easily add music to the app from their iTunes libraries, selecting a color and symbol for each song they add.

Kids easily mentally link their favorite songs with colors and symbols and can quickly find the song they’d like to listen to in one of three interactive music players. The music players feature additional sound effects to spice up the music and cute graphics. Kids will love listening to their music in Moon Tunes.

QR Studio Pro

QR Studio
QR Studio Pro is a full featured QR scanner and generator. QR Studio Pro lets you generate a variety of QR codes with various colors and layouts making them instantly sharable.

QR Studio Pro is also a powerful QR scanner with extra fast decoding. You can decode from the camera, imports, and Copy/Paste. There is also an iOS extension so you can use QR Studio Pro within other apps when QR scanning is needed.

And with support for the Apple Watch, you’ll be ready to present your QR codes anytime, anywhere. And Pan was nice enough to share some promo codes for everyone. So snag em quick! XYYJFJ374T9L, JWKEX47FJF97

WebWatch

WebWatch
Checking websites for status updates is a fact of life in today’s world. Sports scores, order statuses, price changes, daily content, etc are all things we check everyday, often many times a day.

WebWatch makes it easier than ever to track your favorite website. Simply navigate to your favorite website then crop the section you’d like to see. Every so often, WebWatch will automatically refresh the site and snap a screenshot.

WebWatch will sync up to 6 websites to your Apple Watch for quick checks. WebWatch also has a today widget for quick checks on the iPhone as well.

Curve Run

CurveRun
Curve Run is an addictive minimal arcade style game. As you roll along the track, you’ll have to dodge the obstacles while collecting as many stars as possible. The controls are easy to learn, hold left to ride the left side of the track, hold right to ride the right. releasing your touch will leave you in the center of the track.

While its easy to learn, its certainly difficult to master. Obstacles become more difficult while the track becomes faster. See how your scores stack up against the world and friends on the GameCenter leaderboards. Challenge friends and strangers in realtime over GameTime for the endurance race of your life.

Block Racer

BlockRacer
Block Racer is a retro racer thats beautiful in its simplicity. Just tap and hold to speed up, release to slow down. The race track spans just one screen.

There are of course obstacles in your way. Don’t jump the ramps too quickly or risk falling apart. Avoid the acid drips as they fall from the sky. Watch out for the menacing spike traps. And be prepared for cannon fire and time your jumps accordingly.

There are 50 levels to battle through. And GameCenter leaderboards will make sure your friends know how whose the best.

Monster Trucks for Babies

MonsterTrucks
Monster Trucks is perfect for the iPad’s youngest fans. Perfectly suited for 1-4 year olds, Monster Trucks is advertisement and in app purchase free so kids are free to play.

There are twelve awesome monster trucks to choose from and seven color race tracks. There are ramps, tire stacks, traffic cones, and of course cars to run over. Controls are super easy to get your monster truck roaring down the track. And just to make sure you have plenty of fun, there are rockets attached so your truck can do more than roar.

Born 2 Bike

Born2Bike
Born 2 Bike is purpose built for anyone taking advantage of bike rental services. If you’ve got a bike rental service in your city, Born 2 Bike might be for you.

Born 2 Bike is in more than ten countries and fifty cities. Born 2 Bike will show you the nearest stations so you can pick up a bike fast. Stations will show you the number of available bikes and open parking slots. You can favorite your frequent stations or share them with friends. Then you can use Born 2 Bike to keep track of time and avoid late fees. You can also see bike stations along a map so you can find a drop-off zone on your way.

Simply Smoothies

Smoothies
Simply Smoothies is perfect for keeping track of your favorite and in progress smoothie recipes. Simple Smoothies has more than 100 greens, fruits, veggies, nuts, proteins, sweeteners, and other ingredients to build your smoothies from.

Simply Smoothies will help guide you to appropriate amounts for each ingredient to ensure a balanced, delicious smoothie. Simply Smoothies will even calculate Nutrition Facts for your smooth recipe.

To top it off, Simply Smoothies has an Apple Watch extension so you can access your smoothie recipes write from your wrist.

AnyTrail

AnyTrail
AnyTrail is an easy to use trail recorder sitting right in your pocket.

AnyTrail will plot and save your path as you go. Its easy to see your past expeditions, retrace your steps, or share favorite trails with friends. You can add photos and videos to your trails. Take notes based on location to avoid any pitfalls the next time.

AnyTrail also has all the essential trail recorder information such as trail length, trek duration, start time, average speed. If you enjoy hiking this is a worthwhile app to have in your pocket.



Honorable Mentions

Each and every month I get more submissions than I have time to review. I download every app and see what its about, but I can’t write about them all. I love seeing all the apps submitted by readers like you. Its no a popularity contest or even a favorite picking contest. I just try to get a glimpse of what the community is working on through your submissions. Take a moment and checkout these other great apps I didn’t have time to showcase properly.

Division Z
Car Parking free
Line Duel
Space Troubles
Weasel&Bird
Tenorshare Card Data Recovery
Battery Adviser
MosaicImage
Hexaplay
Snappy Word
Dodging Asteroids
Make Your Song
Custom Conga
QuickSchedule
Brainess
Todoly Reminders
Rhyming Words Target Shooting
Periodic Table Investigator
Bubble Pop Letters Numbers Colors and Shapes
BlastRPG
Bouncing Bird: The Bird’s Adventure
Read To Me World
hooploopn
Hexiz FREE
RGB 9
Chess Meister
Walk Me Alarm Clock
Run2Earth
Redacted



Where To Go From Here?

Each month, I really enjoy seeing what our community of readers comes up with. The apps you build are the reason we keep writing tutorials. Make sure you tell me about your next one, submit here!

If you saw an app your liked, hop to the App Store and leave a review! A good review always makes a dev’s day. And make sure you tell them you’re from raywenderlich.com; this is a community of makers!

If you’ve never made an app, this is the month! Check out our free tutorials to become an iOS star. What are you waiting for – I want to see your app next month!

Readers’ App Reviews – May 2015 is a post from: Ray Wenderlich

The post Readers’ App Reviews – May 2015 appeared first on Ray Wenderlich.

Video Tutorial: CALayers Part 2: CAGradientLayer

How To Create a Cool 3D Sidebar Animation Like in Taasky

$
0
0
runfinal


Learn how to make a stylish 3D animation like Taasky’s open-door sidebar!

Last year, readers voted on which effect from Evan Dekhayser’s Top 5 iOS 7 Animations they most wanted to see featured in a future tutorial — and the winner? How to achieve the cool 3D effect of Taasky’s slide-out menu!

This tutorial is for the experienced developer; you’ll be working with Auto Layout constraints, UIScrollView, view controller containment, and Core Animation. If this all sounds a bit unfamiliar, then I’d recommend you start with some of our other iOS tutorials before returning to this one!

Note: Special thanks to David Grandinetti and Mic Pringle for some of the ideas behind the sample project in this tutorial.

Getting Started

Download the starter project, extract it, and open it in Xcode.

Take a moment and have a poke around in the project; you’ll see it’s a master-detail app that displays a table of images. The UITableViewController subclass MenuViewController uses the custom table view cell MenuItemCell in order to set the background color of each cell. The DetailViewController displays a large image using the same background color as the selected cell, as shown below:

starterMasterDetail

You could imagine this as a basic app for negotiating coffee breaks or after-work cocktails with your colleagues or friends; thumbs-up if you’re game, thumbs-down if you can’t make it – and you can even decline due to inclement weather. :]

Creating the feature in this tutorial isn’t as complicated as you might think. You’ll build it up slowly as follows:

  • First, you’ll use Auto Layout in Interface Builder to convert a basic master-detail app to a horizontal scroll view, with the master and detail views embedded in containers.
  • Next, you’ll add a button to show or hide the menu.
  • Then you’ll implement the 3D effect to acheive the neat Taasky-like folding effect!
  • As a final touch, you’ll piggy-back on the menu animation to rotate the menu button, in sync with the act of showing or hiding the menu.

Your first task is to convert the menu into a slide-out sidebar, similar to the SwiftSideNav sample app from the video tutorial Swift Scroll View School Part 13, where a scroll view contains the menu and detail views side-by-side, as shown below:

diagramMenuDetail

The user can scroll right or left to show or hide the menu. The purple rectangle outlines the visible content when the menu is open, and the green rectangle outlines the detail view, which is fully visible when the menu is hidden. When the menu is open, the partial detail view provides a visual cue that the menu is a sidebar.

Note: If you’re unfamiliar with scroll views then please watch Part 1 and Part 2 of the Swift Scroll View School video series to refresh your understanding of how scroll views work.

SwiftSideNav, one of the samples from the Swift Scroll View School video series, sets up the Auto Layout constraints programmatically. But in this tutorial, you’ll set them up in directly in the storyboard, embedding the menu and detail views in container views. It will look like this when you’re done:

sbContainers

Adding Containers to UIScrollView

Note: This section relies heavily on View Controller Containment, which was introduced in iOS 5. If you’re new to this concept, check out Chapter 18, “UIViewController Containment” in iOS 5 by Tutorials.

You’ll need a new view controller to coordinate the existing menu and detail view controllers. You’ll add a scroll view to its view, then add a Content view to the scroll view. Then you’ll add two container views to the Content view and embed the existing menu and detail views in these container views. To reduce errors and confusion, you’ll set up the Auto Layout constraints as you go.

rageAutoLayoutHelpCropped

Create a new Cocoa Touch Class file named ContainerViewController, making sure to subclass UIViewController. Also set the Language to Swift:

newFileContainerVC

Note: You can zoom out the storyboard if you need to – right-click on an unoccupied part of the canvas and select one of the zoom options. Double-click anywhere on the empty canvas to return to the standard zoom. You can also zoom in and out using pinch gestures on a trackpad, or using the scroll wheel on your mouse if it has one.

Open Main.storyboard and drag a new View Controller from the Object Library onto the canvas to the left of the existing scenes. In the Identity Inspector, set Class\Custom Class to ContainerViewController:

sbIdInsp

Select your new View and set Background to Black Color in the Attributes Inspector:

sbBkgdBlack

Setting Up the Scroll View

Next, you’ll add a Scroll View to the view of ContainerViewController, then add its Auto Layout constraints.

In Interface Builder, drag a Scroll View onto ContainerViewController, and let it expand to fill the space. Next uncheck Shows Horizontal Indicator and Shows Vertical Indicator in the Attributes Inspector, to turn off the scroll view’s scroll bars. Also uncheck Delays Content Touches so that the menu will respond immediately when the user makes a selection, rather than having a slight delay:

sbScrollViewAttrs1

Control-drag from the scroll view to its view controller, and select delegate in-order to set ContainerViewController as the scroll view’s delegate:

sbSetDelegate

In the Pin constraints pop-up – found at the bottom of the Interface Builder window – uncheck Constrain to margins. Select the leading, top, trailing, and bottom constraints, make sure they’re values are all 0, and then click Add 4 Constraints to pin the four edges of the scroll view to its superview:

sbAutoScrollView

With the scroll view still selected, confirm the new constraints in the Size Inspector:

  • Trailing Space to: Superview
  • Leading Space to: Superview
  • Top Space to: Superview
  • Bottom Space to: Bottom Layout Guide

sbSizeInspScrollView

Numbers like -16 means the constraints are relative to the margin; fix these by deleting the necessary constraints and then re-pin the scroll view, being sure to uncheck Constrain to Margins.

Note: When you add or modify constraints, you might need to update the frame of a view to reflect the new constraints. Select the Resolve Auto Layout Issues button at the bottom of Interface Builder and select Update Frames as required.

Setting up the Content View

Now you’ll add a content view to the scroll view and set up its Auto Layout constraints; these constraints are important as they help determine the scroll view’s content size. In the next section, you’ll layout two container views in the content view to hold the menu and detail views.

Drag a new View onto the scroll view; let it expand to the size of the scene in Interface Builder, then set Background to Default in the Attributes Inspector:

sbSizeInspView

Open the Identity Inspector for the content view you just added and set Document\Label to Content View; this label appears in the document outline and will help you keep track of the views, and it’s also the name referenced in Auto Layout contraints. You’ll place the two container views into Content View later.

Note: You’ll see Auto Layout warnings when you set up Content View’s constraints, but don’t panic as you’ll fix them before the end of the section.

Pin the four edges of Content View to its superview, which in this case is the Scroll View:

sbAutoContentView

In the Size Inspector, ensure that the Trailing Space constraint’s Constant is set to 0:

sbSizeInspContentView2

The Auto Layout warning appears because the storyboard requires constraints on Content View’s height and width to determine the scroll view’s content size. Making these constraints relative to the scroll view’s superview lets the display adapt to various devices and orientations.

In the document outline, control-drag from Content View to View (Scroll View’s superview), hold down the Shift key, and select Equal Widths and Equal Heights:

sbAutoContainerViewEqWidth

Then edit the Equal Width constraint’s Constant to 80:

sbSizeInspContentView

Setting the constant to 80 means the Content View will be 80 points wider than the viewable area of the View so it can accommodate the menu. You’ll see the Auto Layout warnings have now disappeared – good work! :]

Adding Menu and Detail Container Views

The scroll view now has a Content View for your two container views. You’ll embed the existing menu and detail views in these container views to create a menu sidebar you can swipe open or closed.

First, add the Menu Container View: drag a Container View onto Content View. In the Size Inspector, set Width to 80, then use the Identity Inspector to set Document\Label to Menu Container View:

sbContainerMenuUtil

The Height should default to 600, but if it doesn’t make sure to set that as well.

Next, add the Detail Container View: drag another Container View to the right of the menu container within Content View. Open the Size Inspector and set the following values:

  • X: 80
  • Y: 0
  • Width: 600
  • Height: 600

Then open the Identity Inspector and set the Document\Label to Detail Container View so you can easily identify the view:

sbContainerDetailUtil

The width of the two containers now equal the entire width of the Content View:

sbContainerViews

When you add a container view, Interface Builder will include a contained view controller scene by default; but you’ll connect your container views to the existing menu and detail view controllers. Delete the view controllers that are currently embedded in the container views:

sbDeleteContainerVCs

Next, you’ll set up the Auto Layout constraints for the container views.

Pin the edges of Menu Container View its superview, and add a Width constraint with a constant of 80. You should add 5 constraints in total, as shown below:

sbAutoMenu

Pin Detail Container View’s Top, Bottom, and Trailing edges; don’t pin the Leading edge, as it would duplicate the sibling Menu Container View’s Trailing constraint:

sbAutoDetail

For both sets of contraints, make sure Constrain to margins in unchecked.

Embedding Menu and Detail View Controllers

In this section, you’ll separate the menu and detail view controllers, then embed them in Menu Container View and Detail Container View.

First, make Container View Controller the Initial view controller: drag the start arrow – which denotes the initial view controller in the storyboard – from the Navigation Controller to Container View Controller:

sbMoveStartArrow

Next, embed control-drag from Menu Container View to Navigation Controller, and select embed from the pop-up menu:

sbEmbedMenu

Once the navigation controller is embedded in Menu Container View, each of the connected view’s widths in Interface Builder automatically shrink to 80 points:

sbEmbedResult

Now to make some adjustments to the menu and detail scenes: first, change the Width of the table view cell’s image view to 80:

sbSizeInspImage

Next, delete the push segue between the menu and detail scenes. Select Detail View Controller, then select Editor\Embed In\Navigation Controller from the Xcode menu:

sbEmbedDetailNavController

The Detail View Controller should now be the initial view controller of a new navigation controller, which will provide the black navigation bar with the icon to expand the menu.

Select the navigation bar of the new navigation controller and use the Attributes Inspector to set Style to Black, uncheck Translucent, and set Bar Tint to Black Color:

sbNavBarAttr

This adjusts this navigation bar to match the navigation bar of the first navigation controller.

Then, set up the new navigation controller to match the first navigation controller. In its Attributes Inspector, make sure View Controller\Layout\Adjust Scroll View Insets is checked:

sbNavControllerLayout

Note: Checking Adjust Scroll View Insets causes the view’s content to start below the navigation bar, rather then underneath it.

Finally, embed Detail View Controller in Detail Container View. Control-drag from Detail Container View to Detail View Controller’s navigation controller, and select embed from the pop-up menu:

sbEmbedDetail

Build and run. Swipe left and right to hide or show the menu. Did you notice that you can scroll beyond the left and right edges, and stop scrolling with only part of the menu showing?

runScrollView0a

To fix these issues, change the following attributes of the scroll view using the Attributes Inspector:

  1. Check Scrolling\Paging Enabled so the container “snaps” to it’s boundaries.
  2. Uncheck Bounce\Bounces to prevent scrolling beyond the edges.

Build and run. Check that swiping right does nothing when the menu is open, and swiping left does nothing when the menu is closed. Also check that scrolling to part of the menu snaps it open. But what happens when you attempt to hide the menu?

runScrollview0b

It keeps snapping back open! This is a paging issue related to this problem discussion on StackOverflow. You’ll fix this in just a bit, once you create an outlet for the scroll view.

But there are other problems to fix first: the detail view is blank, and selecting a menu item doesn’t change anything:

runScrollview1

This isn’t surprising, since you haven’t yet adjusted the code to use the container views. You’ll first make the detail view’s navigation bar match the menu view’s navigation bar.

Editing the Code to Use Containers

Before doing anything else, copy viewDidLoad() from MenuViewController.swift into DetailViewController.swift as shown below:

override func viewDidLoad() {
  super.viewDidLoad()
  // Remove the drop shadow from the navigation bar
  navigationController!.navigationBar.clipsToBounds = true
}

This eliminates the hairline shadow beneath the navigation bar. A small detail, but it’s one of those things that gives your app polish. :]

When the user selects a table cell, MenuViewController must set DetailViewController’s menuItem property, but DetailViewController isn’t directly connected to MenuViewController anymore. Instead, the ContainerViewController will act as the mediator between the menu and the content.

Add a property for the DetailViewController to the top of ContainerViewController.swift:

private var detailViewController: DetailViewController?

Implement prepareForSegue(_:sender:) in ContainerViewController.swift with the following code:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
  if segue.identifier == "DetailViewSegue" {
    let navigationController = segue.destinationViewController as! UINavigationController
    detailViewController = navigationController.topViewController as? DetailViewController
  }
}

segue.identifier! what segue, where? Well, embedding DetailViewController in the container creates a Storyboard Embed Segue, and you must set its Identifier in the Attributes inspector.

sbsegueID

Then declare the menuItem property at the top of the class, whose didSet observer in-turn sets DetailViewController’s menuItem property:

var menuItem: NSDictionary? {
  didSet {
    if let detailViewController = detailViewController {
      detailViewController.menuItem = menuItem
    }
  }
}

There’s no longer a segue from a table view cell to the content view, but MenuViewController needs to respond when the user selects an item.

Delete prepareForSegue(_:sender:) from MenuViewController and add the following method — just be careful not to accept tableView(_:didDeselectRowAtIndexPath:) from Xcode’s list of autosuggestions by accident! :]

// MARK: UITableViewDelegate
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
  tableView.deselectRowAtIndexPath(indexPath, animated: true)
  let menuItem = menuItems[indexPath.row] as! NSDictionary
  (navigationController!.parentViewController as! ContainerViewController.menuItem = menuItem
}

Here, you simply set ContainerViewController’s menuItem property based on the selected row. This triggers the property’s didSet observer, which in-turn sets DetailViewController’s menuItem property.

As a final touch, add the following line to viewDidLoad() in MenuViewController.swift:

(navigationController!.parentViewController as! ContainerViewController).menuItem = 
  (menuItems[0] as! NSDictionary)

This sets the image in the detail view when the app is first launched.

Build and run. The detail view shows the smiley image on launch, the menu view appears along the left edge of the center view, and selecting an item displays its larger image in the detail view, as shown below:

runScrollView2

Showing and Hiding Your Menu

The menu should dismiss when the user selects an item from the menu. To do this, you need to set the scroll view content’s horizontal offset to Menu Container View’s width so the scroll view shows only Detail Container View.

You’ll first need references to the scroll view and to Menu Container View.

Create an outlet named scrollView in ContainerViewController.swift: select Scroll View in the storyboard’s document outline, open the Assistant Editor, and control-drag from Scroll View into ContainerViewController.swift. Enter scrollView for Name and click Connect:

sbConnectScrollView

Note: I’ve’ used View\Assistant Editor\Assistant Editors on Bottom to place the Assistant Editor at the foot of the Xcode window, so I didn’t have to drag things across the storyboard canvas.

Select and control-drag from Menu Container View into ContainerViewController.swift, and create an outlet named menuContainerView:

sbConnectMenuContainerView

Next, add the hideOrShowMenu(_:animated:) method to ContainerViewController.swift:

// MARK: ContainerViewController
func hideOrShowMenu(show: Bool, animated: Bool) {
  let menuOffset = CGRectGetWidth(menuContainerView.bounds)
  scrollView.setContentOffset(show ? CGPointZero : CGPoint(x: menuOffset, y: 0), animated: animated)
}

The value of menuOffset is 80 — the width of Menu Container View. If show is true, the origin of scrollView is at 0,0 and the menu is visible. Otherwise, the origin of scrollView is at 80,0 and the menu is hidden.

Now, call hideOrShowMenu(_:animated:) from the didSet observer on menuItem:

var menuItem: NSDictionary? {
  didSet {
    hideOrShowMenu(false, animated: true)
    // ...

The value of show is set to false to hide the menu when the user selects an item.

Also call hideOrShowMenu(_:animated:) in viewDidLoad() to hide the menu when the app starts:

override func viewDidLoad() {
  super.viewDidLoad()
  hideOrShowMenu(false, animated: false)
}

Build and run. It starts with the smiley image selected and the menu hidden. Slide out the menu and select an item; the detail view slides across, hides the menu and displays the new item’s image and background color:

runScrollView3

However, that paging issue remains. If you slide out the menu and don’t select an item, closing the menu causes it to spring back open. You’ll fix this by employing a UIScrollViewDelegate method.

Add the following protocol to the class declaration of ContainerViewController:

class ContainerViewController: UIViewController, UIScrollViewDelegate {

Next, add the following scroll view delegate method to ContainerViewController:

// MARK: - UIScrollViewDelegate
func scrollViewDidScroll(scrollView: UIScrollView) {
  /*
  Fix for the UIScrollView paging-related issue mentioned here:
  http://stackoverflow.com/questions/4480512/uiscrollview-single-tap-scrolls-it-to-top
  */
  scrollView.pagingEnabled = scrollView.contentOffset.x < (scrollView.contentSize.width - CGRectGetWidth(scrollView.frame))
}

This disables paging when the scroll view’s content offset equals the menu width; when the menu is completely hidden, it stays hidden. Once the user starts to slide out the menu it re-enables paging so the menu snaps open.

Build and run. The paging issue is now fixed:

runScrollView4

Looking good! But there’s still something missing. The hamburger menu button in the detail view’s navigation bar that rotates as the menu moves. Tapping it should toggle the menu open or closed.

Adding the Menu Button

Note: The hamburger icon gets a lot of negative press as it hides functionality from users; see Why We Banished the Hamburger Menu From Our iPhone App, as an example. However, the original Taasky app featured it, so you get the full hamburger meal deal in this tutorial. :]

You’ll need to set up the menu button as a custom view so that it can rotate when you reveal the menu.

Create a new Swift Cocoa Touch Class file named HamburgerView.swift, making sure to subclass UIView.

Populate the class with the following code:

class HamburgerView: UIView {
 
  let imageView: UIImageView! = UIImageView(image: UIImage(named: “Hamburger”))
 
  required init(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    configure()
  }
 
  required override init(frame: CGRect) {
    super.init(frame: frame)
    configure()
  }
 
  // MARK: Private
 
  private func configure() {
    imageView.contentMode = UIViewContentMode.Center
    addSubview(imageView)
  }
 
}

Here you set up the required initializers, both of which call through to a utility method that simply creates an image view and adds it as a subview.

In DetailViewController.swift, add the following hamburgerView property:

var hamburgerView: HamburgerView?

In viewDidLoad(), create and add an instance of hamburgerView to the navigation bar as a left bar button, including a tap gesture recognizer:

let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: “hamburgerViewTapped”)
hamburgerView = HamburgerView(frame: CGRect(x: 0, y: 0, width: 20, height: 20))
hamburgerView!.addGestureRecognizer(tapGestureRecognizer)
navigationItem.leftBarButtonItem = UIBarButtonItem(customView: hamburgerView!)

hamburgerViewTapped() will call ContainerViewController’s hideOrShowMenu(_:animated:), but what value should it pass as the show argument? You need a Bool property in ContainerViewController, to keep track of whether the menu is open or closed.

Add the folllowing property to the top of ContainerViewController.swift:

var showingMenu = false

The menu’s hidden when the app starts. Override viewDidLayoutSubviews() to hide or show the menu when the bounds change, such as when the device rotates:

override func viewDidLayoutSubviews() {
  super.viewDidLayoutSubviews()
  hideOrShowMenu(showingMenu, animated: false)
}

You no longer need viewDidLoad(), so delete it completely from ContainerViewController.swift.

Open DetailViewController.swift and add the following code:

func hamburgerViewTapped() {
  let navigationController = parentViewController as! UINavigationController
  let containerViewController = navigationController.parentViewController as! ContainerViewController
  containerViewController.hideOrShowMenu(!containerViewController.showingMenu, animated: true)
}

When the user taps the button, and the menu is hidden — if showingMenu equals false — then this method calls hideOrShowMenu(_:animated:) passing true to show the menu. Conversely, when the menu is open — showingMenu equals true — tapping the button will hide the menu.. Therefore, you must update the value of showingMenu in hideOrShowMenu(_:animated:) in ContainerViewController.swift.

Add the following line to hideOrShowMenu(_:animated:):

showingMenu = show

Build and run. Try different combinations of scrolling, selecting cells, and button-tapping to show and hide the menu:

runButton1a

There’s just one problem. If you slide the menu open or closed instead of using the button, it takes two taps of the button to get the menu to respond. Why?

runButton1b

This happens because scrolling doesn’t update the value of showingMenu. Swiping the menu open leaves the value at false. The first tap appears to do nothing as it sets the value to true, so the menu stays open. The second tap then hides the menu as it sets the value to false.

To fix this, you need to set showingMenu in one of the other UIScrollViewDelegate methods in ContainerViewController. Add the following:

func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
  let menuOffset = CGRectGetWidth(menuContainerView.bounds)
  showingMenu = !CGPointEqualToPoint(CGPoint(x: menuOffset, y: 0), scrollView.contentOffset)
  println(“didEndDecelerating showingMenu \(showingMenu))
}

When the scrolling stops, this delegate method sets showingMenu to false if the scroll view’s content offset equals the menu width — that is, the menu is hidden — otherwise it sets it to true.

Build and run. Swipe right and check the console to see if this method kicks in when you stop. It’s a bit hit or miss, and seems to depend on the scrolling speed. When I tested the app in the simulator, it only worked when I scrolled slowly, but on my iPhone, it only worked when I scrolled quickly. Go figure! :]

Move the above statements into scrollViewDidScroll(_:), where it’s much less efficient – this method is called continously as the user scrolls – but far more reliable:

runButton2

You’ll get to the button rotation in just a bit — but first, you’ll take care of the 3D menu effect.

Adding Perspective to Your Menu

The ultra-cool animated version of your menu should look similar to a door opening and closing. As well, the menu button will rotate smoothly clockwise as the menu opens, and counter-clockwise as the menu closes.

To accomplish this, you’ll calculate the fraction of the menu view that’s visible, then use this to calculate the menu’s angle of rotation.

In ContainerViewController.swift, add the following private method to create the 3D transform, depending on the fraction of the menu shown:

func transformForFraction(fraction:CGFloat) -> CATransform3D {
  var identity = CATransform3DIdentity
  identity.m34 = -1.0 / 1000.0;
  let angle = Double(1.0 - fraction) * -M_PI_2
  let xOffset = CGRectGetWidth(menuContainerView.bounds) * 0.5
  let rotateTransform = CATransform3DRotate(identity, CGFloat(angle), 0.0, 1.0, 0.0)
  let translateTransform = CATransform3DMakeTranslation(xOffset, 0.0, 0.0)
  return CATransform3DConcat(rotateTransform, translateTransform)
}

Here’s the play-by-play of transformForFraction(_:):

  • fraction is 0 when the menu is completely hidden, and 1 when the menu is completely visible.
  • CATransform3DIdentity is the 4×4 matrix with 1s on the diagonal and 0s everywhere else.
  • CATransform3DIdentity’s m34 property is the value in row 3, column 4, which controls the amount of perspective in the transform.
  • CATransform3DRotate uses angle to determine the amount of rotation around the y-axis: -90 degrees renders the menu perpendicular to the back of the view and 0 degrees renders the menu parallel with the x-y plane.
  • rotateTransform rotates the identity transform by angle degrees around the y-axis by the amount noted in its m34 perspective parameter.
  • translateTransform moves the menu from half of its width to the correct position when rotation finishes.
  • CATransform3DConcat concatenates translateTransform and rotateTransform so that the menu appears to slide sideways while rotating.

Note: m34 is usually calculated as 1 divided by a number that represents your position on the z-axis while observing the 2D x-y plane. Negative z-values indicate the viewer is in front of the plane, while positive z-values indicate the viewer is behind the plane.

Drawing lines between this viewer and the edges of objects in the plane produces the effect of 3D perspective. As the viewer moves farther away, the perspective is less pronounced. Try changing 1000 to 500 or 2000 to see how the menu’s perspective changes.

Now add the following lines to scrollViewDidScroll(_:):

let multiplier = 1.0 / CGRectGetWidth(menuContainerView.bounds)
let offset = scrollView.contentOffset.x * multiplier
let fraction = 1.0 - offset
menuContainerView.layer.transform = transformForFraction(fraction)
menuContainerView.alpha = fraction

The value of offset is between 0 and 1. When it’s 0 it means the menu is completely visible, and when it’s 1 it means the menu is completely hidden. Think of it as a measure of the menu’s hiddenness – and yes, according to my Mac’s lookup, hiddenness really is a word! :]

Consequently, fraction is the visible fraction of the menu width, ranging between 0 when the menu is completely hidden and 1 when the menu is completely visible.

You also use fraction to adjust the menu’s alpha value to darken and lighten the menu as it closes and opens respectively.

Build and run. Swipe to to see the 3D effect and…uh oh. There’s something wrong with the menu’s “hinge”, because the default anchorPoint of the view – the point at which the transform is applied – is in its centre.

runwonkyhinge

To make the menu hinge around its right edge, add the following line to viewDidLayoutSubviews() in ContainerViewController.swift:

menuContainerView.layer.anchorPoint = CGPoint(x: 1.0, y: 0.5)

Setting the x value to 1.0 move it all the way to the right-edge.

Build and run. Bask in your glorious 3D folding animation!

runPenultimate

One Last Thing: Animating the Menu Button

rageAllTheThingsCropped

Now you can put the final finishing touch on your app by rotating the menu button.

When the menu is closed, you see the standard menu icon. When the menu opens, the button should rotate 90 degrees clockwise. When the menu closes, the button should rotate counter-clockwise back to 0 degrees.

Note: Technically speaking, it’s the menu button’s imageView that you rotate. But the resulting effect is that the button itself appears to rotate.

Add the following method to HamburgerView.swift:

func rotate(fraction: CGFloat) {
  let angle = Double(fraction) * M_PI_2
  imageView.transform = CGAffineTransformMakeRotation(CGFloat(angle))
}

Here you rotate the image view smoothly. You use fraction to calculate an angle between 0 and 90 degrees, and rotate the view accordingly. For the curious ones, M_PI_2 above is defined in math.h, and is the mathematical constant for pi/2.

Now add the following lines to scrollViewDidScroll(_:), to make the view rotate as you move the scroll view:

if let detailViewController = detailViewController {
  if let rotatingView = detailViewController.hamburgerView {
    rotatingView.rotate(fraction)
  }
}

Build and run. Swipe and tap to see your animations in motion, and totally in sync:

runfinal

Where to Go From Here?

You can download the final version of the project here.

Experiment with the m34 value to see what effect it has on your transformation. If you’d like to try out more 3D transforms, take a look at Richard Turton’s Visual Tool for CATransform3D.

Wikipedia’s Perspective page also has some good photos explaining the concepts of visual perspective.

Also, think about how you could use 3D animation in your own applications to add a little bit of life to user interactions. It’s amazing how a subtle effect on something as simple as a menu can really add to the overall user experience.

If you have any questions or comments about this tutorial, please leave them in the comments below, or in the forums!

How To Create a Cool 3D Sidebar Animation Like in Taasky is a post from: Ray Wenderlich

The post How To Create a Cool 3D Sidebar Animation Like in Taasky appeared first on Ray Wenderlich.

Video Tutorial: CALayers Part 3: CAShapeLayer

Viewing all 4370 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>