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

Merry Christmas 2015!

$
0
0

As you may or may not know, we have a tradition where each year, we sing a silly Christmas song about a geeky topic.

This year, we have made a song titled “Frosty the Indie”, sung to the tune of “Frosty the Snowman.” We hope you enjoy – and we apologize in advance for our singing! :]

Lyrics and Credits

Frosty the indie (Vicki Wenderlich, Ray Wenderlich)
was a jolly happy geek (Joshua Greene)
his apps were free making no money (Tammy Coron)
but at least they had no leaks (Jeff Rames)

Frosty the indie (Brian Moakley)
is a fairytale they say (Kelvin Lau)
he could write no bugs, but the true devs know (Daniel Tavares)
how he came to be that way (Daniel Tavares)

There must have been some magic in (Tim Mitra)
that new Swift lang he found (Tim Mitra)
for when he used it in his apps (Mic Pringle)
his bug count went right down! (Todd Kerpelman)

Frosty the indie (Brian Moakley)
didn’t like Objective-C (Kelvin Lau)
he used Swift instead – optionals, he said, (Vicki Wenderlich, Ray Wenderlich)
enforce my code safety. (Todd Kerpelman)

Clackety clack clack, clackety clack clack (Vicki Wenderlich, Ray Wenderlich)
look at Frosty code (Daniel Tavares)
Clackety clack clack, clackety clack clack (Joshua Greene)
type safety he showed (Mic Pringle)

Frosty the indie (Brian Moakley)
knew Swift 2 was on its way (Jeff Rames)
so he said let’s run with inheritance fun (Jeff Rames)
before protocols invade (Jeff Rames)

Down to the conference (Mic Pringle)
with a tech talk in his hand (Daniel Tavares)
teaching here and there, his knowledge he shared (Joshua Greene)
counting all his twitter fans (Mic Pringle)

He taught around the Cocoaheads (Tammy Coron)
until he found a spot (Tammy Coron)
that had remote work and a ton of pay (Todd Kerpelman)
he imagined his new yacht (Tim Mitra)

Frosty the indie (Brian Moakley)
Had to hurry to his pay (Mic Pringle)
so he said goodbye with a big high-five (Jeff Rames)
Life with Swift is good, hooray! (Tammy Coron)

Special thanks to Ellen Shapiro for the guitar music and background singing!

But Wait, There’s More!

If you enjoyed this video, we have a few more videos you might want to check out:

That’s It!

Have a Merry Christmas and very happy New Year everyone, and thanks so much for reading this blog! :]

The post Merry Christmas 2015! appeared first on Ray Wenderlich.


Video Tutorial: CALayers: Series Introduction

Video Tutorial: CALayers Part 1: Getting Started

Creating Custom UIViewController Transitions

$
0
0
Time to master the transitioning API

Time to master the transitioning API

Push, pop, cover vertically… you get some nice view controller transitions built in to iOS, but it’s great fun to make your own. Custom UIViewController transitions can add significantly to the user experience and set your app apart from the rest of the pack. If you’ve avoided making your own custom transitions based on what you’ve heard in the past, you’ll find it’s far less work than you might expect.

In this tutorial, you’ll add some custom UIViewController transitions to a small guessing game app. By the time you’re done, you’ll have picked up the following skills:

  • How the transitioning API is structured.
  • How to present and dismiss view controllers using custom transitions.
  • How to build interactive transitions.

Note: The transitions shown in this tutorial make use of UIView animations, so you’ll need to be familiar with the topic on at least a basic level. Check out our tutorial on iOS Animation for a quick introduction to the topic.

Getting Started

Download the starter project for this tutorial. Build and run the project; you’ll see the following:

starter

Custom transitions - AND kittehs, all in the same tutorial?

Custom transitions – AND kittehs, all in the same tutorial?

The app presents several cards in a page view controller. Each card shows a description of a pet, and tapping a card reveals which pet it describes.

Your job is to guess the pet! Is it a cat, dog, or fish? Play with the app, and see how well you do.

Most of the navigation logic is already in place, but the app currently feels quite bland. You’re going to spice it up with custom transitions.

Exploring the Transitioning API

Instead of concrete objects, the transitioning API makes heavy use of protocols. By the end of this section, you’ll understand the responsibilities of each protocol and the connections between them. The diagram below shows you the main players in the API:

parts.001

The Participants

Although the diagram looks complex, it will feel quite straightforward once you understand how the various parts work together.

Transitioning Delegate

Every view controller can have a transitioningDelegate that conforms to the UIViewControllerTransitioningDelegate protocol.

Whenever you present or dismiss a view controller, UIKit queries the transitioning delegate for the animation controller to use. Setting the view controller’s transitioningDelegate to an instance of your custom class lets you return your own, custom animation controllers instead of the default ones.

Animation Controller

Objects implementing the UIViewControllerAnimatedTransitioning protocol perform the transition animations.

Transitioning Context

The context object implements the UIViewControllerContextTransitioning procotol and plays a vital role in the transitioning process: it encapsulates information about the view controllers involved in the transition.

You don’t actually need to implement this protocol in your own code. Instead, your animation controller will receive a fully configured context object from UIKit whenever a transition occurs.

The Transitioning Process

Here are the steps involved in a presentation transition:

  1. You trigger the transition either programmatically or via a segue.
  2. UIKit asks the “to” view controller (the view controller to be shown) for its transitioning delegate. If it doesn’t have one, UIKIt uses the standard, built-in transition.
  3. UIKit then asks the transitioning delegate for an animation controller via animationControllerForPresentedController(_:presentingController:sourceController:). If this returns nil, the transition will use the default animation.
  4. Once it has a valid animation controller, UIKit constructs the transitioning context.
  5. UIKit then queries the duration of the animation using transitionDuration(_:) from the animation controller.
  6. Then UIKit invokes animateTransition(_:) on the the animation controller to perform the transition.
  7. Finally, the animation controller calls the completeTransition(_:) method on the transitioning context to indicate the animation is complete.

Creating a Custom Presentation Transition

Time to put your new-found knowledge into practice!

Your goal is to implement the following animation:

  • When the user taps a card, it flips to reveal the second view scaled down to the size of the card.
  • Following the flip, the view scales to fill the whole screen.

Creating the Animator

You’ll start by creating the animation controller.

Go to File\New\File…, choose iOS\Source\Cocoa Touch Class, and click Next. Set the name to FlipPresentAnimationController, make it a subclass of NSObject and set the language to Swift. Click Next and set the Group to Animation Controllers. Click Create to make your new file.

Animation controllers need to conform to the UIViewControllerAnimatedTransitioning protocol. Open FlipPresentAnimationController.swift, and update the class declaration accordingly:

import UIKit
 
class FlipPresentAnimationController: NSObject, UIViewControllerAnimatedTransitioning {
 
}

Note that you may receive compiler errors due to missing methods; don’t panic – you’re about to fix these.

Compiler errors...don't panic...

Compiler errors…don’t panic…

You’re going to use the frame of the tapped card as a starting point for the animation. Inside the body of the class, add the following new variable to hold this value:

var originFrame = CGRect.zeroRect

In order to meet the requirements for the UIViewControllerAnimatedTransitioning, you’ll need to add two methods to the class.

Add the method below inside the class body:

func transitionDuration(transitionContext: UIViewControllerContextTransitioning) -> NSTimeInterval {
  return 2.0
}

As the name suggests, this method specifies the duration of your transition. Setting it to two seconds will prove useful during development, as it leaves enough time to observe the animation.

Now add the following method stub to the class:

func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
 
}

This protocol method is where you’ll implement the transition animation itself. Start off by inserting the following lines at the top of the method:

// 1
guard let fromVC = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey),
    let containerView = transitionContext.containerView(),
    let toVC = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey) else {
    return
}
 
// 2
let initialFrame = originFrame
let finalFrame = transitionContext.finalFrameForViewController(toVC)
 
// 3
let snapshot = toVC.view.snapshotViewAfterScreenUpdates(true)
snapshot.frame = initialFrame
snapshot.layer.cornerRadius = 25
snapshot.layer.masksToBounds = true

Here’s what’s going on above:

  1. The transitioning context will provide the view controllers and views participating in the transition. You use the appropriate keys to obtain them.
  2. You next specify the starting and final frames for the “to” view. In this case, the transition starts from the card’s frame and scales to fill the whole screen.
  3. UIView snapshotting captures the “to” view and renders it into a lightweight view; this lets you animate the view together with its hierarchy. The snapshot’s frame starts off as the card’s frame. You also modify the corner radius to match the card.

Continue by adding the following lines to the method body:

containerView.addSubview(toVC.view)
containerView.addSubview(snapshot)
toVC.view.hidden = true
 
AnimationHelper.perspectiveTransformForContainerView(containerView)
snapshot.layer.transform = AnimationHelper.yRotation(M_PI_2)

A new player appears: the container view. Think of this as the dance floor upon which your transition shakes its stuff. The container view already contains the “from” view, but it’s your responsibility to add the “to” view.

You also add the snapshot view to the container and hide the real view for now. The completed animation will rotate the snapshot out of view and hide it from the user.

Note: Don’t let AnimationHelper confuse you. It’s a small utility class, responsible for adding perspective and rotation transforms to your views. Feel free to have a look at the implementation.

At this point, you have all the necessary parts in place to perform the animation. Add the final lines of code to the bottom of the method:

// 1
let duration = transitionDuration(transitionContext)
 
UIView.animateKeyframesWithDuration(
  duration,
  delay: 0,
  options: .CalculationModeCubic,
  animations: {
    // 2
    UIView.addKeyframeWithRelativeStartTime(0.0, relativeDuration: 1/3, animations: {
      fromVC.view.layer.transform = AnimationHelper.yRotation(-M_PI_2)
    })
 
    // 3
    UIView.addKeyframeWithRelativeStartTime(1/3, relativeDuration: 1/3, animations: {
      snapshot.layer.transform = AnimationHelper.yRotation(0.0)
    })
 
    // 4
    UIView.addKeyframeWithRelativeStartTime(2/3, relativeDuration: 1/3, animations: {
      snapshot.frame = finalFrame
    })
  },
  completion: { _ in
    // 5
    toVC.view.hidden = false
    fromVC.view.layer.transform = AnimationHelper.yRotation(0.0)
    snapshot.removeFromSuperview()
    transitionContext.completeTransition(!transitionContext.transitionWasCancelled())
  })

Taking each commented section in turn:

  1. First, you specify the duration of the animation. Notice the use of the transitionDuration(_:) method, implemented at the top of this class. You need the duration of your animations to match up with the duration you’ve declared for the whole transition so UIKit can keep things in sync.
  2. You start by rotating the “from” view halfway around its y-axis to hide it from view.
  3. Next, you reveal the snapshot using the same technique.
  4. Then you set the frame of the snapshot to fill the screen.
  5. Finally, it’s safe to reveal the real “to” view. You remove the snapshot since it’s no longer useful. Then you rotate the “from” view back in place; otherwise, it would hidden when transitioning back. Calling completeTransition informs the transitioning context that the animation is complete. UIKit will ensure the final state is consistent and remove the “from” view from the container.

You’re now ready to use your animation controller!

Wiring Up the Animator

Open CardViewController.swift and declare the following property for the class:

private let flipPresentAnimationController = FlipPresentAnimationController()

UIKit expects a transitioning delegate to vend the animation controller for a transition. To do this, you must first provide an object which conforms to UIViewControllerTransitioningDelegate.

In this example, CardViewController will act as a transitioning delegate. Add the following class extension to the bottom of the source file to make this class conform to UIViewControllerTransitioningDelegate:

extension CardViewController: UIViewControllerTransitioningDelegate {
 
}

Next, add the following method just inside the class extension:

func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
 
  flipPresentAnimationController.originFrame = cardView.frame
  return flipPresentAnimationController
}

Here you return your custom animation controller instance. The method will also ensure the transition starts from the correct frame.

Your final step is to mark CardViewController as the transitioning delegate. View controllers have a transitioningDelegate property, which UIKit will query to see if it shoulld use a custom transition.

Add the following to prepareForSeque(_:sender:), just below the card assignment section:

destinationViewController.transitioningDelegate = self

It’s important to note that it is the view controller being presented that needs a transitioning delegate, not the view controller doing the presenting!

Build and run your project; tap on a card and you should see the following:

frontflip-slow

There you have it – your first custom transition. But presenting your new view is only half the solution: you need to dismiss it in an equally showy manner!

Showy? I got yer showy right here!

Showy? I got yer showy right here!

Dismissing The View Controller

Go to File\New\File…, choose iOS\Source\Cocoa Touch Class, and click Next. Set the name to FlipDismissAnimationController, and make sure to subclass NSObject and set the language to Swift. Click Next and make sure the Animation Controllers group is still selected from last time. Click Create to create the file.

Replace the contents of the new file with the following:

import UIKit
 
class FlipDismissAnimationController: NSObject, UIViewControllerAnimatedTransitioning {
 
  var destinationFrame = CGRectZero
 
  func transitionDuration(transitionContext: UIViewControllerContextTransitioning) -> NSTimeInterval {
    return 0.6
  }
 
  func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
 
  }
}

The goal of this class is essentially the reverse of the presenting animation:

  • Shrink the displayed view to the size of the card; destinationFrame will hold this value.
  • Flip the view around and reveal the original card.

Add the following lines to the top of animateTransition(_:):

guard let fromVC = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey),
    let containerView = transitionContext.containerView(),
    let toVC = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey) else {
    return
}
 
// 1
let initialFrame = transitionContext.initialFrameForViewController(fromVC)
let finalFrame = destinationFrame
 
// 2
let snapshot = fromVC.view.snapshotViewAfterScreenUpdates(false)
snapshot.layer.cornerRadius = 25
snapshot.layer.masksToBounds = true
 
// 3
containerView.addSubview(toVC.view)
containerView.addSubview(snapshot)
fromVC.view.hidden = true
 
AnimationHelper.perspectiveTransformForContainerView(containerView)
 
//4
toVC.view.layer.transform = AnimationHelper.yRotation(-M_PI_2)

Here’s what you’re doing in each commented section:

  1. Since this animation shrinks the view, you’ll need to flip the initial and final frames.
  2. This time you’re manipulating the “from” view so you take a snapshot of that.
  3. Just as before, you add the “to” view and the snapshot to the container view, then hide the “from” view, so that it doesn’t conflict with the snapshot.
  4. Finally, you hide the “to” view via the same rotation technique.

All that’s left to do is add the animation itself.

Add the following code directly below the code you just added to animateTransition(_:):

let duration = transitionDuration(transitionContext)
 
UIView.animateKeyframesWithDuration(
 duration,
 delay: 0,
 options: .CalculationModeCubic,
 animations: {
   // 1
   UIView.addKeyframeWithRelativeStartTime(0.0, relativeDuration: 1/3, animations: {
     snapshot.frame = finalFrame
   })
 
   UIView.addKeyframeWithRelativeStartTime(1/3, relativeDuration: 1/3, animations: {
     snapshot.layer.transform = AnimationHelper.yRotation(M_PI_2)
   })
 
   UIView.addKeyframeWithRelativeStartTime(2/3, relativeDuration: 1/3, animations: {
     toVC.view.layer.transform = AnimationHelper.yRotation(0.0)
   })
 },
 completion: { _ in
   // 2
   fromVC.view.hidden = false
   snapshot.removeFromSuperview()
   transitionContext.completeTransition(!transitionContext.transitionWasCancelled())
})

This is pretty much the inverse of the presenting animation:

  1. You scale the view first, then hide the snapshot with the rotation. Next you reveal the “to” view by rotating it halfway around the y-axis but in the opposite direction.
  2. Finally, you remove the snapshot and inform the context that the transition is complete. This allows UIKit to update the view controller hierarchy and tidy up the views it created to run the transition.

Open CardViewController.swift and declare the following property right below the previous animation controller:

private let flipDismissAnimationController = FlipDismissAnimationController()

Next, add the following delegate method to the class extension:

func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
  flipDismissAnimationController.destinationFrame = cardView.frame
  return flipDismissAnimationController
}

This passes the correct frame to the dismissing animation controller and returns it.

As a final step, modify transitionDuration in FlipPresentAnimationController to make the animation a bit more snappy:

func transitionDuration(transitionContext: UIViewControllerContextTransitioning) -> NSTimeInterval {
  return 0.6
}

Build and run your app; tap the card to see your presenting and dismissing animations:

flip-ready

Your custom animation looks really sharp. But you can improve it even further by adding user interaction to the animation.

Making It Interactive

The Settings app in iOS has a great example of an interactive transition animation:

settings

Your task in this section is to navigate back to the face-down state of the card with swipe from the left edge of the screen; the progress of the transition will follow the user’s finger.

How Interactive Transitions Work

An interaction controller responds to either touch events or programmatic input by speeding up, slowing down, or even reversing the progress of a transition. In order to enable interactive transitions, the transitioning delegate must also provide an interaction controller. This can be any object that implements the UIViewControllerInteractiveTransitioning protocol. You’ve already made the transition animation; the interaction controller moves this animation in response to gestures rather than letting it play like a video.

Apple provides the ready-made UIPercentDrivenInteractiveTransition class, which is a concrete interaction controller implementation. You’ll use this class to make your transition interactive.

Creating an Interactive Transition

Your first job is to create the interaction controller. Go to File\New\File…, and then choose iOS\Source\Cocoa Touch Class. Call it SwipeInteractionController, and make it a subclass of UIPercentDrivenInteractiveTransition. Make sure the Language is Swift then click Next. Choose the Interaction Controllers group and click Create.

Open SwipeInteractionController.swift, and define the following properties at the top of the class:

var interactionInProgress = false
private var shouldCompleteTransition = false
private weak var viewController: UIViewController!

The code above is fairly straightforward:

  • As the name suggests, interactionInProgress indicates whether an interaction in already in progress.
  • You will use shouldCompleteTransition internally to control the transition – you’ll see how later on.
  • The interaction controller directly presents and dismisses view controllers, so you hold onto the current view controller in viewController.

Add the following method to the class body:

func wireToViewController(viewController: UIViewController!) {
  self.viewController = viewController
  prepareGestureRecognizerInView(viewController.view)
}

Your implementation will rely on gesture detection to control the transition. In the above method, you obtain a reference to the view controller, and set up a gesture recognizer in its view.

Implement prepareGestureRecognizerInView(_:) as shown below:

private func prepareGestureRecognizerInView(view: UIView) {
  let gesture = UIScreenEdgePanGestureRecognizer(target: self, action: "handleGesture:")
  gesture.edges = UIRectEdge.Left
  view.addGestureRecognizer(gesture)
}

Here you declare a gesture recognizer, which will be triggered by a left edge swipe, and add it to the view.

The final piece of the puzzle is to add handleGesture(_:) as shown below:

func handleGesture(gestureRecognizer: UIScreenEdgePanGestureRecognizer) {
 
  // 1
  let translation = gestureRecognizer.translationInView(gestureRecognizer.view!.superview!)
  var progress = (translation.x / 200)
  progress = CGFloat(fminf(fmaxf(Float(progress), 0.0), 1.0))
 
  switch gestureRecognizer.state {
 
  case .Began:
    // 2
    interactionInProgress = true
    viewController.dismissViewControllerAnimated(true, completion: nil)
 
  case .Changed:
    // 3
    shouldCompleteTransition = progress > 0.5
    updateInteractiveTransition(progress)
 
  case .Cancelled:
    // 4
    interactionInProgress = false
    cancelInteractiveTransition()
 
  case .Ended:
    // 5
    interactionInProgress = false
 
    if !shouldCompleteTransition {
      cancelInteractiveTransition()
    } else {
      finishInteractiveTransition()
    }
 
  default:
      println("Unsupported")
  }
}

Breaking down the implementation:

  1. You start by declaring local variables to track the progress. You’ll record the translation in the view and calculate the progress. A Swipe of 200 points will lead to 100% completion, so you use this number to measure the transition’s progress.
  2. When the gesture starts, you adjust interactionInProgress accordingly and trigger the dismissal of the view controller.
  3. While the gesture is moving, you continuously call updateInteractiveTransition with the progress amount. This is a method on UIPercentDrivenInteractiveTransition which moves the transition along by the percentage amount you pass in.
  4. If the gesture is cancelled, you update interactionInProgress and roll back the transition.
  5. Once the gesture has ended, you use the current progress of the transition to decide whether to cancel it or finish it for the user.

All that’s left is to wire it up.

SO CLOSE...

SO CLOSE…

Open CardViewController.swift and declare the following property for the interaction controller:

private let swipeInteractionController = SwipeInteractionController()

UIKit queries the transitioning delegate for an interaction controller in interactionControllerForDismissal(_:).

Add the following implementation to the class extension at the bottom of the file:

func interactionControllerForDismissal(animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
 
  return swipeInteractionController.interactionInProgress ? swipeInteractionController : nil
}

This implementation checks whether the view is currently detecting a gesture, which means there’s an interaction in progress. It then returns the appropriate interaction controller.

Now go to prepareForSegue(_:sender:), and add the following line just below the transitioningDelegate assignment:

swipeInteractionController.wireToViewController(destinationViewController)

This gives the interaction controller a reference to the presented view controller.

Build and run your project; tap a card, then swipe from the left edge of the screen to see the final result:

interactive

Congratulations – you’ve created a sharp-looking interactive, animated transition!

Where to Go From Here?

You can download the completed project for this tutorial here.

To learn more, check out Chapter 3, “Custom View Controller Transitions” in iOS 7 by Tutorials as well as Chapter 19, “Custom Presentation Controller & Device Orientation Animations” in iOS Animations by Tutorials.

This tutorial focuses on modal presentation and dismissal transitions. It’s important to point out that custom UIViewController transitions can also be used when using container view controllers:

  • When using a navigation controller, vending the animation controllers is the responsibility of its delegate, which is an object conforming to UINavigationControllerDelegate. The delegate can provide an animation controller in the navigationController(_:animationControllerForOperation:fromViewController:toViewController:) method.
  • A tab bar controller relies on an object implementing the UITabBarControllerDelegate protocol to return the animation controller in the tabBarController(_:animationControllerForTransitionFromViewController:toViewController:) method.

I hope you enjoyed this tutorial; if you have any questions or comments, please join the forum discussion below!

The post Creating Custom UIViewController Transitions appeared first on Ray Wenderlich.

Video Tutorial: CALayers Part 2: CAGradientLayer

Video Tutorial: CALayers Part 3: CAShapeLayer

Video Tutorial: CALayers Part 4: Conclusion

Video Tutorial: Introducing Concurrency: Series Introduction


Video Tutorial: Introducing Concurrency Part 1: NSOperation

Apple Pencil Tutorial: Getting Started

$
0
0

Apple Pencil Tutorial

I know that many of you have got yourself a gorgeous new iPad Pro and snagged a Pencil to go along with it.

If you’re anything like me, once you’ve experienced the awesomeness of drawing with Pencil, you’ll want to include support for it in all of your apps.

I’ve been waiting for something like this device since I purchased the original iPad. As you’ll see from my scribbles, I’m no Rembrandt, but I’ve found Pencil is also great for taking notes. I can only imagine what kinds of amazing works of art people will create now that there is Apple Pencil.

In this Apple Pencil tutorial, you’re going to learn exactly what it takes to support Pencil. Here are the key things you’ll learn:

  • How to work with force
  • How to improve accuracy
  • How to implement shading behavior
  • How to add an eraser
  • How to improve the experience by working with predictive and actual drawings

By the end of this tutorial, you’ll be ready to integrate Apple Pencil support into your apps!

Prerequisites

To follow along with this tutorial, you’ll need:

  • An iPad Pro and Apple Pencil. You cannot test Pencil on the simulator. Also, Pencil doesn’t work with older iPads, just the iPad Pro. Sounds like you’ve got your excuse for an upgrade!
  • At least Xcode 7.1 with at least iOS 9.1.
  • A basic familiarity with Core Graphics. You’ll need to know what contexts are, how to create them and how to draw strokes. Have a look at the first part of our Core Graphics tutorial — that will be plenty to get you up to speed, and the app will remind you to drink water. :]

Getting Started

Throughout this Apple Pencil tutorial, you’ll build an app called Scribble. It’s a simple app that lets you draw with responsive UI, e.g. pressure sensitivity and shading.

Download and explore Scribble. Try it out on your iPad Pro, with both Pencil and your finger, making sure to rest your hand on the screen as you draw.

You’ll see that unlike previous iPads, palm rejection is automatic, although you’ll have to be careful to rest a large area of your hand because smaller areas are read as touches.

Apple Pencil Tutorial
Shake the iPad to clear the screen — just like an Etch-A-Sketch!

Under the hood, Scribble is a basic app that consists of a canvas view that captures the touch from finger or Pencil. It also continuously updates the display to reflect your touch.

Take a look at the code in CanvasView.swift.

The most important code can be found in touchesMoved(_:withEvent:), which is triggered when the user interacts with the canvas view. This method creates a Core Graphics context and draws the image displayed by the canvas view into that context.

touchesMoved(_:withEvent:) then calls drawStroke(_:touch:) to draw a line into the graphics context between the previous and current touch.

touchesMoved(_:withEvent:) replaces the image displayed by the canvas view with the updated one from the graphics context.

See? It’s pretty simple. :]

Your First Drawing with Pencil

Drawing with your finger has never been elegant, even in a digital environment. Pencil makes it much more like drawing the old analog way, with the basic UI of a pencil and paper.

You’re now ready to use the first feature of the Pencil — force. When you press harder against the screen the resulting stroke is wider. This feature doesn’t work with your finger, although there is a little cheat that you’ll learn about later.

Force amount is recorded in touch.force. A force of 1.0 is the force of an average touch so you need to multiply this force by something to produce the right stroke width. More on that in a moment…

Open CanvasView.swift, and at the top of the class add the following constant:

private let forceSensitivity: CGFloat = 4.0

You can tweak this forceSensitivity constant to make your stroke width more or less sensitive to pressure.

Find lineWidthForDrawing(_:touch:). This method calculates the line width.

Just before the return statement, add the following:

if touch.force > 0 {
  lineWidth = touch.force * forceSensitivity
}

Here you calculate the line width by multiplying the force of the touch with the forceSensitivity multiplier, but remember this only applies to Pencil and not to a finger. If you’re using your finger, touch.force will be 0, so you can’t change the stroke width.

Build and run. Drawn some lines with Pencil and notice how the stroke varies depending on how hard you press down on the screen:

Apple Pencil Tutorial

Smoother Drawing

You’ll notice that when you draw, the lines have sharp points rather than a natural curve. Before Pencil, you had to do complex things like convert your strokes to spline curves to make drawings look decent, but Pencil makes this sort of workaround largely unnecessary.

Apple tells us that the iPad Pro scans for a touch at 120 times per second, but when the Pencil is near the screen the scan rate doubles to 240 times per second.

The iPad Pro’s refresh rate is 60 Hz, or 60 times per second. This means that with a scan of 120 Hz it could theoretically recognize two touches but only display just one. In addition, if there’s a lot of processing behind the scenes, the touch event could be missed altogether on certain frames because the main thread is occupied and unable to process it.

Try drawing a circle quickly. It should be round, but the result is more akin to the jagged points of a polygon:

Apple Pencil Tutorial

Apple came up with the concept of coalesced touches to deal with this problem. Essentially, they capture the touches that would have been lost in a new UIEvent array, which you can access via coalescedTouchesForTouch(_:).

Find touchesMoved(_:withEvent:) in CanvasView.swift and replace:

drawStroke(context, touch: touch)

With the following:

// 1
var touches = [UITouch]()
 
// 2
if let coalescedTouches = event?.coalescedTouchesForTouch(touch) {
  touches = coalescedTouches
} else {
  touches.append(touch)
}
 
// 3
print(touches.count)
 
// 4
for touch in touches {
  drawStroke(context, touch: touch)
}

Let’s go through this section by section.

  1. First, you set up a new array to hold all the touches you’ll have to process.
  2. Check for coalesced touches, and if they are there, you save them all to the new array. If there aren’t any, you just add the one touch to the existing array.
  3. Add a log statement to see how many touches you’re processing.
  4. Finally, instead of calling drawStroke(_:touch:) just once, you call it for every touch saved in the new array.

Build and run. Draw some fancy curlicues with your Pencil and revel in buttery smoothness and stroke width control:

Apple Pencil Tutorial

Turn your attention to the debug console. You’ll notice that when you’re drawing with Pencil rather than your finger, you receive many more touches.

You’ll also notice that even with coalesced touches, circles drawn with Pencil are much rounder simply because the iPad Pro scans for touches twice as often when it senses Pencil.

Tilting the Pencil

Now you have lovely fluent drawing in your app. However, if you’ve read or watched any reviews of the Apple Pencil, you’ll remember there was talk of its pencil-like shading abilities. All the users need do is tilt it, but little do they realize that shading doesn’t happen automatically — it’s all down to us clever app developers to write the code that makes it work as expected. :]

Altitude, Azimuth and Unit Vectors

In this section, I’ll describe how you measure the tilt. you’ll get to add support for simple shading in the next section.

When you’re working with Pencil, you can rotate it in three dimensions. Up and down direction is called altitude, while side-to-side is called azimuth:

Apple Pencil Tutorial

The altitudeAngle property on UITouch is new to iOS 9.1, and is there just for the Apple Pencil. It’s an angle measured in radians. When Pencil lies flat on the iPad’s surface, the altitude is 0. When it stands straight up with the point on the screen, the altitude is π/2. Remember that there are radians in a 360 degrees circle, so π/2 is equivalent to 90 degrees.

There are two new methods on UITouch to get azimuth: azimuthAngleInView(_:) and azimuthUnitVectorInView(_:). The least expensive is azimuthUnitVectorInView(_:), but both are useful. The best one for your situation depends on what you need to calculate.

You’ll explore how the azimuth’s unit vector works. For reference, a unit vector has a length of 1 and points from the coordinate (0,0) towards a direction:

Apple Pencil Tutorial

To see for yourself, add the following at the top of touchesMoved(_:withEvent:), just after the guard statement:

print(touch.azimuthUnitVectorInView(self))

Build and run. With the iPad in landscape orientation — Scribble is landscape only to keep this tutorial focused on Pencil — hold your pen so that the point is touching on the left side of the screen, and the end is leaning right.

You won’t be able to get these values in the debug console with satisfactory precision, but the vector is approximately 1 unit in the x direction and 0 units in the y direction — in other words (1, 0).

Rotate Pencil 90 degrees counter-clockwise so the tip is pointing towards the bottom of the iPad. That direction is approximately (0, -1).

Note that x direction uses cosine and the y direction uses sine. For example, if you hold your pen as in the picture above — about 45 degrees counter-clockwise from your original horizontal direction — the unit vector is (cos(45), sin(-45)) or (0.7071, -0.7071).

Note: If you don’t know a lot about vectors, it’s a useful bit of knowledge to pursue. Here’s a two-part tutorial on Trigonometry for Games using Sprite Kit that will help you wrap your head around vectors.

Remove that last print statement when you understand how changing the direction of Pencil gives you the vector that indicates where it’s pointing.

Draw With Shading

Now that you know how to measure tilting, you’re ready to add simple shading to Scribble.

When Pencil is at a natural drawing angle, you draw a line by using force to determine the thickness, but when the user tilts it on its side, you use force to measure the shading’s opacity.

You’ll also calculate the thickness of the line based upon the direction of the stroke and the direction in which you’re holding the Pencil.

If you’re not quite following me here, just go find a pencil and paper to try shading by turning the pencil on its side so that the lead has maximum contact with the paper. When you shade in the same direction as the pencil is leaning, the shading is thin. But when you shade at a 90 degree angle to the pencil, the shading is at its thickest:

Apple Pencil Tutorial

Working With Texture

The first order of business is to change the texture of the line so that it looks more like shading with a real pencil. The starter app includes an image in the Asset Catalog called PencilTexture to use for this.

Add this property to the top of CanvasView:

private var pencilTexture = UIColor(patternImage: UIImage(named: "PencilTexture")!)

This will allow you to use pencilTexture as a color to draw with, instead of the default red color you’ve used up until now.

Find the following line in drawStroke(_:touch:):

drawColor.setStroke()

And change it to:

pencilTexture.setStroke()

Build and run. Hey presto! Your lines now look much more like a pencil’s lines:

Apple Pencil Tutorial

Note: In this tutorial, you’re using a texture in a rather naive way. Brush engines in full-featured art apps are far more complex, but this approach is enough to get you started.

To check that Pencil is tilted far enough to initiate shading, add this constant to the top of CanvasView:

private let tiltThreshold = π/6  // 30º

If you find that this value doesn’t work for you because you hold it differently, you can change its value to suit.

Note: To type π hold down Option + P at the same time. π is a convenience constant defined at the top of CanvasView.swift as CGFloat(M_PI).

When programming graphics, it’s important to start thinking in radians rather than converting to degrees and back again. Take a look at this image from Wikipedia to see the correlation between radians and degrees.

Next, find the following line in drawStroke(_:touch:):

let lineWidth = lineWidthForDrawing(context, touch: touch)

And change it to:

var lineWidth:CGFloat
 
if touch.altitudeAngle < tiltThreshold {
  lineWidth = lineWidthForShading(context, touch: touch)
} else {
  lineWidth = lineWidthForDrawing(context, touch: touch)
}

Here you’re adding a check to see if your Pencil is tilted more than π/6 or 30 degrees. If yes, then you call the shading method rather than the drawing method.

Now, add this method to the bottom of CanvasView:

private func lineWidthForShading(context: CGContext?, touch: UITouch) -> CGFloat {
 
  // 1
  let previousLocation = touch.previousLocationInView(self)
  let location = touch.locationInView(self)
 
  // 2 - vector1 is the pencil direction
  let vector1 = touch.azimuthUnitVectorInView(self)
 
  // 3 - vector2 is the stroke direction
  let vector2 = CGPoint(x: location.x - previousLocation.x, y: location.y - previousLocation.y)
 
  // 4 - Angle difference between the two vectors
  var angle = abs(atan2(vector2.y, vector2.x) - atan2(vector1.dy, vector1.dx))
 
  // 5
  if angle > π {
    angle = 2 * π - angle
  }
  if angle > π / 2 {
    angle = π - angle
  }
 
  // 6
  let minAngle: CGFloat = 0
  let maxAngle = π / 2
  let normalizedAngle = (angle - minAngle) / (maxAngle - minAngle)
 
  // 7
  let maxLineWidth: CGFloat = 60
  var lineWidth = maxLineWidth * normalizedAngle
 
  return lineWidth
}

There’s some complex math in there, so here’s a play-by-play:

  1. Store the previous touch point and the current touch point.
  2. Store the azimuth vector of the Pencil.
  3. Store the direction vector of the stroke that you’re drawing.
  4. Calculate the angle difference between stroke line and the Pencil direction.
  5. Reduce the angle so it’s 0 to 90 degrees. If the angle is 90 degrees, then the stroke will be the widest. Remember that all calculations are done in radians, and π/2 is 90 degrees.
  6. Normalize this angle between 0 and 1, where 1 is 90 degrees.
  7. Multiply the maximum line width of 60 by the normalized angle to get the correct shading width.

Note: Whenever you’re working with Pencil, the following formulae come in handy:

Angle of a vector: angle = atan2(opposite, adjacent)
Normalize: normal = (value - minValue) / (maxValue - minValue)

Build and run. Hold Pencil at about the angle indicated in the picture, as is you’re going to shade. Without changing the angle, do a little shading.

Apple Pencil Tutorial

Notice how as the stroke direction changes it becomes wider and narrower. It’s a bit blobby here with this naive approach, but you can definitely see the potential.

Using Azimuth to Adjust Width

One more thing to do: When you draw at 90 degrees with a real pencil, the line gets narrower as you change the pencil’s tilt angle. But, if you try that with your Apple Pencil, the line width stays the same.

In addition to the azimuth angle, you also need to take into Pencil’s altitude into account when calculating the width of the line.

Add this constant to the top of the CanvasView class, just below the others:

private let minLineWidth: CGFloat = 5

This will be the narrowest that a shading line can be — you can change it to suit your own personal shading tastes. :]

At the bottom of lineWidthForShading(_:touch:), just before the return statement, add the following:

// 1    
let minAltitudeAngle: CGFloat = 0.25
let maxAltitudeAngle = tiltThreshold
 
// 2
let altitudeAngle = touch.altitudeAngle < minAltitudeAngle ? minAltitudeAngle : touch.altitudeAngle
 
// 3
let normalizedAltitude = 1 - ((altitudeAngle - minAltitudeAngle) / (maxAltitudeAngle - minAltitudeAngle))
 
// 4
lineWidth = lineWidth * normalizedAltitude + minLineWidth

Note: Make sure you add this code to lineWidthForShading(_:touch:), and not lineWidthForDrawing(_:touch:) by mistake.

There’s a lot to digest here, so let’s take this bit by bit.

  1. Theoretically, the minimum altitude of Pencil is 0 degrees, meaning it’s lying flat on the iPad and the tip isn’t touching the screen, hence, altitude can’t be recorded. The actual minimum altitude is somewhere around 0.2, but I’ve made the minimum to be 0.25.
  2. If the altitude is less than the minimum, you use the minimum instead.
  3. Just like you did earlier, you normalize this altitude value to be between 0 and 1.
  4. Finally, you multiply the line width you calculated with the azimuth by this normalized value, and add that to the minimum line width.

Build and run. As you shade, change the Pencil’s altitude and see how the strokes get wider and narrower. Increasing the Pencil’s altitude gradually should let you segue smoothly into the drawing line:

Apple Pencil Tutorial

Playing with Opacity

The last task in this section is to make the shading look a bit more realistic by turning down the texture’s opacity, which you’ll calculate with force.

Just before the return statement in lineWidthForShading(_:touch:), add the following:

let minForce: CGFloat = 0.0
let maxForce: CGFloat = 5
 
let normalizedAlpha = (touch.force - minForce) / (maxForce - minForce)
 
CGContextSetAlpha(context, normalizedAlpha)

After working through the previous blocks of code, this one should be self-explanatory. You’re simply taking the force and normalizing it to a value between 0 and 1, and then setting the alpha used by the drawing context to that value.

Build and run. Try shading with varying pressure:

Shaded

Finger vs. Pencil

If you’re anything like me, you’ve probably made a few sketching errors here and there and wish you could erase those errant lines.

In this section, you’re going to look at how you can distinguish between using the Apple Pencil and your finger. More specifically, you’ll configure the app so that your finger can play the role of a faithful eraser.

It turns out that checking whether a finger or the Apple Pencil is being used is pretty easy — you just use the type property on UITouch.

At the top of CanvasView, add a property for the eraser color. You’re going to paint in the background color of the canvas view, and it will give the illusion of acting as an eraser. Clever, eh? :]

private var eraserColor: UIColor {
  return backgroundColor ?? UIColor.whiteColor()
}

Here you set eraserColor to the view’s background color, unless it’s nil, in which case you just set it to white.

Next, find the following code in drawStroke(_:touch:):

if touch.altitudeAngle < tiltThreshold {
  lineWidth = lineWidthForShading(context, touch: touch)
} else {
  lineWidth = lineWidthForDrawing(context, touch: touch)
}
 
pencilTexture.setStroke()

And replace it with the following:

if touch.type == .Stylus {
  if touch.altitudeAngle < tiltThreshold {
    lineWidth = lineWidthForShading(context, touch: touch)
  } else {
    lineWidth = lineWidthForDrawing(context, touch: touch)
  }
  pencilTexture.setStroke()
} else {
  lineWidth = 20
  eraserColor.setStroke()
}

Here you’ve added a check to see whether it’s Pencil or a finger, and if it’s the latter you change the line width and use the eraser color for drawing.

Build and run. Now you can clean up any untidy edges or erase everything with your finger!

Apple Pencil Tutorial

Faking Force For a Finger

Just as an aside, did you know that since iOS 8 you’ve been able to fake force with your finger? There’s a property declared on UITouch called majorRadius, which, as its name implies, holds the size of the touch.

Find this line that you just added in the previous code block:

lineWidth = 20

And replace it with this one:

lineWidth = touch.majorRadius / 2

Build and run. Shade a dark area, and then erase with both the tip of your finger and the flat of your finger to see the varying thicknesses:

Apple Pencil Tutorial

Finger painting feels really clumsy and the drawings are painful after you’ve played around with the elegant Apple Pencil. :].

Reducing Latency

You might think that your Pencil zooms over the surface of the iPad with the drawn line following closer than ever. Not so much — it’s an illusion because there is latency between the touch and the time the line renders. Apple has a trick up its sleeve to deal with it: Touch Prediction.

Incredible as it may seem, all-seeing Apple knows where your Pencil, or finger, is about to draw. Those predictions are saved into an array on UIEvent so that you can draw that predicted touch ahead of time. How cool is that!? :]

Before you can begin working with predicted touches, there’s one small technical obstacle to overcome. At the moment, you’re drawing strokes in the graphics context, which are then displayed immediately in the canvas view.

You’ll need to draw the predicted touches onto the canvas but discard them when the actual touches catch up with the predicted ones.

For example, when you draw an S-shape it predicts the curves, but when you change direction, those predictions will be wrong and need to be discarded. This picture illustrates the problem. The “S” is drawn in red and the predicted touches show in blue.

Predicted

Here’s what your code will need to do to avoid this problem:

  1. You’ll create a new UIImage property named drawingImage to capture the true — not predicted — touches from the graphics context.
  2. On each touch move event, you’ll draw drawingImage into the graphics context.
  3. The real touches will be drawn into the graphics context, and you’ll save it to the new drawingImage instead of using the image property on the canvas view.
  4. The predicted touches will be drawn into the graphics context.
  5. The graphics context, complete with predicted touches, will be pushed into canvasView.image, which is what the user will see.

In this way, no predicted touches will draw into drawingImage and each time a touch move event occurs, the predictions will be deleted.

Housekeeping: Deleting Drawing Predictions

There’s a little housekeeping in order to ensure those predicted touches are properly disposed of at the end of the stroke or when the user cancels the drawing.

Add a new UIImage property at the top of the CanvasView to hold the proper drawn image — the one without predictions:

private var drawingImage: UIImage?

Next, find the following statement in touchesMoved(_:withEvent:):

image?.drawInRect(bounds)

And replace it with the following:

drawingImage?.drawInRect(bounds)

Here you’re drawing drawingImage into the graphics context, rather than the image being displayed at that time by the canvas view. This will overwrite any predicted touches drawn by the previous move event.

Now, at the bottom of touchesMoved(_:withEvent:), but just above these lines:

image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()

Add this new code:

// 1
drawingImage = UIGraphicsGetImageFromCurrentImageContext()
// 2
if let predictedTouches = event?.predictedTouchesForTouch(touch) {
  for touch in predictedTouches {
    drawStroke(context, touch: touch)
  }
}

Here’s what’s happening in there:

  1. You save the graphics context with the new stroke that’s been drawn but don’t include the predicted strokes.
  2. Like you did with the coalesced touches, you get the array of predicted touches and draw the strokes for each predicted touch.

Now add these two methods:

override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
  image = drawingImage
}
 
override func touchesCancelled(touches: Set<UITouch>?, withEvent event: UIEvent?) {
  image = drawingImage
}

These are called at the end of a stroke. By replacing the image with drawingImage when a touch ends or is cancelled, you’re discarding all the predicted touches that were drawn onto the canvas.

One last thing: You’ll need to clear both the canvas and the true drawing when you shake to clear.

In CanvasView.swift, in clearCanvas(animated:), locate this code inside the animation closure:

self.image = nil

Add this statement straight after that line:

self.drawingImage = nil

Now a little bit further in that same method, locate:

image = nil

and add this code after it:

drawingImage = nil

Here you clear both images of any drawing that you’ve done.

Build and run. Draw some squiggles and curves. You may notice that you’re drawing all the touches that Apple predicted you might make, and consequently perceived latency is reduced. You may need to watch closely because it’s very subtle. :]

Apple Pencil Tutorial

Note: When you run the second code sample at the end of this tutorial, you’ll be able to visualize what predicted touches actually do. You’ll see an option to replace the texture with a blue color just for the predicted touches.

Apple’s algorithm for predicted touches is astonishingly good. It’s the little subtleties like this one that make it a pleasure to develop for Apple platforms.

Where To Go From Here?

Congratulations! You have now completed a simple drawing app where you can scribble and enjoy getting artsy with your Pencil. :] You can download the finished project to see the final result.

You did some pretty awesome things and learned about the following:

  • Smoothing lines and shapes so they look natural
  • Working with altitude and azimuth
  • Implementing drawing and shading
  • Adding and working with texture
  • Adding an eraser
  • Working with predictive data and what to do when it’s not used

I’m also providing a second project that has buttons to turn coalesced and predicted touches on or off, so that you can visualize their effects.

Apple’s WWDC video on touches has a great section on how coalesced and predicted touches work with the 60 Hz frame rate. Watch it to see how latency has improved from 4 frames in iOS 8 to 1.5 frames in iOS 9.1. Pretty spectacular!

FlexMonkey (aka Simon Gladman) has done some really creative things with the Pencil that go well beyond just drawing with it. Take a look at his blog, especially the Pencil Synthesizer and FurrySketch.

I hope you enjoyed this Apple Pencil tutorial – I’d love to see as many apps as possible integrating this very cool device. If you have any questions or comments please join the forum discussion below!

The post Apple Pencil Tutorial: Getting Started appeared first on Ray Wenderlich.

Video Tutorial: Introducing Concurrency Part 2: NSOperationQueue

Reminder: RWDevCon Student Scholarship Applications Due Monday

$
0
0

RWDevCon Scholarship

As you might know, this year we offering 5 student scholarships for RWDevCon 2016.

The 5 lucky students will win a free ticket to the conference and will get to attend our team-only pre-conference fun day!

Not only is this an amazing opportunity for students to learn a ton about Swift and iOS development, but it’s also the only way to get a ticket to the conference at the moment, because RWDevCon 2016 is sold out.

This post is a quick reminder that applications for RWDevCon 2016 student scholarships are due next Monday, January 11 – so if you’re a student and haven’t started yet, now’s the time!

Keep reading for a reminder about find out who’s eligible, how to apply, and who to thank for this great opportunity.

Eligibility and How To Apply

To be eligible to win, there are three requirements:

  • You must be born on or after March 12, 1995 (i.e. you’re 21 years or younger when the conference ends; this is primarily intended for high school or early college students).
  • You also must be able to attend the conference and the pre-conference fun day (March 10-12, 2016).
  • You must be able to pay for your own travel and hotel expenses (they are not included; the scholarship includes a ticket to the conference and an invitation to the team-only pre-conference fun day only).

To apply, simply:

  • Write a tutorial related to iOS or Swift Language development, and post it to your own blog. If you don’t have a blog, I recommend you post it on Medium.
  • Then send us an email with a link to your tutorial, a scanned ID that shows your birthday on it, and confirm that you meet the three requirements listed above.

We will choose the authors of the 5 best tutorials as winners, based on writing skills, technical skills, and the “cool factor” of the subject of the tutorial.

Again, entries are due next Monday, January 11, 2016 – so get writing! :]

Introducing the Patrons

The RWDevCon 2016 scholarships are sponsored by 5 generous patrons of the iOS community, who bought a special ticket that included the cost of the student tickets. Along with me, these patrons will be judging the applicants for the scholarships.

I asked each of our patrons to write some advice for students studying programming. Here’s what they had to say:

Steve Daly, Software Developer

SteveDaly

“When writing a program, it helps if you act as if the program is going to eventually be read, modified or maintained by somebody else. This makes it easier for you if you need to revisit the code after being away from it for a long time.”

Larry Ketchersid, CEO of Media Sourcery, Inc; owner of JoSara MeDia

LarryKetchersid

“You’ll learn more working with others than in isolation. Learning from someone is great, but also try teaching someone what you’ve learned; whether the subject is programming, cooking, martial arts or anything, you’ll find that you truly understand a topic when you attempt to explain it to someone else, and hear their questions on what you are trying to convey. It’s also a great way to give back to the programming community.”

Kevin Legg, Co-Owner of Five Pack Creative

KevinLegg

“Work on things you are passionate about and don’t forget to have fun. Do good things even when not required and you will go far.”

Carey McLean, Innovation Software Engineer

CareyMcLean

“When you start learning to program, the task may seem impossible. Just remember, the word itself says I’m possible! Make a plan to learn, develop and execute. You’ll be amazed at what you can accomplish. :-)”

Walter Tyree – Computer Whisperer

WalterTyree

“The best part about learning programming is that the basic concepts are mostly unchanged for years but; there are always new things being invented. Every few months, you have the opportunity to become the world’s leading expert in something.”

Where To Go From Here?

If you, or a student you know, wants to take advantage of an amazing learning opportunity that will pay some major dividends in life, don’t miss this chance!

Start writing your tutorial now, and send it to us along with a scanned ID and a confirmation that you meet the 3 requirements by next Monday, January 11, 2016.

We wish the best of luck to all of the applicants, and we look forward to seeing you at RWDevCon 2016!

Note: Missed your chance to get a RWDevCon ticket? Be sure to sign up to our mailing list to get notified when RWDevCon 2017 tickets become available so you don’t miss it next time :]

The post Reminder: RWDevCon Student Scholarship Applications Due Monday appeared first on Ray Wenderlich.

Video Tutorial: Introducing Concurrency Part 3: Asynchronous Operations

Swift Tutorial: Introduction to Generics

$
0
0
Why make three boxes when a generic one will do?

Why make three boxes when a generic one will do?

Generic programming is a way to write functions and data types without being specific about the types they use. Arrays are a good example – whether you have an array of strings or an array of integers or an array of AnyObject, they’re all arrays that work in the same way.

The difference is the type of thing they store, but there’s still just a single Array type. The big idea here is that you say what the array will hold when you declare it. In a way, it’s like having a type become an additional parameter to a function, saving you from writing many different versions of a similar function or data type.

You’ll find generics in use throughout Swift, which makes understanding them essential to a complete understanding of the language. In this tutorial, you’ll experiment in a Swift playground to learn what generics are and why they’re useful, how to write generic functions and data structures, as well as more intermediate tasks such as how to use type constraints and extend generic types. Finally, you’ll take a look at some of the new generics features in Swift 2.

Note: This tutorial requires Xcode 7 and Swift 2.

Getting Started

Begin by creating a new playground: In Xcode, go to File\New\Playground…, name the playground Generics and select OS X as the platform. Click Next to choose where you’d like to save your new playground and finally, click Create.

Suppose your application requires a function to add two integers. Add the following to your newly created playground:

func adderInt(x: Int, _ y: Int) -> Int {
  return x + y
}

adderInt(_:_:) takes two Int values and returns their sum. You can give it a try by adding the following code to the playground:

let intSum = adderInt(1, 2)

This is a pretty simple example that also demonstrates Swift’s type safety. You can call this function with two integers, but not any other type. Now suppose you also need to add two Double values. You would create a second function adderDouble:

func adderDouble(x: Double, _ y: Double) -> Double {
  return x + y
}
 
let doubleSum = adderDouble(1.0, 2.0)

The function signatures of adderInt and adderDouble are different, but the function bodies are identical. Not only do you have two functions, you’ve also repeated the code inside them. Soon you’ll see how you can use generics to reduce these two functions to one and remove the redundant code.

Arrays as Generic Types

Add the following to your playground:

let numbers = [1, 2, 3]
 
let firstNumber = numbers[0]

Here, you create a simple array of three numbers and then take the first number out of that array.

Now Option-click first on numbers and then on firstNumber. What do you see? Because Swift has type inference, you don’t have to explicitly define the types of your constants, but they both have an exact type: numbers is an [Int]—that is, an array of integers—and firstNumber is an Int.

The Swift Array type is a generic type, or one that requires a type parameter in order to be fully specified. Via type inference and also thanks to Swift’s type safety, numbers can only contain Int values, and when you take anything out of that array, Swift—and more importantly you—both know it must be an Int.

You can better see the generic nature of Array by forgoing type inference and the Swift array syntactic sugar and adding the following code to the end of the playground:

var numbersAgain = Array<Int>()
numbersAgain.append(1)
numbersAgain.append(2)
numbersAgain.append(3)
 
let firstNumberAgain = numbersAgain[0]

Check the types of numbersAgain and firstNumberAgain by Option-clicking on them; the types will be exactly the same as the previous values. Here you specify the type of numbersAgain using explicit generic syntax, by putting Int in angle brackets after Array.

Try appending something else to the array, like a Double or a String:

numbersAgain.append("hello")

You’ll get an error—something like, Cannot invoke 'append' with an argument list of type '(String)'. The compiler is telling you that you can’t add a string to an array of integers. As a method on the generic type Array, append is a so-called generic method. It knows the type of the containing array’s elements, and won’t let you add something of an incorrect type.

Other Generic Types

In Swift, some of the most common structures you use are generic types. You took a quick look at Array, above. Dictionaries and optionals are also generic types and result in type-safe data structures.

Create the following dictionary of country codes at the end of your playground and then look up the country code of Austria:

let countryCodes = ["Austria": "AT", "United States of America": "US", "Turkey": "TR"]
 
let at = countryCodes["Austria"]

Check the types of both declarations. You’ll see that countryCodes is a dictionary of String keys and String values—nothing else can ever be in this dictionary. The formal generic type is Dictionary.

The type of at is String?, which is shorthand for Optional, so you can see that optional types are generic types. Generics are all over the place! The compiler enforces that you can only look up string keys and you always get string values back. The string value is optional, because there might not be a value corresponding to the passed-in key.

Add the following to your playground to see the full explicit syntax for creating an optional string:

let optionalName = Optional<String>.Some("John")
 
if let name = optionalName {
}

Check the type of name, which you’ll see is String. Optional binding, that is, the if-let construct, is a generic operator of sorts. It takes a value of type T? and gives you a value of type T.

T_time

These are the main ideas behind generics. For generic functions, the parameter list and/or the return value depend on one or more generic types, such as T. You specify those types on an individual basis when you call the function, either explicitly or via type inference.

Now that you grasp of the basics of generics, you can learn about writing your own generic functions and types!

Writing a Generic Function

Add the following function to the bottom of the playground:

func pairsFromDictionary<KeyType, ValueType>(dictionary: [KeyType: ValueType]) -> [(KeyType, ValueType)] {
  return Array(dictionary)
}

Take a good look at the function declaration, parameter list and return type.

The function is generic over two types that you’ve named KeyType and ValueType. The only parameter is a dictionary from KeyType to ValueType, and the return value is an array of tuples of the form—you guessed it— (KeyType, ValueType).

You can use pairsFromDictionary on any valid dictionary and it will work, thanks to generics:

let pairs = pairsFromDictionary(["minimum": 199, "maximum": 299])
let morePairs = pairsFromDictionary([1: "Swift", 2: "Generics", 3: "Rule"])

Of course, since you can’t control the order in which the dictionary items go into the array, you may see an order of tuple values in your playground more like “Generics”, “Rule”, “Swift”, and indeed, they kind of do! :]

The compiler generates separate functions for each possible KeyType and ValueType, filling in the real types in the function declaration and body. In the first case of pairs, pairsFromDictionary returns an array of (String, Int) tuples, and in the second case of morePairs, it returns an array of (Int, String) tuples. At the code level, you created both of these using a single function.

Writing a Generic Data Structure

A queue is a data structure kind of like a list or a stack, but you can only add new values to the end (enqueuing) and only take values from the front (dequeuing). This concept might be familiar if you’ve ever used NSOperationQueue or Grand Central Dispatch, with dispatch_async and friends.

Add the following struct declaration to the end of your playground:

struct Queue<Element> {
}

Queue is a generic type over Element. Queue and Queue, for example, will become types of their own, generated by the compiler, that can only enqueue and dequeue strings and integers, respectively.

Add the following private property to the queue:

private var elements = [Element]()

You’ll use this array to hold the elements, which you initialize as an empty array. Note that you can use Element as if it’s a real type, even though it’ll be filled in later.

Finally, implement the two main queue methods:

mutating func enqueue(newElement: Element) {
  elements.append(newElement)
}
 
mutating func dequeue() -> Element? {
  guard !elements.isEmpty else {
    return nil
  }
  return elements.removeAtIndex(0)
}

Again, the type parameter Element is available everywhere in the struct body including inside methods. Making a type generic is like making every one of its methods implicitly generic over the same type. You’ve implemented a type-safe generic data structure, just like the ones in the standard library.

Play around with your new data structure for a bit at the bottom of the playground.

var q = Queue<Int>()
 
q.enqueue(4)
q.enqueue(2)
 
q.dequeue()
q.dequeue()
q.dequeue()
q.dequeue()

Also, have some fun by intentionally making as many mistakes as you can to trigger the different error messages related to generics—for example, add a string to your queue. The more you know about these errors now, the easier it will be to recognize and deal with them later.

Intermediate Topics

Now that you know the basics of creating and working with generic types and functions, it’s time to move on to some more advanced features. You’ve already seen how useful generics are to limit things by type, but you can add additional constraints as well as extend your generic types to make them even more useful.

Type Constraints and Where Clauses

The function below sorts an array and finds the middle value. Add it to your playground:

func mid<T>(array: [T]) -> T {
  return array.sort()[(array.count - 1) / 2]
}

You’ll get an error. The problem is that for sort() to work, the elements of the array need to be Comparable. You need to somehow tell Swift that mid can take any array as long as the element type implements Comparable.

Change the function declaration to the following:

func mid<T where T: Comparable>(array: [T]) -> T {
  return array.sort()[(array.count - 1) / 2]
}

Here, you use the where keyword to add a type constraint to the generic type parameter T. You can now only call the function with an array of comparable elements, so that sort() will always work! Try out the constrained function by adding:

mid([3, 5, 1, 2, 4]) // 3

In the case that where makes the type conform to a protocol, such as above, you can use the following syntactic sugar and remove where:

func mid<T: Comparable>(array: [T]) -> T {
  return array.sort()[(array.count - 1) / 2]
}

Other uses of where include when there is more than one generic type, and you want to add a constraint between two or more of them.

Now that you know about type constraints, you can create a generic version of the adder functions from the beginning of the playground. Add the following protocal and extensions to your playground:

protocol Summable { func +(lhs: Self, rhs: Self) -> Self }
 
extension Int: Summable {}
extension Double: Summable {}

First, you create a Summable protocol that says any type that conforms must have the addition operator + available. Then, you specify that the Int and Double types conform to it.

Now using a generic type T and a type constraint, you can create a generic function adder:

func adder<T: Summable>(x: T, _ y: T) -> T {
  return x + y
}

You’ve reduced your two functions (actually more, since you would have needed more for other Summable types) down to one and removed the redundant code. You can use the new function on both integers and doubles:

let adderIntSum = adder(1, 2)
let adderDoubleSum = adder(1.0, 2.0)

And you can also use it on other types, such as strings:

extension String: Summable {}
let adderString = adder("Generics", " are Awesome!!! :]")

By adding other conforming types to Summable, your adder(_:_:) function becomes more widely available thanks to its generics-powered definition!

Extending a Generic Type

Extend the Queue type and add the following method right below the Queue definition:

extension Queue {
  func peek() -> Element? {
    return elements.first
  }
}

peek returns the first element without dequeuing it. Extending a generic type is easy! The generic type parameter is visible just like in the original definition’s body. You can use your extension to peek into a queue:

q.enqueue(5)
q.enqueue(3)
q.peek()

You’ll see the value 5 as the first element in the queue, but nothing has been dequeued and the queue has the same number of elements as before.

Challenge: Extend the Queue type to implement a function homogeneous that checks if all elements of the queue are equal. You’ll need to add a type constraint in the Queue declaration to ensure its elements can be checked for equality to each other.

challenge_considered

Solution Inside: Homogeneous queue SelectShow>

New Generics Features in Swift 2

Along with many other language features, generics got a nice update in the latest Swift 2 release. Here, you’ll review some of the latest updates.

Subclassing Generic Classes

Swift 2 added the ability to subclass generic classes, which can be useful in some cases. Previously, you could subclass generic classes but they had to also be generic. Now, you can make a more “concrete” subclass of a generic class.

Add the following generic class to the playground:

class Box<T> {
 
}

You define a Box class. The box can contain anything, and that’s why it’s a generic class. There are two ways you could subclass Box:

  1. You might want to extend what the box does and how it works but keep it generic, so you can still put anything in the box;
  2. You might want to have a specialized subclass that always knows what’s in it.

Swift 2 allows both. Add this to your playground:

class Gift<T>: Box<T> {
}
 
class StringBox: Box<String> {
}

You define two Box subclasses here: Gift is a special kind of box that will presumably have different methods and properties defined on it, such as recipient and wrap(). However, it still has a generic on the type, meaning it could contain anything.

In contrast, StringBox is a box of strings, and thus isn’t generic anymore.

boxes

Declare instances of each class under the subclass declarations:

let box = Box<Int>()
let gift = Gift<Double>()
let stringBox = StringBox()

Notice that the StringBox initializer doesn’t need to take the generic type parameter anymore, since it’s fixed in the declaration of StringBox.

Enums With Multiple Generic Associated Values

Before WWDC 2015, when Swift still didn’t support the new error-handling mechanism, the most popular way to do “functional” error-handling was using a so-called result enum. This is a generic enum with two associated values: one for the actual result value and one for the possible error. Swift didn’t support this, and you would get a compiler error if you were lucky, and strange undefined behavior if you weren’t.

There were hacks to work around this limitation. Thankfully, Swift 2 supports declaring such a result type, among other useful enums with multiple generic associated values.

Add the following declaration to the end of your playground:

enum Result<ValueType, ErrorType> {
  case Success(ValueType)
  case Failure(ErrorType)
}

The main use case for such an enum is as a return value for a function with specific error information, kind of like a more general optional:

func divideOrError(x: Int, y: Int) -> Result<Int, String> {
  guard y != 0 else {
    return Result.Failure("Division by zero is undefined")
  }
  return Result.Success(x / y)
}

Here, you declare a function that divides two integers. If the division is legal, you return the resulting value in the .Success case; otherwise you return an error message.

Try out your new function:

let result1 = divideOrError(42, y: 2)
let result2 = divideOrError(42, y: 0)

The first result is a success case with a value of 21, and the second result is the failure case with the message Division by zero is undefined. Even though the enum type has two types associated with it, you can see how the cases are defined to use just one or the other.

Where to Go From Here?

Here’s the downloadable final playground with all the code you’ve written in this tutorial.

Generics are at the core of many common language features, such as arrays and optionals. You’ve seen how to use them to build your own container types and to avoid duplicating code that would only differ by type.

For more information, read through the Generics” chapter and the Generic Parameters and Arguments” language reference chapter of Apple’s guide, The Swift Programming Language. You’ll find more detailed information about generics in Swift, as well as some handy examples.

Thank you for taking the time to learn about generics in Swift, an integral feature that you’ll use everyday to write powerful and type-safe abstractions. You can get the best of both worlds – generic classes, while specifying an actual type to get type safety when you instantiate it.

If you have any questions, please let me know in the forum discussion below! :]

The post Swift Tutorial: Introduction to Generics appeared first on Ray Wenderlich.

Video Tutorial: Introducing Concurrency Part 4: Dependencies


Video Tutorial: Introducing Concurrency Part 5: Canceling Operations

Video Tutorial: Introducing Concurrency Part 6: NSOperation in Practice

$
0
0

Challenge

Your challenge is to add a new filtering operation to achieve an old school camera effect for the images. For details, download the challenge starter project from the resources link below.

Download resources

Find out more about the challenge in the following video and then pause it to try the challenge on your own. Once you’ve given it a try you can continue watching to find the solution here:

View previous video: Canceling Operations

The post Video Tutorial: Introducing Concurrency Part 6: NSOperation in Practice appeared first on Ray Wenderlich.

State Restoration Tutorial: Getting Started

$
0
0
State-restoration

Learn how to let your users pick-up right were they left off!

State restoration is an often-overlooked feature in iOS that lets a user return to their app in the exact state in which they left it – regardless of what’s happened behind the scenes.

At some point, the operating system may need to remove your app from memory; this could significantly interrupt your user’s workflow. Your user also shouldn’t have to worry about switching to another app and losing all their work. This is where state restoration saves the day.

In this state restoration tutorial, you’ll update an existing app to add preservation and restoration functionalities and enhance the user experience for scenarios where their workflow is likely to be interrupted.

Getting Started

Downloading the starter project for this tutorial. The app is named Pet Finder; it’s a handy app for people who happen to be seeking the companionship of a furry feline friend.

Run the app in the simulator; you’ll be presented with an image of a cat that’s eligible for adoption:

Pet Finder

Swipe right to be paired up with your new furry friend; swipe left to indicate you’d rather pass on this ball of fluff. You can view a list of all your current matches from the Matches tab bar:

Matches

Tap to view more details about a selected friend:

Details

You can even edit your new friend’s name (or age, if you’re into bending the truth):

Edit

You’d hope that when you leave this app annd return to it later, you’d be brought back to the same furry friend you were last viewing. But is this truly the case with this app? The only way to tell is to test it.

Testing State Restoration

Run the app, swipe right on at least one cat, view your matches, then select one cat to view his or her details. Press Cmd+Shift+H to return to the home screen. Any state preservation logic, should it exist, would run at this point.

Next, stop the app from Xcode:

Stop App

The state restoration framework intentionally discards any state information when the user manually kills an app, or when the state restoration process fails. These checks exist so that your app doesn’t get stuck in an infinite loop of bad states and restoration crashes. Thanks, Apple! :]

Note: You cannot kill the app yourself via the app switcher, otherwise state restoration simply won’t work.

Launch the app again; instead of returning you to the pet detail view, you’re back at the home screen. Looks like you’ll need to add some state restoration logic yourself.

Enabling State Restoration

The first step in setting up state restoration is to enable it in your app delegate. Open AppDelegate.swift and add the following code:

func application(application: UIApplication, shouldSaveApplicationState coder: NSCoder) -> Bool {
  return true
}
 
func application(application: UIApplication, shouldRestoreApplicationState coder: NSCoder) -> Bool {
  return true
}

There are five app delegate methods that manage state restoration. Returning true in application(_:shouldSaveApplicationState:) instructs the system to save the state of your views and view controllers whenever the app is backgrounded. Returning true in application(_:shouldRestoreApplicationState:) tells the system to attempt to restore the original state when the app restarts.

You can make these delegate methods return false in certain scenarios, such as while testing or when the user’s running an older version of your app that can’t be restored.

Build and run your app, and navigate to a cat’s detail view. Press Cmd+Shift+H to background your app, then stop the app from Xcode. You’ll see the following:

Pet Finder

confused

It’s the exact same thing you saw before! Just opting-in to state restoration isn’t quite enough. You’ve enabled preservation and restoration in your app, but the view controllers aren’t yet participating. To remedy this, you’ll need to give each of these scenes a restoration identifier.

Setting Restoration Identifiers

A restoration identifier is simply a string property of views and view controllers that UIKit uses to restore those objects to their former glory. The actual content of those properties isn’t critical, as long as it’s unique. It’s the presence of a value that communicates to UIKit your desire to preserve this object.

Open Main.storyboard and you’ll see a tab bar controller, a navigation controller, and three custom view controllers:

cinder_storyboard

Restoration identifiers can either be set in code or in Interface Builder. To make things easy, in this tutorial you’ll set them in Interface Builder. You could go in and think up a unique name for each view controller, but Interface Builder has a handy option named Use Storyboard ID that lets you use your Storyboard IDs for restoration identifiers as well.

In Main.storyboard, click on the tab bar controller and open the Identity Inspector. Enable the Use Storyboard ID option as shown below:

Use Storyboard ID

This will archive the view controller and restore it during the state restoration process.

Repeat the process for the navigation controller and the three view controllers. Make sure you’ve checked Use Storyboard ID for each of the view controllers, or your app may not restore its state properly.

Note that all the controllers already have a Storyboard ID and the checkbox simply uses the same string that you already have as Storyboard ID. If you are not using Storyboard IDs, you need to manually enter a unique Restoration ID.

Restoration identifiers come together to make restoration paths that form a unique path to any view controller in your app; it’s analagous to URIs in an API, where a unique path identifies a unique path to each resource.

For example, the following path represents MatchedPetsCollectionViewController:

RootTabBarController/NavigationController/MatchedPetsCollectionViewController

With this bit of functionality, the app will remember which view controller you left off on (for the most part), and any UIKit views will retain their previous state.

Build and run your app; test the flow for restoration back to the pet details view. Once you pause and restore your app, you should see the following:

No Data

Although the system restores the correct view controller, it appears to be missing the cat object that’s needed to populate the view. How do you restore the view controller and the objects it needs?

The UIStateRestoring Protocol

When it comes to implementing state restoration, UIKit does a lot for you, but your app is responsible for a few things on its own:

  1. Telling UIKit it wants to participate in state restoration, which you did in your app delegate.
  2. Telling UIKit which view controllers and views should be preserved and restored. You took care of this by assigning restoration identifiers to your view controllers.
  3. Encoding and decoding any relevant data necessary to reconstruct the view controller to its previous state. You haven’t done this yet, but that’s where the UIStateRestoring protocol comes in.

Every view controller with a restoration identifier will receive a call to encodeRestorableStateWithCoder(_:) of the UIStateRestoring protocol when the app is saved. Additionally, the view controller will receive a call to decodeRestorableStateWithCoder(_:) when the app is restored.

To complete the restoration flow, you need to add logic to encode and decode your view controllers. While this part of the process is probably the most time-consuming, the concepts are relatively straightforward. You’d usually write an extension to add conformance to a protocol, but UIKit automatically registers view controllers to conform to UIStateRestoring — you merely need to override the appropriate methods.

Open PetDetailsViewController.swift and add the following code to the end of the class:

override func encodeRestorableStateWithCoder(coder: NSCoder) {
  //1
  if let petId = petId {
    coder.encodeInteger(petId, forKey: "petId")
  }
 
  //2
  super.encodeRestorableStateWithCoder(coder)
}

Here’s what’s going on in the code above:

  1. If an ID exists for your current cat, save it using the provided encoder so you can retrieve it later.
  2. Make sure to call super so the rest of the inherited state restoration functionality will happen as expected.

With these few changes, your app now saves the current cat’s information. Note that you didn’t actually save the cat model object, but rather the ID you can use later to get the cat object. You use this same concept when saving your selected cats in MatchedPetsCollectionViewController.

Apple is quite clear that state restoration is only for archiving information needed to create view hierarchies and return the app to its original state. It’s tempting to use the provided coders to save and restore simple model data whenever the app goes into the background, but iOS discards all archived data any time state restoration fails or the user kills the app. Since your user won’t be terribly happy to start back at square one each time they restart the app, it’s best to follow Apple’s advice and only save state restoration using this tactic.

Now that you’ve implemented encoding in PetDetailsViewController.swift, you can add the corresponding decoding method below:

override func decodeRestorableStateWithCoder(coder: NSCoder) {
  petId = coder.decodeIntegerForKey("petId")
 
  super.decodeRestorableStateWithCoder(coder)
}

Here you decode the ID and set it back to the view controller’s petId property.

The UIStateRestoring protocol provides applicationFinishedRestoringState() for additional configuration steps once you’ve decoded your view controller’s objects.

Add the following code to PetDetailsViewController.swift:

override func applicationFinishedRestoringState() {
  guard let petId = petId else { return }
  currentPet = MatchedPetsManager.sharedManager.petForId(petId)
}

This sets up the current pet based on the decoded pet ID and completes the restoration of the view controller. You could, of course, do this in decodeRestorableStateWithCoder(_:), but it’s best to keep the logic separate since it can get unwieldy when it’s all bundled together.

Build and run your app; navigate to a pet’s detail view and trigger the save sequence by backgrounding the app then killing it via Xcode. Re-launch the app and verify that your same furry friend appears as expected:

Details

You’ve learned how to restore view controllers created via storyboards. But what about view controllers that you create in code? To restore storyboard-created views at run-time, all UIKit has to do is find them in the main storyboard. Fortunately, it’s almost as easy to restore code-based view controllers.

Restoring Code-based View Controllers

The view controller PetEditViewController is created entirely from code; it’s used to edit a cat’s name and age. You’ll use this to learn how to restore code-created controllers.

Build and run your app; navigate to a cat’s detail view then click Edit. Modify the cat’s name but don’t save your change, like so:

Edit

Now background the app and kill it via Xcode to trigger the save sequence. Re-launch the app, and iOS will return you to the pet detail view instead of the edit view:

Details

Just as you did for the view controllers built in Interface Builder, you’ll need to provide a restoration ID for the view controller and add the encode and decode UIStateRestoring protocol methods to properly restore the state.

Take a look at PetEditViewController.swift; you’ll notice the encode and decode methods already exist. The logic is similar to the encode and decode methods you implemented in the last section, but with a few extra properties.

It’s a straightforward process to assign the restoration identifier manually. Add the following to viewDidLoad() right after the call to super:

restorationIdentifier = "PetEditViewController"

This assigns a unique ID to the restorationIdentifier view controller property.

During the state restoration process, UIKit needs to know where to get the view controller reference. Add the following code just below the point where you assign restorationIdentifier:

restorationClass = PetEditViewController.self

This sets up PetEditViewController as the restoration class responsible for instantiating the view controller. Restoration classes must adopt the UIViewControllerRestoration protocol and implement the required restoration method. To that end, add the following extension to the end of PetEditViewController.swift:

extension PetEditViewController: UIViewControllerRestoration {
  static func viewControllerWithRestorationIdentifierPath(identifierComponents: [AnyObject], 
      coder: NSCoder) -> UIViewController? {
    let vc = PetEditViewController()
    return vc
  }
}

This implements the required UIViewControllerRestoration protocol method to return an instance of the class. Now that UIKit has a copy of the object it’s looking for, iOS can call the encode and decode methods and restore the state.

Build and run your app; navigate to a cat’s edit view. Change the cat’s name as you did before, but don’t save your change, then background the app and kill it via Xcode. Re-launch your app and verify all the work you did to come up with a great unique name for your furry friend was not all in vain!

Edit

Where to Go From Here?

You can download the completed project here. The state restoration framework is an extremely useful tool in any iOS developers toolkit; you now have the knowledge to add basic restoration code to any app and improve your user experience just a little more.

For further information on what’s possible with this framework, check out the WWDC videos from 2012 and 2013. The 2013 presentation is especially useful since it covers restoration concepts introduced in iOS 7 such as UIObjectRestoration for saving and restoring arbitrary objects and UIDataSourceModelAssociation for restoring table and collection views in apps with more complicated needs.

If you have any questions or comments about this tutorial, please join the forum discussion below!

The post State Restoration Tutorial: Getting Started appeared first on Ray Wenderlich.

Video Tutorial: Introducing Concurrency Part 7: Grand Central Dispatch

2D iOS & tvOS Games by Tutorials Update Now Available!

$
0
0

2D iOS and tvOS Games by Tutorials Now Available!

This is just a quick note to let you know we have released an update to the 2D iOS & tvOS Games by Tutorials (version 1.2).

Here’s what’s new in this version of 2D iOS & tvOS Games by Tutorials:

  • Crash fix: We have fixed a crash that occurred after the “Game Over” scene at the end of Chapter 17, “Juice Up Your Game”, along with a bug that was preventing the background music to repeat upon game restarts. These issues were caused by a recent release of Xcode.
  • Errata fixes: We have also added several minor corrections for issues pointed out by the errata thread on the book forums.

Here’s how you can get the update:

  • If you’re a 2D iOS & tvOS Games by Tutorial PDF customer, you can download the update for free on your My Loot page (version 1.2).
  • If you haven’t picked up a copy of 2D iOS & tvOS Games by Tutorials yet, grab your copy now.

The team and I hope you enjoy this update!

The post 2D iOS & tvOS Games by Tutorials Update Now Available! appeared first on Ray Wenderlich.

Viewing all 4370 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>