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

iOS 9 Multitasking Tutorial

$
0
0
Note from Ray: This is an abridged version of a chapter from iOS 9 by Tutorials, to give you a sneak peek of what’s inside the book, released as part of the iOS 9 Feast. We hope you enjoy!

iOS9_feast_API_blend

iOS 9 introduces a phenomenal feature for the iPad — multitasking. For the first time, iPad users can run two apps on the screen at the same time.

Maybe you want to read a proposal in your email app while you research the topic in Safari. Or you’d like to keep an eye on Twitter while you enjoy your favorite sports show. For a device that you can hold in one hand, this is a crazy amount of productivity power. It’s undoubtedly going to change the way users interact with their iPads.

In this iOS 9 multitasking tutorial, you’ll learn how to update an existing app so that it plays nicely in a multi-tasking iPad environment.

Getting started

In this tutorial, you’ll work on an app called Travelog. It’s a simple app that you use to keep a diary of a business trip or a vacation. Start by downloading the starter project for this tutorial and run it on the iPad Air 2 Simulator. The app is already seeded with some entries:

ios9-multitasking-000

The app uses UISplitViewController to display entries on the left side. Tap any entry to display it in the right-hand view; rotate the device and you’ll find both master and detail views of the Split View Controller are visible in both orientations.

It’s time to see how the app behaves in a multitasking environment. Swipe from the right edge of the screen to expose the list of multitasking-ready apps on your iPad. This can be tricky in the simulator; try starting with your mouse pointer just inside the simulator window to simulate a swipe in from the edge.

Tap on any app to launch it. A small version of the app opens in the previous position of the list. At this point you’re in Slide Over multitasking mode. Note that Travelog is dimmed out but otherwise unaffected. The app running in Slide Over mode sits on top of Travelog, and a short handle bar sits at top of the Slide Over. Swipe down on the handle to expose the list of multitasking apps and launch a different app in the Slide Over.

You’ll notice a handle at the edge of the Slide Over view. Tap it, and you’ll see the following:

ios9-multitasking-001

W00t! The screen just divided in two! Isn’t that neat?! This is Split View multitasking mode. Travelog is now available for use and resized itself to fit the new, narrower portion of the window.

Note: If an app isn’t multitasking ready, it won’t appear in the list. Even more reason to get your app ready for multitasking as soon as possible! :]

The primary app is the original running app, while the secondary app is the newly opened app. If you drag the divider further out, the screen will split 50:50 between the apps. Drag it all the way to the other side and you’re back to single app mode. The primary app is backgrounded at this point.

Now that you have an idea of the multitasking modes on iPad, it’s time to take a closer look and improve your app to better support multitasking.

Preparing your app for multitasking

Here’s the good news: if you paid attention at WWDC 2014 and built a universal app with size classes, adaptive layout and a launch storyboard or XIB, you’re done! Rebuild your app with the iOS 9 SDK, go grab yourself a beverage and I’ll see you next year!

What’s that? You live in the real world and don’t quite have all the above implemented in your app? Okay then; this tutorial will walk you through what it takes to make your app multitasking-ready.

Any new project created in Xcode 7 is automatically multitasking-ready. An existing app you convert to Xcode 7 automatically becomes multitasking-ready if your app:

  • Is a universal app
  • Is compiled with SDK 9.x
  • Supports all orientations
  • Uses a launch storyboard

Since all the required criteria are in place, Travelog automatically becomes multitasking ready. That’s great news, but just because it’s multitasking ready doesn’t mean that everything will work as expected. The remainder of this tutorial will help you work through common pitfalls encountered when converting existing apps to multitasking apps.

Orientation and size changes

Run Travelog in Split View mode and rotate the iPad to portrait orientation; you’ll see the app layout changes:

ios9-multitasking-002

While this layout is functional, it can certainly stand to be improved. There’s whitespace wasted on the left hand side and all the labels are squashed over to the right hand side.

Now rotate the device to landscape orientation:

ios9-multitasking-003

Again, it’s functional, but the master view column is too narrow and the text inside the table view cells doesn’t really provide any value.

The app already performs some layout updates on orientation change; that seems like the best place to start.

Open SplitViewController.swift; this is a subclass of UISplitViewController and overrides viewDidLayoutSubviews() so it can update the maximum width of primary column via helper method updateMaximumPrimaryColumnWidth(). The implementation of updateMaximumPrimaryColumnWidth() checks the status bar orientation to determine what the maximum width should be. This approach won’t work any longer, since the app can still have a narrow window in split view mode when it’s in landscape orientation.

UIKit provides a number of anchor points where you can hook in and update your layout:

  1. willTransitionToTraitCollection(_:, withTransitionCoordinator:)
  2. viewWillTransitionToSize(_:, withTransitionCoordinator:)
  3. traitCollectionDidChange(_:):

Not all multitasking or orientation changes trigger a size class change, so you can’t simply rely on size class changes to provide the best user experience.

It looks like viewWillTransitionToSize(_:, withTransitionCoordinator:) is a good candidate for an update. Remove viewDidLayoutSubviews() and updateMaximumPrimaryColumnWidth() from SplitViewController.swift and add the following:

func updateMaximumPrimaryColumnWidthBasedOnSize(size: CGSize) {
  if size.width < UIScreen.mainScreen().bounds.width
    || size.width < size.height {
      maximumPrimaryColumnWidth = 170.0
  } else {
    maximumPrimaryColumnWidth = UISplitViewControllerAutomaticDimension
  }
}

This helper method updates the split view’s maximum primary column width; it returns the smaller version when the split view is narrower than the screen, such as in a multitasking situation, or when the split view itself has a portrait orientation.

You’ll need to call this helper method when the view is first loaded, so add the following:

override func viewDidLoad() {
  super.viewDidLoad()
  updateMaximumPrimaryColumnWidthBasedOnSize(view.bounds.size)
}

This ensures that the split view starts in the right configuration.

Add one final method:

override func viewWillTransitionToSize(size: CGSize,
  withTransitionCoordinator coordinator:
  UIViewControllerTransitionCoordinator) {
    super.viewWillTransitionToSize(size,
      withTransitionCoordinator: coordinator)
    updateMaximumPrimaryColumnWidthBasedOnSize(size)
}

This method updates the primary column when the size changes.

Build and run your app; first verify for all orientations that the app still looks and behaves as it did before multitasking. Then bring in another app in Split View and try some different orientations:

ios9-multitasking-004

Hmm — it’s certainly not fixed. It even looks more broken now: with multitasking enabled in landscape orientation, the master column view has been jacked up! It looks like the table view cell doesn’t adapt to size changes appropriately.

Open LogCell.swift and find the implementation of layoutSubviews(); you’ll see the code checks for UIScreen.mainScreen().bounds.width to determine whether it should use the compact view or regular view.

UIScreen always represents the entire screen, regardless of the multitasking state. However, you can’t rely on screen sizes alone anymore. Update the implementation of layoutSubviews() as follows:

override func layoutSubviews() {
  super.layoutSubviews()
  let isTooNarrow = bounds.width <= LogCell.widthThreshold
  // some code ...
}

Also update widthThreshold, declared at the beginning of LogCell, as follows:

static let widthThreshold: CGFloat = 180.0

The updated code checks the width of the cell itself instead of the width of the screen. This decouples the view’s behavior from that of its superview. Adaptivity is now self-contained! :]

Build and run; again, verify the app still looks and behaves as it did before multitasking. This time around, Split View mode should play nicely in all orientations:

ios9-multitasking-005

Adaptive presentation

Let’s try another scenario: this time with the device in landscape orientation and the Split View at 33%, tap the Photo Library bar button. You’ll see the following popover:

ios9-multitasking-006

With the popover still visible, drag the divider further to the left so the screen is evenly divided between the two apps:

ios9-multitasking-007

The popover automatically turned into a modal view without any action on your part; dragging the divider to 50% changes the horizontal size class of the app from regular to compact. That’s neat, but it’s not quite the functionality you’re looking for.

Instead, you only want to present the Photo Library in a modal fashion when the app is in Slide Over mode, or when it’s the secondary (smaller) app in the 33% Split View mode. When your app is full screen or has 50% width, you’d prefer to present the Photo Library in a popover.

iOS 8 introduced UIPopoverPresentationController to manage the display of the content in a popover; you use it along with the UIModalPresentationPopover presentation style to present popovers. However, you can intercept the presentation and customize it with UIPopoverPresentationControllerDelegate callbacks.

Open LogsViewController.swift and add the following class extension to the end of the file:

extension LogsViewController : UIPopoverPresentationControllerDelegate {
 
  func adaptivePresentationStyleForPresentationController(controller:
    UIPresentationController,
    traitCollection: UITraitCollection) -> UIModalPresentationStyle {
      //1
      guard traitCollection.userInterfaceIdiom == .Pad else {
        return .FullScreen
      }
 
      if splitViewController?.view.bounds.width > 320 {
        return .None
      } else {
        return .FullScreen
      }
  }
}

Here’s a breakdown of the code:

  1. Check that the app is running on an iPad; the photo picker should always be presented modally on the iPhone.
  2. Check that the split view controller is larger than 320 points — the size of the Slide Over / 33% view. If so, return .None to retain the popover, otherwise return .FullScreen for a modal presentation instead.

Now you can make LogsViewController a delegate of the popover presentation controller.

Find the implementation of presentImagePickerControllerWithSourceType(_:). Read through the implementation and you’ll see that when the source type is .PhotoLibrary, UIImagePickerController presents as a popover. Update the implementation by adding presenter?.delegate = self as shown below:

func presentImagePickerControllerWithSourceType(sourceType:
  UIImagePickerControllerSourceType) {
    // some code...
    if sourceType == UIImagePickerControllerSourceType.PhotoLibrary {
      // some code...
      presenter?.delegate = self
    }
    // some code...
}

Build and run your app; verify that the popover transitions to a modal fullscreen view only when your app is in the Slide Over mode or when the Split View pane is sufficiently narrow.

ios9-multitasking-008

Design Considerations

Beyond coding considerations, you’ll need to change your approach to app visual design a little differently:

  • Be flexible: Step away from a pixel-perfect design for various platforms and orientations. You need to think about different sizes and how you can have a flexible app that responds appropriately to size changes.
  • Use Auto Layout: Remove hardcoded sizes or custom code that resizes elements. It’s time to consider Auto Layout and make your code more flexible and future-proof.
  • Use size classes: One single layout won’t always fit all displays. Use size classes to build a base layout and then customize each specific size class based on individual needs. But don’t treat each size class as a completely separate design; as you saw in this tutorial, your app should easily transition from one size class to another, and you don’t want to surprise your user with a dramatic change as they drag the divider.

Where to go from here?

You can download the completed project here.

This iOS 9 multitasking tutorial only touched on the basics of multitasking — it’s up to developers like you to help chart the course for accepted multitasking design patterns of the future.

This tutorial was an abbreviated version of Chapter 5, “Multitasking” from iOS 9 by Tutorials. If you’d like to learn more about multitasking and other new features in iOS 9 please check out the book!

In the meantime, if you have any questions or comments about this tutorial or Stack Views in general, please join the forum discussion below!

The post iOS 9 Multitasking Tutorial appeared first on Ray Wenderlich.


RWDevCon 2016: 4 New Sponsors, and Tutorial Poll!

$
0
0

A lot has happened since I last posted about RWDevCon, so I wanted to give you a quick status update.

New Sponsors

First, we are happy to announce 4 new sponsors for the conference:

rwdevcon_sponsors2

  • Savvy Apps (gold sponsor): Savvy Apps is a full-service mobile development company that’s driven by making life better, one app at a time. They have worked on award-winning mobile apps from Homesnap to PBS for iPad to Musx and more.
  • LaunchKit (silver sponsor): LaunchKit is a suite of tools that makes it easier to build, launch, and manage mobile apps – such as a screenshot builder, review monitor, sales reporter, and app website generator.
  • WillowTree (silver sponsor): WillowTree is a mobile app development company that excels at bleeding-edge projects. They have worked with clients such as GE, Johnson & Johnson, and the NBA to create the best mobile experience possible.
  • FastSpring (bronze sponsor): FastSpring is your complete e-commerce solution for payments and subscriptions. It’s used as the back-end for the stores of many popular Mac apps, and is the back end for the store on this site! :]

Topic Poll Tomorrow

As you may know, one of the unique features of RWDevCon is that the attendees choose what topics we give tutorials on!

A while back, we had a brainstorming round of topic ideas from team members & attendees. Tomorrow, we are sending out a poll where attendees can select from the following topics:

  • 3D Touch
  • Accessibility
  • Accelerate and other advanced computation topics
  • Alamofire
  • Android Development for iOS Developers
  • Android: Android Wear
  • App Architecture – Including MVVM and others
  • Audio Generation / Manipulation / Plugin Writing
  • Adaptive Layout, Advanced
  • Auto Layout, Advanced
  • AVFoundation
  • Business of App Development, The
  • CloudKit, Beginning
  • CloudKit, Advanced
  • CocoaPods and Carthage
  • Continuity (Handoff)
  • Core Animation Layer Masks
  • Core Audio Tutorial
  • Core Bluetooth
  • Core Data vs. CloudKit vs. iCloud vs. Parse vs. FireBase
  • Core Data: Building a Swift Core Data Stack
  • Core Data: Device to Online Service Synchronization
  • Core Data: High Performance
  • Core Graphics
  • Core Location
  • Core Motion
  • Custom Back-end for an iOS App, Making
  • Custom Controls in iOS
  • Custom Presentations and Transitions, Advanced
  • Functional Programming
  • GameplayKit
  • GCD Beginner
  • GCD Advanced
  • Godot Engine
  • HealthKit
  • iBeacons
  • Instruments in Xcode
  • Integrating Data from Workout Apps with Watch / HealthKit
  • Internationalization
  • iOS & Bluetooth
  • iOS & Internet of Things integration
  • iOS 9 Multitasking
  • iOS 9 Search APIs
  • iOS Design Patterns in Swift
  • iOS Security
  • Javascript Core
  • Libraries and Frameworks, Building
  • LLDB, Beginning
  • LLDB, Advanced
  • Keeping App Data In Sync Across iPhone, iPad, and Apple TV
  • MapKit
  • Math for Programmers
  • Metal: for Beginners
  • Metal: Custom 2D or 3D UI
  • NSOperation, Advanced
  • NSPredicate
  • NSURLSession, Advanced
  • On-Demand Resources and App Thinning
  • OS X for iOS Developers
  • Parse Local Data Store
  • Reactive Cocoa / RxSwift
  • React Native
  • Realm
  • Regexes : in unit testing, data validation, etc
  • SceneKit: For Beginners
  • SpriteKit: For Beginners
  • SpriteKit: Scene Editor
  • SpriteKit: Building tvOS Games
  • Stack Views (UIStackView)
  • Swift 2: For Beginners
  • Swift 2: Error Handling
  • Swift 2: Reference vs. Value Types
  • Swift 2: Optionals Made Easy
  • Swift 2: Protocol Oriented Programming in Practice
  • Swift 2: Interoperability with Objective-C In-Depth
  • Swift 2: Programming in a Swift (rather than Obj-C) Style
  • Swift 2: Adopting Swift in a large production app
  • Test Driven Development
  • tvOS: Making Native Apps
  • tvOS: Making TVML Apps
  • tvOS: Understanding video streaming
  • tvOS: Reusing code between tvOS & iOS Apps
  • UIAnimation: For Beginners
  • UIAnimation: CALayer animations
  • Unit Testing
  • Unity
  • watchOS 2: For Beginners
  • watchOS 2: For Beginners, Part 2
  • watchOS: Notifications
  • watchOS: Glances
  • watchOS: Connectivity
  • watchOS: Complications
  • Xcode for Beginners
  • Xcode Server
  • Xcode Tips & Tricks, Advanced
  • Xcode UI Testing

We’ll be choosing the final topics based on a combination of popular requests and our areas of expertise. We can’t wait to see what ends up winning the poll!

Where To Go From Here?

After we get the poll results, we’ll invite a second round of speakers and build out the schedule. We’ll post the schedule here when it’s ready.

As for tickets, they’re going extremely fast. We already have 199 confirmed attendees (more than last year already), and have just 30 tickets left!

If you want a ticket, be sure to grab your ticket now so you don’t regret missing out later. If you sign up today, you can participate in the tutorial poll tomorrow! :]

The team and I look forward to meeting you at RWDevCon for some tutorials, inspiration, and fun!

The post RWDevCon 2016: 4 New Sponsors, and Tutorial Poll! appeared first on Ray Wenderlich.

iOS 9 Storyboards Tutorial: What’s New in Storyboards?

$
0
0
Note from Ray: This is an abridged version of a chapter from iOS 9 by Tutorials, to give you a sneak peek of what’s inside the book, released as part of the iOS 9 Feast. We hope you enjoy!

iOS9_feast_API_blendStoryboards have been around since iOS 5 and have received lots of upgrades and new features since then, including unwind segues for reverse navigation, universal storyboards for both iPhone and iPad, and live rendering of views designed in code.

Xcode 7 brings new features for storyboards that let you do the following:

  • Refactor a single storyboard into multiple storyboards and link them visually via storyboard references.
  • Add supplementary views to a view controller using the scene dock.
  • Add multiple buttons to a navigation bar, right from the storyboard itself!

In this iOS 9 storyboards tutorial, you’ll learn how to use storyboard references and supplementary views. You’ll be updating an app designed to help you with all those listable moments in life, whether it’s grocery shopping, packing your luggage for vacation, or a survival checklist for the impending zombie apocalypse! :]

25-ExpandedNotes2

To get the most out of this tutorial you should have some basic storyboard and table view knowledge. Need a quick brush-up? Check out our Storyboards Tutorial in iOS 9.

Getting started

Download the starter project for this tutorial and run it in the simulator; tap one of the displayed checklists to view the items contained within, then tap any entry to check it off. Done and done!

01-Prepped

Take a quick look at the code to get your bearings.

ChecklistsViewController.swift displays the initial list of checklists, and ChecklistDetailViewController.swift displays the items within each list. Main.storyboard contains the user interface items.

Your task in this tutorial is to improve Prepped so that the storyboard is more organized; you’ll also be able to view notes for list items and add diary entries to record your zombie survival efforts.

There are two unused scenes in the storyboard. When you’ve completed this tutorial, you may like to incorporate these scenes into Prepped so that you can add items and notes to a checklist.

Storyboard references

If you’ve used storyboards on a large project or as part of a team with other developers, you’ll know they can quickly become unwieldy. Merge conflicts, spaghetti-like segue arrows and navigating your way around a wall of scenes is enough to make anybody question whether storyboards are worth the effort.

Although you’ve always been able to use multiple storyboards in your apps, you’ve never been able to segue between them using Interface Builder. To present a view controller from a different storyboard, you’d have to instantiate it first and present it in code. But no longer!

With Xcode 7, you can add references between storyboards right in Interface Builder using storyboard references, which can either point to specific view controllers or to the initial view controller within another storyboard. This makes it much easier to divide up storyboards into smaller storyboards, and alleviates many of the issues mentioned above without needing to add any extra code.

Multiple smaller storyboards also make it possible for other team members to work independently on their own storyboards without stepping on each other’s toes.

Enough theory — time to put it into practice!

Note: Storyboard references are actually backwards-compatible to iOS 8. However, in iOS 8 you can’t use a storyboard reference with a relationship segue, or use it to point to storyboards in external bundles.

Creating your first storyboard reference

In its current state, Prepped is a small app in the early stages of development, but there’s enough structure there to discern where to divide up the main storyboard. Container view controllers are a good place to consider splitting out functionality into new storyboards.

Prepped uses a tab bar controller, and in this case it makes sense to separate each tab’s children into their own storyboards.

Open Main.storyboard and zoom out so you can see all six scenes. Hold Command and press + to zoom in and to zoom out, or right-click on a blank area in the storyboard and choose your zoom level.

Click and drag to highlight all scenes in the storyboard except for the tab bar controller on the left-hand side:

02-HighlightStoryboard

Select Editor\Refactor to Storyboard and enter Checklists.storyboard as the name of the new storyboard. Set the Group to Checklists, then click Save.

As if by magic, Xcode does the following:

  1. Splits out the selected scenes into a new storyboard.
  2. Changes the target of the tab bar controller’s “view controllers” segue to a storyboard reference that points to the relevant scene in the new storyboard.
  3. Takes you to the new storyboard.

You may have to zoom out and reposition the new storyboard to see all of its scenes. The arrangement of the scenes and their segues is exactly like it was in the original storyboard. Here’s what the new storyboard should look like:

03-Refactored

But what happened to the original storyboard? Open Main.storyboard and take a look:

04-AfterRefactor

The tab bar controller’s “view controllers” segue now points to the storyboard reference for the navigation controller in Checklists.storyboard. The storyboard reference uses the navigation controller’s storyboard ID to determine which scene to segue to in the new storyboard.

There are a few ‘dangling’ storyboard references to view controllers that had storyboard IDs set; you won’t need these any longer. Select ChecklistDetailViewController, AddChecklistItemNavigationController and AddChecklistItemViewController and delete them.

Note: If a scene has an empty storyboard ID, the Refactor to Storyboard command automatically generates an ugly one, such as UIViewController-gtY-c7-gYu. You can change this later, but it’s much easier to keep track of things when you explicitly set the storyboard IDs yourself.

Instead of referencing specific view controllers, storyboard references can simply refer to the initial scene in a storyboard.

Still in Main.storyboard, select the new storyboard reference named ChecklistsNavigationController and use the Attributes Inspector to remove the Referenced ID, like so:

05-StoryboardReferenceID

The reference now points to the initial view controller in Checklists.storyboard, and updates as shown:

06-ChecklistsStoryboardRef

Open Checklists.storyboard and select the Checklists Navigation Controller scene. Use the Attributes Inspector to check Is Initial View Controller; this indicates this scene should be the entry point for the storyboard.

07-NavigationStoryboardID

Note: The initial view controller of a storyboard has an arrow pointing to it from the left-hand side.

Build and run your project; the app performs just as it did when you started. The only difference is that things are a little more organized behind the scenes!

Storyboards within a team

Distributed development of storyboards has always been a challenge; in fact, many developers still avoid storyboards out of fear of the dreaded merge conflict. But storyboard references can help you avoid the complications of team storyboard development.

Consider the following scenario: you’re writing Prepped with a fellow apocalypse survivor, whose task it is to create the functionality to handle the diary entries. She’s built it using a separate storyboard, and now you need to add it to your own storyboard hierarchy…before the zombies descend upon your little enclave.

In the project navigator, select the top level Prepped group, located just below the project itself. Click File\Add Files to “Prepped”. Navigate to the Prepped folder, and select the Diary folder. Ensure that Copy items if needed is checked in the dialog box, and that Added folders is set to Create groups. Ensure that Add to targets is ticked for Prepped. Click Add to add the folder and its contents to the project.

In Main.storyboard, drag a storyboard reference from the Object Library into an empty space on the storyboard:

08-StoryboardReference

Ctrl-drag from the existing tab bar controller scene to the storyboard reference:

09-ConnectStoryboardRef

In the pop-up that appears, choose view controllers from the Relationship Segue section.

Select the storyboard reference you just added. In the Attributes Inspector set the Storyboard to Diary:

10-DiaryStoryboardRef

Build and run your app; you’ll see one tab to handle Checklists, and another tab for the Diary entries – the functionality your teammate worked on. You can now add Diary entries using the storyboard scenes and code created by your sister-in-arms:

11-Diary

Note: Currently both tabs in the tab bar controller in the storyboard display the title Item. The proper title will be loaded at runtime from the Checklists and Diary storyboards. You can change the titles in Main.storyboard for your own reference, but it won’t make any difference at runtime.

Focusing on a storyboard

Isn’t it annoying when you have to tap through a bunch of scenes in your app, when you’re just trying to test one single scene buried deep in the stack? With storyboard references you can isolate the scenes you’re interested in into their own storyboard and instruct the app to launch straight into that. You’ll do that now for the checklist item section.

In Checklists.storyboard highlight the Checklist Detail View Controller, Add Item Navigation Controller and Add Item View Controller scenes:

12-ItemsRefactored

Select Editor\Refactor to Storyboard and name the new storyboard ChecklistDetail.storyboard. Ensure that the Group is still set to Checklists.

Just as you did for the Checklists storyboard, select the Checklist Detail View Controller scene in ChecklistDetail.storyboard, and use the Attributes Inspector to check Is Initial View Controller. The Checklist Detail View Controller should now have an arrow on its left to indicate it’s the first scene in the storyboard.

Click on the Prepped project at the top of the project navigator, then click on Prepped target and choose the General tab. Change Main Interface to ChecklistDetail.storyboard:

13-ProjectSettings1

Build and run your app; you’ll see the checklist detail scene loads first:

14-ChecklistDetail

Where are the navigation and tab bar? Since the view controller is no longer embedded in a navigation or tab bar controller, you won’t see those two elements while you’re working on the items storyboard.

Note: This approach will fail if the initial view controller in the chosen storyboard requires data provided via a segue. In this project, ChecklistDetailViewController has already been set up to load initial sample data.

Views in the scene dock

A lesser-known feature of storyboard scenes is the scene dock. Most people don’t even notice it’s there – did you? You’ll find it at the top of the currently selected scene in a storyboard:

15-SceneDock

Out of the box, the scene dock contains references to the current view controller, the first responder, and any available unwind segues. But did you know you can add your own views to the scene dock? You’ve always been able to do so, but Xcode 7 lets you design these attached views within Interface Builder.

Any views you add in the scene dock won’t be added to your view controller’s initial subviews array; instead, you can add IBOutlets to them and make use of them at runtime.

Selecting a checklist item in Prepped highlights its table row with a boring gray color. You will now perform the amazing feat of changing the color of the selected row with no code at all — thanks to the scene dock!

In ChecklistDetail.storyboard, select Checklist Detail View Controller and drag a view from the Object Library onto the scene dock:

16-DragViewOntoSceneDock

The new view will appear just above the scene dock. You can add subviews and controls to these docked views, just as you would any other view.

17-ViewInSceneDock

Select the view you added and use the Attributes Inspector to change the background color of the view to #FFFAE8.

The size of the view in the storyboard doesn’t really matter, since it will be stretched automatically when it’s used in the cell. However, if you want it to take up less room you can resize it by dragging its top, left and right edges.

In the document outline, Ctrl-drag from ChecklistItemCell to the new view. Choose selectedBackgroundView from the connections pop-up:

18-ConnectSelectedView

Build and run your app; tap any row, and it’s highlighted with by your new view. Pretty neat — and without a stitch of code!

19-SelectedViewColoring

Note: This coloring method will only work for table views that don’t have multiple selection enabled. Only one instance of the colored view is created, and it’s shared between each cell in the table view. As such, it can only be applied to one cell at a time.

Conditional views using the scene dock

Often, you’ll have a view that you only want to show under certain conditions. Designing a view like this amongst all the other views in a view controller was always rather difficult in storyboards. The advantage of having a view in the scene dock is that you can create it visually without interfering with the rest of your view controller’s subviews. You can then add it to the view hierarchy in code when it’s needed.

The checklist items in Prepped’s sample data have notes accompanying them; you’re now going to create a view to display an item’s note. When you tap the table view row for an item, the row will expand to display the associated note. Tapping the row again or tapping a different row collapses the row and removes the note view from that row.

Still in ChecklistDetail.storyboard, drag a new view onto the scene dock, next to the selected background view you created in the last section. Select the view, and use the Size Inspector to set its width to 320 and its height to 128.

Drag a label from the Object Library onto the new view and use the Attributes Inspector to change the label text to Notes:”. You may have to resize the label so that the text fits. Change the label’s text color to #BB991E:

20-NotesLabel

Next, drag a text view from the Object Library onto the new view. Remove its default Lorem ipsum text using the Attributes Inspector. Uncheck Behavior Editable and Selectable. Resize and rearrange the label and text views so they touch the edges of their container so that it looks like this:

21-NotesTextView

You’ll now connect this notes view to an IBOutlet in the view controller. Even though there are multiple cell instances on the screen at one time, there will be only one notes view instance at any time, so it won’t be an issue to connect this view to an outlet.

With ChecklistDetail.storyboard open in the main editor, open ChecklistDetailViewController.swift in the assistant editor. You may have to close the document outline using the icon beneath the storyboard to get enough space:

22-DocumentOutline

Ctrl-drag from the new view to ChecklistDetailViewController to create an outlet for the view just below the existing checklist property. Ensure that you are dragging from the view’s background, not from the text view or label. You can also drag from the view’s icon in the scene dock.

23-CreateOutlet

Name the outlet notesView and click Connect. The outlet will appear as a property in ChecklistDetailViewController.

Now Ctrl-drag from the text view to ChecklistDetailViewController to create another outlet just below the one you just made. Name the outlet notesTextView and click Connect.

Finally, it’s time to write some code! :] You’ll use another new feature of iOS 9, UIStackView, to add and remove the notes view from a cell with an animation.

Note: To learn more about UIStackView, be sure to check out Introducing Stack Views which is an excerpt from our book iOS 9 by Tutorials.

In ChecklistDetailViewController.swift, add the following method to the bottom of the main class implementation:

func addNotesViewToCell(cell: ChecklistItemTableViewCell) {
  notesView.heightAnchor
    .constraintEqualToConstant(notesViewHeight)
    .active = true
  notesView.clipsToBounds = true
 
  cell.stackView.addArrangedSubview(notesView)
}

This method ensures Auto Layout defines the the notes view’s height, then adds it to the cell’s stack view’s arrangedSubviews collection. It also sets clipsToBounds to true to prevent the text view from spilling outside of the cell when you perform a swipe-to-delete.

The height needs to be set using Auto Layout since the stack view derives its own height from the heights of its arrangedSubviews. If you don’t set the height here, the cell won’t grow when you add the notes view.

Next, add the following method below addNotesViewToCell(_:):

func removeNotesView() {
  if let stackView = notesView.superview as? UIStackView {
    stackView.removeArrangedSubview(notesView)
    notesView.removeFromSuperview()
  }
}

This removes the notes view from the stack view’s arrangedSubviews as well from its set of visible subviews.

Next, you need to put these methods to use. Still in ChecklistDetailViewController.swift, find the table view delegate extension for ChecklistDetailViewController and add the following code:

override func tableView(tableView: UITableView,
  didSelectRowAtIndexPath indexPath: NSIndexPath) {
    // 1
    guard let cell = tableView.cellForRowAtIndexPath(indexPath) as?
      ChecklistItemTableViewCell else {
        return
    }
 
    // 2
    tableView.beginUpdates()
    // 3
    if cell.stackView.arrangedSubviews.contains(notesView) {
      removeNotesView()
    } else {
      addNotesViewToCell(cell)
 
      // 4
      notesTextView.text = checklist.items[indexPath.row].notes
    }
 
    // 5
    tableView.endUpdates()
}

This method does the following:

  1. Uses a Swift 2.0 guard statement to ensure that there is a valid cell of the right type at the selected index path before continuing.
  2. Calls tableView.beginUpdates() to animate the changes to the cell’s height.
  3. Removes the notes view if the cell’s stack view already contains it; otherwise, add the notes view.
  4. Updates the notes text view to contain the notes for the selected checklist item.
  5. Finally, calls tableView.endUpdates() to commit the changes.

Finally — don’t forget that you changed the project’s main interface earlier on. To change the project’s main interface back to the main storyboard: click on the Prepped project in the project navigator, click on the Prepped target and then click on the General tab. Change Main Interface to Main.storyboard:

24-ProjectSettings2

Build and run your app; tap any cell and you should see the notes view appear. Using a stack view means you didn’t need to set any frames manually or add any constraints to the cell other than the one that defines the height of the notes view. In previous versions of iOS, this would’ve been rather more tricky to implement.

25-ExpandedNotes2

Note: Being able to create a view in the scene dock is useful, but only if it is used solely from one view controller. If the supplementary view is reused throughout the app, you’d be better off using a XIB file that you instantiate in code.

Where to go from here?

Here’s the completed example project from this tutorial.

Your app to help you survive the apocalypse is well on the way to being finished! This tutorial about the new storyboard references and an enhanced scene dock should show you there are very few reasons not to use storyboards in your own projects.

This iOS 9 storyboards tutorial was an abbreviated version of Chapter 8, “What’s new in Storyboards” from iOS 9 by Tutorials. Storyboards in Xcode 7 also have greater support for custom segues. We’ve got that covered in Chapter 9, “Custom Segues”. If you decide to convert Prepped into a universal app, you can also read more about supporting multitasking on the iPad in Chapter 5, “Multitasking”.

There are some useful sessions from WWDC 2015 that will help you as well:

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

The post iOS 9 Storyboards Tutorial: What’s New in Storyboards? appeared first on Ray Wenderlich.

watchOS 2 by Tutorials Now Available!

$
0
0

watchOS 2 by Tutorials Now Available!

Note from Ray: Happy Wednesday – it’s book release day during the iOS 9 Feast!

This year at WWDC, Apple introduced watchOS 2, which signifies a huge change for Apple Watch developers. Now, you can make native apps that run directly on your watch.

  • Out is the hybrid architecture where the interface resided on the Watch, but the code executed as an extension on the paired iPhone.
  • In is a much more familiar, although still quite unique, flavor of architecture where the code is still executed as an extension, but within the Watch app running on the device itself.

With this shift, you can now access some of the more popular iOS frameworks from the watch, including Core Data, Core Location, Core Motion, and many, many others. There’s also many brand new features like Complications, Watch Connectivity, and more.

Given the major shift with watchOS 2 development, rather than doing a weak-sauce update of our previous book (WatchKit by Tutorials) we decided to rethink the book from the ground up.

The result is a brand new book, that is available today – watchOS 2 by Tutorials!

About watchOS 2 by Tutorials

watchOS 2 by Tutorials is for intermediate developers, who already know the basics of iOS and Swift development but want to learn how to make apps for the Apple Watch.

watchOS 2 is a whopping 27 chapters and 466 pages, 17 chapters of which are brand new chapters covering new functionality in watchOS 2. Let’s take a quick look at what’s inside:

  1. Chapter 1, Hello, Apple Watch!: Dive straight in and build your first watchOS 2 app–a very modern twist on the age-old “Hello, world!” app.

bezelHello

  1. Chapter 2, Architecture: watchOS 2 might support native apps, but they still have an unusual architecture. This chapter will teach you everything you need to know about this unique aspect of watch apps.
  2. Chapter 3, UI Controls: There’s not a UIView to be found! In this chapter you’ll dig into the suite of interface objects that ship with WatchKit–watchOS’ user interface framework.

image32

  1. Chapter 4, Pickers: WKInterfacePicker is the only programmatic way to work with the Digital Crown. You’ll learn how to set one up, what the different visual modes are, and how to respond to the user interacting with the Digital Crown via the picker.

finished

  1. Chapter 5, Layout: Auto Layout? Nope. Springs and Struts then? Nope. Guess again. Get an overview of the layout system you’ll use to build the interfaces for your watchOS apps.

finished

  1. Chapter 6, Navigation: You’ll learn about the different modes of navigation available on watchOS, as well as how to combine them.

b6

  1. Chapter 7, Tables: Tables are the staple ingredient of almost any watchOS app. Learn how to set them up, how to populate them with data, and just how much they differ from UITableView.

image9

  1. Chapter 8, Menus: Context menus are the watchOS equivalent of action sheets on iOS. You’ll get your hands dirty and learn everything you need to know about creating them and responding to user interaction.

image11

  1. Chapter 9, Animation: The way you animate your interfaces has changed with watchOS 2, with the introduction of a single, UIView-like animation method. You’ll learn everything you need to know about both animated image sequences and the new API in this chapter.

Woodpecker

  1. Chapter 10, Glances: Think of a glance as a read-only, quick and lightweight view of your app, providing your users with timely information. You’ll learn about the interface of a glance, as well as how to provide the underlying data.

finished

  1. Chapter 11, Notifications: watchOS offers support for several different types of notifications, and allows you to customize them to the individual needs of your watch app. In this chapter, you’ll get the complete overview.

custom_dynamic_long_look_notification_bezel

  1. Chapter 12, Complications: Complications are small elements that appear on the user’s selected watch face and provide quick access to frequently used data from within your app. This chapter will walk you through the process of setting up your first complication, along with introducing each of the complication families and their corresponding layout templates.

familyTypes

  1. Chapter 13, Watch Connectivity: With the introduction of native apps, the way the watch app and companion iOS app share data has fundamentally changed. Out are App Groups, and in is the Watch Connectivity framework. In this chapter you’ll learn the basics of setting up device-to-device communication between the Apple Watch and the paired iPhone.

watch_to_phone_side_by_side

  1. Chapter 14, Audio and Video: As a developer, you can now play audio and video on the Apple Watch with watchOS 2. In this chapter, you’ll gain a solid understanding of how to implement this, as well as learn about some of the idiosyncrasies of the APIs, which are related to the unique architecture of a watch app.

final-phone-watch

  1. Chapter 15, Advanced Layout: Take your watch app interfaces to the next level by leveraging the new, and extremely powerful, layout engine in watchOS. Chapter 5 may have set the scene, but in this chapter you’ll take a deep-dive into this new system and learn how to take full advantage of it.

final

  1. Chapter 16, Advanced Tables: Building on what you learned in Chapter 7, it’s time to supercharge your tables. You’ll learn how to use different row controllers, customize table row appearance, and even implement sections, which aren’t natively supported in the APIs provided by Apple.

image9

  1. Chapter 17, Advanced Animation: The proper use of animation in an interface is often the difference between a good watch app and a _great_ watch app! In this chapter you’ll learn how to add subtle and engaging animations to you watch app, as well as how to leverage Grand Central Dispatch to work around some of the limitations of the API.

addNameAnimation

  1. Chapter 18, Advanced Watch Connectivity: In Chapter 13, you learned how to set up a Watch Connectivity session and update the application context. In this chapter, you’ll take a look at some of the other features of the framework, such as background transfers and real-time messaging.

qr_phone_and_watch

  1. Chapter 19, Advanced Complications: Now that you know how to create a basic complication, this chapter will walk you through adding Time Travel support, as well giving you the lowdown on how to efficiently update the data presented by your complication.

timeTravelAnimation

  1. Chapter 20, Handoff: Want to allow your watch app users to begin a task on their watch and then continue it on their iPhone? Sure you do, and this chapter will show exactly how to do that through the use of Handoff.

handoff02

  1. Chapter 21, Core Motion: The Apple Watch doesn’t have every sensor the iPhone does, but you can access what is available via the Core Motion framework. In this chapter, you’ll learn how to set up Core Motion, how to request authorization, and how to use the framework to track the user’s steps.

bezelDreamWalker

  1. Chapter 22, HealthKit: The HealthKit framework allows you to access much of the data stored in user’s health store, including their heart rate! This chapter will walk you through incorporating HealthKit into your watch app, from managing authorization to recording a workout session.

Watch_ActiveWorkout_bez

  1. Chapter 23, Core Location: A lot of apps are now location aware, but in order to provide this functionality you need access to the user’s location. With watchOS 2, developers now have exactly that via the Core Location framework. Learn everything you need to know about using the framework on the watch in this chapter.

bezel-01

  1. Chapter 24, Networking: NSURLSession, meet Apple Watch. That’s right, you can now make network calls directly from the watch, and this chapter will show you the in’s and out’s of doing just that.

Watch_ResultsTop_bezel

  1. Chapter 25, Haptic Feedback: The Taptic Engine in the Apple Watch allows apps to send taps to the wearers wrist, as a subtle and discreet way to communicate information or provide feedback. In this chapter, you’ll learn how to take advantage of the Taptic Engine to provide Haptic feedback to your users.

bezel

  1. Chapter 26, Localization: Learn how to expand your reach and grow a truly international audience by localizing your watch app using the tools and APIs provided by Apple.

bezel-4

  1. Chapter 27, Accessibility: You want as many people as possible to enjoy your watch app, right? Learn all about the assistive technologies available in watchOS, such as VoiceOver and Dynamic Type, so you can make your app just as enjoyable for those with disabilities as it is for those without.

bezel

One thing you can count on: after reading this book you’ll have all the experience necessary to build rich and engaging apps for Apple’s new Apple Watch platform.

Where To Go From Here?

Pretty cool, eh? Here’s how you can get your copy:

  • If you are a WatchKit by Tutorials Customer: We are offering this book at 50% off this new book to thank you for your support – check your email for a coupon code. If you don’t see it, check your spam or contact us.
  • If you preordered watch watchOS 2 by Tutorials: You can download the book immediately on your My Loot page.
  • If you don’t have the book yet: What are you waiting for – grab your copy now! :]

With the advent of the changes in watchOS 2, if you’re yet to begin your journey of Apple Watch development, you couldn’t have picked a better time.

Prepare yourself for your own private tour through the amazing new features of watchOS 2. The team and I hope you enjoy the book, and look forward to seeing some great Apple Watch apps made by you! :]

The post watchOS 2 by Tutorials Now Available! appeared first on Ray Wenderlich.

New Video Tutorial Series: Testing in iOS

$
0
0

As part of this year’s iOS 9 Feast, we are releasing a new video tutorial series every Thursday.

This week, we are happy to release a brand new video tutorial series – Testing in iOS by Greg Heo!

UnitTestingVideos

Unit testing lets you prove the correctness of your code. You can ensure your objects work as intended, prevent bugs from reappearing, and new in Xcode 7—automatically test parts of your UI.

In this series, Greg demonstrates the basics of the XCTest framework. You’ll learn how to write unit tests to ensure an interface works as expected, then move on to test asynchronous tasks and performance tests.

In the final two videos, you’ll learn how to write user interface tests, both manually and using the new recording features.

All 7 parts of the series are available today. You can check them out here:

We hope you enjoy this new video tutorial series, and thanks for subscribing! :]

The post New Video Tutorial Series: Testing in iOS appeared first on Ray Wenderlich.

watchOS 2 Tutorial Part 1: Getting Started

$
0
0
Note: This is a brand new tutorial released as part of the iOS 9 Feast. Enjoy!

This year at WWDC, Apple introduced watchOS 2, which signifies a huge change for Apple Watch developers. Now, you can make native apps that run directly on your watch.

In this watchOS 2 Tutorial, you’ll build a simple but fully functional watchOS 2 app. Specifically, you will work on a watchOS app for a fictional airline called Air Aber.

In the process, you’ll learn:

  • How to add a watchOS 2 target to an iOS app;
  • How to share data across the two targets;
  • How to add a watchOS 2 interface controller to the Storyboard, and lay out the interface objects; and
  • How to create the WKInterfaceController subclass and wire everything up.

Let’s get started! ┗(°0°)┛

Getting Started

Start by downloading the starter project for this tutorial.

Open it in Xcode and build and run. You should see a blank white screen:

There’s not much to this project as it stands; it just includes a few helper files you’ll need, and not much else. You’ll address that now!

Adding the WatchKit App

Select File\New\Target…, and in the dialog that appears choose watchOS\Application\WatchKit App and click Next:

Adding a watchOS 2 Target

In the following screen, set Product Name to Watch, make sure Language is set to Swift, and uncheck any checkboxes that are checked. Click Finish:

watchOS 2 Target Details

You’ll be asked if you want to activate the watch scheme, which you do, so make sure to choose Activate:

Activate watchOS 2 Scheme

Congratulations, you’ve just created your first watch app! It really is that easy.

You’ll notice that this action actually created two targets, not one, and two corresponding groups in the Project Navigator. This is because the code of a watch app actually runs as an extension bundled within the watch app, in much the same way Today extensions on iOS work.

If you expand the Watch and Watch Extension groups in the Project Navigator you’ll see that the storyboard resides in the Watch group, and the classes created by the target template reside in the Watch Extension group:

Project Navigator with watchOS 2 Groups

This is the pattern you’ll follow moving forward. Any code you add must reside within the Watch Extension group and be added to the Watch Extension target, whereas any assets or storyboards need to go in the Watch group.

A Little Housekeeping

Before continuing, you need to remove a couple of things added by the target template that you don’t need.

Right-click on InterfaceController.swift in the Project Navigator and choose Delete. When prompted, choose Move to Trash to make sure the file is actually removed from the project:

Delete

Next, open up Interface.storyboard, select the only interface controller that’s in there, and hit backspace to delete it. This should leave you with an empty storyboard, or as I prefer to think of it, a blank canvas.

Sharing Data and Code

The starter project includes a JSON file containing all the Air Aber flight details, and a model class that represents that data. This is exactly the kind of thing that should be shared amongst targets, since it’s highly likely the iOS app and the watch app will use the same model class and data – you do remember DRY, right?

Expand the Shared group in the Project Navigator and select Flights.json. Then, find the Target Membership section in the File Inspector, and check Watch Extension:

File-Inspector

The file should now be included in both the AirAber and Watch Extension targets.

Repeat the process for the other file in the Shared group, Flight.swift.

And with that done you can finally begin building the flight details interface!

Building the Interface

Open Watch\Interface.storyboard, and drag an Interface Controller from the Object Library onto the storyboard canvas. With the interface controller selected, open the Attributes Inspector and set Identifier to Flight and check Is Initial Controller:

Flight

You set the identifier so you can refer to the interface controller in code. Checking Is Initial Controller simply informs WatchKit that this is the interface controller you want to display when the watch app first launches.

Next, drag a Group from the Object Library onto the interface controller:

Group

Although it doesn’t look much now, this group will eventually contain the Air Aber logo, flight number, and route.

With the new group selected, head over to the Attributes Inspector and change Insets to Custom. This will reveal four extra text boxes where you can manually set the insets for the top, bottom, left, and right of the group. Change Top to 6:

Insets

This just gives the layout group a little extra padding at the top.

Next, drag an Image into the group. If your group shrank in response to changing the Top inset (thanks Xcode!), then drag the image into the Document Outline instead, making sure it’s a child of the group, rather than a sibling:

Image

Now you need an image to display. Download this logo image and drag it into your Watch\Assets.xcassets. This should create a new image set called Logo, with the actual image in the 2x slot:

Logo-Image-Set

You want to tint this image, so select the image and then in the Attributes Inspector change Render As to Template Image.

Re-open Watch\Interface.storyboard and select the image. Using the Attributes Inspector, make the following changes:

  • Set Image to Logo – if it doesn’t appear in the dropdown, you can simply type it;
  • Set Tint to #FA114F (you can type this in the Color Sliders panel);
  • Set Width to Fixed, with a value of 40;
  • Set Height to Fixed, with a value of 40.

The Attributes Inspector should now look like the following:

Image-Attributes

Don’t worry if you can’t see the logo, as it turns out that Xcode doesn’t tint template images at design time!

Next, drag another group into the existing group, making sure it appears to the right of the image, and set its Layout to Vertical using the Attributes Inspector. Also change Spacing to 0 and Width to Size to Fit Content. Then drag two labels into the new group, positioning one underneath the other:

Top-Group-Labels

Select the upper label and using the Attributes Inspector, set Text to Flight 123 and Text Color to #FA114F.

Then select the lower label and set its Text to MAN to SFO. Your interface controller should now look like the following:

Top-Group-Complete

This text is simply placeholder text that’ll be replaced when you hook the interface up to its controller class.

Next, drag another group onto the interface controller, but this time make sure its a sibling of the very first group you added. If you can’t get the group positioned at the correct place in the hierarchy then use the Document Outline instead.

Sibling

With this new group selected, set its Layout to Vertical and Spacing to 0.

Now, drag three labels into this new group:

Middle-Group-Labels

Make sure the labels are inside the group, not siblings of the group!

Select the top label and use the Attributes Inspector to change its Text to AA123 Boards.

With the middle label selected, change its Text to 15:06. Also change Text Color to #FA114F, and Font to System, with a style of Regular and a size of 54.0. Finally, change Height to Fixed, with a value of 44.

Select the bottom label and change its Text to On time and Text Color to #04DE71.

Your interface controller should now look like the following:

Middle-Group-Complete

You’ve now just one more group to add before you can create the outlets and have this interface display some real data.

Drag a new group from the Object Library into the lower group, this time making sure it’s a child rather than a sibling, and that it’s positioned at the very bottom of the containing group. Then add two labels to it. Your complete interface object hierarchy should now look like this:

Hierarchy

Using the Attributes Inspector, set Text to Gate 1A for the left label. For the right label, set Text to Seat 64A and set the Horizontal alignment to Right.

The completed interface should now look like the following:

Interface-Completed

Congratulations, you’ve finished laying out your very first watch app interface. Now it’s time to populate it with some real data and get it up and running in the simulator.

Creating the Controller

Right-click on the Watch Extension group in the Project Navigator and choose New File…. In the dialog that appears select watchOS\Source\WatchKit Class and click Next. Name the new class FlightInterfaceController, and make sure it’s subclassing WKInterfaceController and that Language is set to Swift:

File-Options

Click Next, and then Create.

When the new file opens in the code editor, delete the three empty method stubs so you’re left with just the import statements and the class definition.

Add the following outlets to the top of FlightInterfaceController:

@IBOutlet var flightLabel: WKInterfaceLabel!
@IBOutlet var routeLabel: WKInterfaceLabel!
@IBOutlet var boardingLabel: WKInterfaceLabel!
@IBOutlet var boardTimeLabel: WKInterfaceLabel!
@IBOutlet var statusLabel: WKInterfaceLabel!
@IBOutlet var gateLabel: WKInterfaceLabel!
@IBOutlet var seatLabel: WKInterfaceLabel!

Here you’re simply adding an outlet for each of the labels you added earlier. You’ll hook them up in just a moment.

Next, add the following property and property observer just below the outlets:

// 1
var flight: Flight? {
  // 2
  didSet {
    // 3
    if let flight = flight {
      // 4
      flightLabel.setText("Flight \(flight.shortNumber)")
      routeLabel.setText(flight.route)
      boardingLabel.setText("\(flight.number) Boards")
      boardTimeLabel.setText(flight.boardsAt)
      // 5
      if flight.onSchedule {
        statusLabel.setText("On Time")
      } else {
        statusLabel.setText("Delayed")
        statusLabel.setTextColor(UIColor.redColor())
      }
      gateLabel.setText("Gate \(flight.gate)")
      seatLabel.setText("Seat \(flight.seat)")
    }
  }
}

Here’s the play-by-play of what’s happening here:

  1. You declare an optional property of type Flight. This class is declared in Flight.swift, which is part of the shared code you added to the Watch Extension target earlier;
  2. You add a property observer that is triggered whenever the property is set;
  3. You make sure there’s an actual flight rather than nil in the optional property. You only want to proceed with configuring the labels when you know you have a valid instance of Flight;
  4. You configure the labels using the relevant properties of flight;
  5. If the flight is delayed then you change the text colour of the label to red.

Now you need to set flight when the controller is first shown. Add the following just below the declaration of flight:

override func awakeWithContext(context: AnyObject?) {
  super.awakeWithContext(context)
  flight = Flight.allFlights().first!
}

Later in the session you’ll change this implementation to use the context that’s passed to it, but for now you simply load all the flights from the shared JSON file and then take the first one from the array.

You’ll also learn more about awakeWithContext(_:) later in the session, but for now just know that it’s called early enough in the interface controller’s lifecycle to make it a great place to set flight.

Now there’s just one final step before you can build and run, and that’s to connect the outlets.

Connecting the Outlets

Open Watch\Interface.storyboard and select the interface controller. Using the Identity Inspector, set Class\Custom Class to FlightInterfaceController.

Next, right-click on the yellow icon at the top of the interface controller to invoke the outlets and actions popup:

Popup

Now, connect the outlets as per the list below:

  • boardingLabel: AA123 Boards
  • boardTimeLabel: 15:06
  • flightLabel: Flight 123
  • gateLabel: Gate 1A
  • routeLabel: MAN to SFO
  • seatLabel: Seat 64A
  • statusLabel: On time

Before you hit run, there’s just one more thing to do. The sample app you’re building throughout this tutorial has been designed for the 42mm Apple Watch, so you need to make sure you have the correct watch simulator set up, otherwise some things may look a little off. For a real world app you’d want to make sure your interfaces work equally well across both sizes of watch, but that’s outside the scope of this tutorial.

In Xcode, select Window\Devices to bring up the device manager, and then click the + icon in the lower left corner. In the dialog box that pops up, name the simulator iPhone 6 – 42mm, change Device Type to iPhone 6, change Paired Apple Watch to Apple Watch – 42mm (watchOS 2.0) and click Create:

New-Simulator

Close the device manager, select the Watch scheme, and choose the new simulator:

Select-Scheme

Build and run. Once the simulator has finished loading you should see the following:

Final

Note: If you receive an error message stating the installation failed, then you can either try again with Xcode, or manually install the app in the watch simulator. To do this, open the Watch app in the iOS simulator, tap on AirAber, and then flick Show App on Apple Watch to On. Once that’s done, jump back to the watch simulator, press Shift+Command+H to navigate to the home screen, and then tap the AirAber icon to launch the app.

Congratulations! You’ve now finished implementing your very first WatchKit interface, and got it up and running in the watch simulator using real data, nice work.

Where To Go From Here?

Here is the finished example project from this tutorial series so far.

In this exercise you’ve learned how to add a watch app to an existing iOS app, how to create an interface controller and lay out a pretty complex interface using nested groups, and how to tie the whole thing together using a WKInterfaceController subclass. So, where to next?

Part 2 of this tutorial series, of course! In part 2, you’ll learn all about tables and navigation in WatchKit.

You might also be interested in our book watchOS 2 by Tutorials that goes into much greater detail about making watchOS 2 apps – from beginning to advanced.

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

The post watchOS 2 Tutorial Part 1: Getting Started appeared first on Ray Wenderlich.

watchOS 2 Tutorial Part 2: Tables

$
0
0
Note: This is a brand new tutorial released as part of the iOS 9 Feast. Enjoy!

Welcome back to our watchOS 2 tutorial series!

In the first part of this series, you learned about the basics of watchOS 2 development by creating your first interface controller.

In this second part of the series, you’ll add a table to your app that displays a list of flights.

In the process, you’ll learn:

  • How to add a new interface controller, add a table to it, and build the prototype row;
  • How to create a subclass of WKInterfaceController to populate the table, configure the rows, and handle selection;
  • How to present an interface controller modally and pass it data to present.

And with that, let’s get going! ┗(°0°)┛

Note: This tutorial picks up where we left things off in the previous tutorial. You can either continue with the same project, or download it here if you don’t have it already.

Getting Started

Open Watch\Interface.storyboard, and drag another Interface Controller from the Object Library onto the storyboard canvas, to the left of the existing Flight controller.

With the new interface controller selected, open the Attributes Inspector and make the following changes:

  • Set Identifier to Schedule;
  • Set Title to Air Aber;
  • Check Is Initial Controller:
  • Check Display Activity Indicator When Loading.

You’ll notice that the title is dark grey, rather than the vibrant pink shown in the screenshot above. You’ll fix that now:

Title-Grey

Open the File Inspector and change Global Tint to #FA114F. That’s much better:

Title-Pink

Next, drag a Table from the Object Library onto the new interface controller:

Add-Table

With the Table Row Controller selected in the Document Outline:

Table-Row-Controller

Use the Attributes Inspector to set its Identifier to FlightRow. The identifier doubles-up as the row type when you’re informing the table which rows it should be instantiating, which is why it’s important that you set it.

Building the Row’s Interface

Your first task is to make two changes to the default layout group provided by the row. Select the group inside the table row from the Document Outline, and then using the Attributes Inspector set Spacing to 6 and Height to Size To Fit Content.

Table rows have a standard, fixed height by default. However, most of the time you’ll want your rows to display all the interface objects you add to them, so it’s always worthwhile changing the Height attribute in this way.

With that out of the way, drag a Separator from the Object Library into the table row. You won’t be using it to actually separate anything, but rather to just add a little visual flair to your table row. With the separator selected, make the following changes using the Attributes Inspector:

  • Set Color to #FA114F;
  • Set Vertical alignment to Center;
  • Set Height to Relative to Container;
  • Set Adjustment to –4.

The inspector should now look like the following:

Separator

Now it’s time to flesh out the row!

Drag a Group from the Object Library onto the table row, after (to the right of) the separator. With the group still selected, change the following attributes in the Attributes Inspector:

  • Set Layout to Vertical;
  • Set Spacing to 0;
  • Set Width to Size To Fit Content.

You’ve probably noticed that you’re often manipulating the Spacing attribute; this simply tightens up the space between each of the interface objects in the group and makes things look a little sharper on the small screen.

Drag another Group into the group you just added, and make the following changes:

  • Set Spacing to 4;
  • Set Height to Fixed, with a value of 32.

To this new group, add a Label, an Image, and then another Label. These two labels will display the origin and destination of each flight.

Now you need something to put in that image. Download this image and add it to Watch\Assets.xcassets. This should create a new image set called Plane, with the actual image in the 2x slot:

Plane-Image-Set

You want to tint this image, so select the image and then in the Attributes Inspector change Render As to Template Image.

Re-open Watch\Interface.storyboard and select the image. Using the Attributes Inspector, make the following changes:

  • Set Image to Plane;
  • Set Tint to #FA114F;
  • Set Vertical alignment to Center;
  • Set Width to Fixed, with a value of 24;
  • Set Height to Fixed, with a value of 20.

Select the left label and set its Text to MAN. Also change its Font to System, with a style of Semibold and a size of 20.0. Finally set its Vertical alignment to Center.

Make the same changes to the right label, except using the text SFO. Your table row should now look like the following:

Table-Row-Upper-Group

And the interface object hierarchy should resemble the following:

Table-Row-Hierarchy-1

You’re almost done with the table row’s interface; you just need to add the flight number and status.

Drag another Group from the Object Library onto the table row, making sure it’s a sibling of the group that contains the origin and destination labels:

Table-Row-Lower-Group

As you continue to build this interface your seeing further examples of how you can use nested groups with mixed layouts to create complex layouts. Who needs Auto Layout?! ;]

Drag two labels into this new group. Once again use the Attributes Inspector to make the following changes to the left most label:

  • Set Text to AA123;
  • Set Text Color to Light Gray Color;
  • Set Font to Caption 2;
  • Set Vertical alignment to Bottom.

Now, make these changes to the right label:

  • Set Text to On time;
  • Set Text Color to #04DE71;
  • Set Font to Caption 2;
  • Set Horizontal alignment to Right;
  • Set Vertical alignment to Bottom.

And with those final changes, the completed table row should now look like this:

Table-Row-Complete

Now the table is set up in Interface Builder it’s time to populate it with some data.

Populating the Table

The first thing you need to do is create a subclass of WKInterfaceController that will provide the data for the table.

Right-click on the Watch Extension group in the Project Navigator and choose New File…. In the dialog that appears select watchOS\Source\WatchKit Class and click Next. Name the new class ScheduleInterfaceController, and make sure it’s subclassing WKInterfaceController and that Language is set to Swift:

File-Options

Click Next, and then Create.

When the new file opens in the code editor, delete the three empty method stubs so you’re left with just the import statements and the class definition.

Re-open Watch\Interface.storyboard and select the new interface controller. In the Identity Inspector, change Custom Class\Class to ScheduleInterfaceController:

Custom-Class

With the interface controller still selected, open the Assistant Editor and make sure it’s displaying ScheduleInterfaceController. Then, Control+Drag from Table in the Document Outline to inside the class declaration of ScheduleInterfaceController to create an outlet:

Table-Outlet

Name the outlet flightsTable, make sure the type is set to WKInterfaceTable and click Connect.

Now you’ve set the custom class and created an outlet to the table, it’s finally time to populate the thing!

Close the Assistant Editor, open ScheduleInterfaceController.swift, and add the following, just below the outlet:

var flights = Flight.allFlights()

Here you’re simply adding a property that holds all the flight information as an array of Flight instances.

Next, add the following implementation of awakeWithContext(_:):

override func awakeWithContext(context: AnyObject?) {
  super.awakeWithContext(context)
  flightsTable.setNumberOfRows(flights.count, withRowType: "FlightRow")
}

Here you’re informing the table to create an instance of the row you just built in Interface Builder for each flight in flights. The number of rows is equal to the size of the array, and the row type is the identifier you set in the storyboard.

Build and run. You’ll see a table populated with several rows:

Identical-Rows

However, you’ve likely noticed that they’re all displaying the placeholder text you set in Interface Builder. You’ll fix this now by adding a row controller that you can use to configure the labels for each row individually.

Adding a Row Controller

Right-click on the Watch Extension group in the Project Navigator and choose New File…. In the dialog that appears select watchOS\Source\WatchKit Class and click Next. Name the new class FlightRowController, and make sure it’s subclassing NSObject and that Language is set to Swift:

File-Options-Row-Controller

Click Next, and then Create.

When the new file opens in the code editor add the following to the top of the class:

@IBOutlet var separator: WKInterfaceSeparator!
@IBOutlet var originLabel: WKInterfaceLabel!
@IBOutlet var destinationLabel: WKInterfaceLabel!
@IBOutlet var flightNumberLabel: WKInterfaceLabel!
@IBOutlet var statusLabel: WKInterfaceLabel!
@IBOutlet var planeImage: WKInterfaceImage!

Here you’re simply adding an outlet for each of the labels you added to the table row. You’ll connect them shortly.

Next, add the following property and property observer just below the outlets:

// 1
var flight: Flight? {
  // 2
  didSet {
    // 3
    if let flight = flight {
      // 4
      originLabel.setText(flight.origin)
      destinationLabel.setText(flight.destination)
      flightNumberLabel.setText(flight.number)
      // 5
      if flight.onSchedule {
        statusLabel.setText("On Time")
      } else {
        statusLabel.setText("Delayed")
        statusLabel.setTextColor(UIColor.redColor())
      }
    }
  }
}

Here’s the play-by-play of what’s happening here:

  1. You declare an optional property of type Flight. Remember, this class is declared in Flight.swift, which is part of the shared code you added to the Watch Extension in tutorial #1;
  2. You add a property observer that is triggered whenever the property is set;
  3. You exit early if flight is nil. Since it’s an optional and you only want to proceed with configuring the labels when you know you have a valid instance of Flight;
  4. You configure the labels using the relevant properties of flight;
  5. If the flight is delayed then you change the text colour of the label to red and update the text accordingly.

With the the row controller set up, you now need to update the table row to use it.

Open Watch\Interface.storyboard and select FlightRow in the Document Outline. Using the Identity Inspector, set Custom Class\Class to FlightRowController.

Next, right-click on FlightRow in the Document Outline to invoke the outlets and actions popup:

Outlets-Popup

First connect planeImage to the image in the table row, and separator to the separator. Then connect the remaining outlets as per the list below:

  • destinationLabel: SFO
  • flightNumberLabel: AA123
  • originLabel: MAN
  • statusLabel: On time

The final step is to update ScheduleInterfaceController so it passes an instance of Flight to each row controller in the table.

Open ScheduleInterfaceController.swift and add the following to the bottom of awakeWithContext(_:):

for index in 0..<flightsTable.numberOfRows {
  if let controller = flightsTable.rowControllerAtIndex(index) as? FlightRowController {
    controller.flight = flights[index]
  }
}

Here you’re iterating over each row in the table using a for loop, and asking the table for the row controller at the given index. If you successfully cast the controller you’re handed back to an instance of FlightRowController, you set flight to the corresponding flight in flights. This in-turn triggers the didSet observer and configures all the labels in the table row.

It’s time to see the fruits of your labour. Build and run. You’ll see that your table rows are now populated with the relevant flight details:

Populated-Rows

The final part of this tutorial is to present the flight details interface you created in tutorial #1 when a user taps on a table row, and pass it the corresponding flight as the context.

Responding to Row Selection

The first thing you need to do is to override the method declared WKInterfaceController that’s responsible for handling table row selection.

Add the following to ScheduleInterfaceController:

override func table(table: WKInterfaceTable, didSelectRowAtIndex rowIndex: Int) {
  let flight = flights[rowIndex]
  presentControllerWithName("Flight", context: flight)
}

Here you retrieve the appropriate flight from flights using the row index that’s passed to this method. You then present the flight details interface, passing flight as the context. Remember that the name you pass to presentControllerWithName(_:context:) is the identifier you set in the storyboard.

Now you need to update FlightInterfaceController so it uses the context to configure its interface.

Open FlightInterfaceController.swift and find awakeWithContext(_:). Replace this statement:

flight = Flight.allFlights().first!

With the following:

if let flight = context as? Flight { self.flight = flight }

Here you try to cast context to an instance of Flight. If it succeeds you then use it to set self.flight, which will in turn trigger the property observer and configure the interface.

For the final time in the tutorial, build and run. If you tap on a table row, you’ll now see the flight details interface is presented modally, displaying the details of the selected flight:

Final

Congratulations! You’ve now finished implementing your very first table, and have populated it using real data; nice work!

Where to Go From Here?

Here is the finished example project from this tutorial series so far.

In this tutorial you’ve learnt how to add a table to an interface controller, build the table row interface, create a row controller, handle table row selection, present another interface controller, and even pass contexts. Phew! That’s a lot to cram into 20 minutes or so.

So, where to next? Part 3 of this tutorial, of course! There, you’ll learn all about animation in watchOS.

You might also be interested in our book watchOS 2 by Tutorials that goes into much greater detail about making watchOS 2 apps – from beginning to advanced.

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

The post watchOS 2 Tutorial Part 2: Tables appeared first on Ray Wenderlich.

watchOS 2 Tutorial Part 3: Animation

$
0
0
Note: This is a brand new tutorial released as part of the iOS 9 Feast. Enjoy!

Welcome back to our watchOS 2 tutorial series!

In the first part of this series, you learned about the basics of watchOS 2 development by creating your first interface controller.

In this second part of the series, you learned how to add tables to your app.

In this third part of the series, you’ll learn how to use watchOS 2 animation by adding a new check-in interface into your app.

In the process, you’ll learn:

  • How to create image-based animations;
  • How to use the new watchOS 2 animation API.

And with that, let’s get cracking! ┗(°0°)┛

Note: This tutorial picks up where we left things off in the previous tutorial. You can either continue with the same project, or download it here if you don’t have it already.

Getting Started

Open Watch\Interface.storyboard and drag an Interface Controller from the Object Library onto the storyboard canvas. With the interface controller selected, open the Attributes Inspector and set Identifier to CheckIn. You do this so you can present the interface controller from within ScheduleInterfaceController.

Next, drag a Group from onto the new interface controller from the Object Library. Use the Attributes Inspector to make the following changes:

  • Set Layout to Vertical;
  • Set Mode to Center;
  • Set the Horizontal alignment to Center;
  • Set Height to Relative to Container.

Your interface controller should now look like this:

Background-Group

Drag another Group into the existing group, and make the following changes using the Attributes Inspector:

  • Set Spacing to 4;
  • Set the Horizontal alignment to Center;
  • Set Width to Size To Fit Content;
  • Set Height to Fixed, with a value of 30.

Add a Label, an Image, and then another Label to this new layout group. The two labels will display the origin and destination of each flight, respectively.

Select the image, either in the storyboard or in the Document Outline. Using the Attributes Inspector, make the following changes:

  • Set Image to Plane;
  • Set Tint to #FA114F;
  • Set Vertical alignment to Center;
  • Set Width to Fixed, with a value of 24;
  • Set Height to Fixed, with a value of 20.

As the image is black it might be difficult to see against the black background of the interface controller. You’ll just have to trust me that it’s there.

Select the left label and set its Text to MAN. Also change its Font to System, with a style of Semibold and a size of 20.0. Finally set its Vertical alignment to Center.

Make the same changes to the right label, except using the text SFO. Your interface controller should now look like the following:

Upper-Group-Complete

Now it’s time to add that huge check-in button!

Adding the Check-In Button

Drag a Button from the Object Library onto the interface controller, making sure it’s positioned as a sibling of the group containing the origin and destination labels:

Button-Position

Buttons in WatchKit are incredibly flexible; you can use them with their stock appearance – how the one you just added looks – or you can turn them into a layout group and add other interface objects to customize their appearance. That’s exactly what you’re going to do here.

Select the button and use the Attributes Inspector to make the following changes:

  • Set Content to Group;
  • Set the Horizontal alignment to Center;
  • Set the Vertical alignment to Center.

Your interface controller should now look like this:

Button-Group

You may have noticed that when you changed the Content attribute of the button, a new group appeared in the Document Outline:

Button-Embedded-Group

This is what you’re going to use as the background of your custom check-in button. Select this group and make the following changes using the Attributes Inspector:

  • Set Color to #FA114F;
  • Set Radius to 39;
  • Set Width to Fixed, with a value of 78;
  • Set Height to Fixed, with a value of 78.

The interface controller should now look like this:

Round-Button

Your check-in button is really starting to take shape. The only thing missing is the label, so you’ll add that now.

Drag a Label from the Object Library into the group belonging to the button, and then select it. Once again, make the following changes using the Attributes Inspector:

  • Set Text to Check In;
  • Set Font to System, with a style of Semibold and a size of 16.0;
  • Set the Horizontal alignment to Center;
  • Set the Vertical alignment to Center.

Your finished check-in interface controller should now look like this:

Check-In-Interface-Complete

With the interface complete, it’s now time to create a subclass of WKInterfaceController to manage this controller, and to update ScheduleInterfaceController to show it.

Creating the Controller

Right-click on the Watch Extension group in the Project Navigator and choose New File…. In the dialog that appears select watchOS\Source\WatchKit Class and click Next. Name the new class CheckInInterfaceController, and make sure it’s subclassing WKInterfaceController and that Language is set to Swift:

File-Options

Click Next, and then Create.

When the new file opens in the code editor, delete the three empty method stubs so you’re left with just the import statements and the class definition.

Add the following at the top of the class:

@IBOutlet var backgroundGroup: WKInterfaceGroup!
@IBOutlet var originLabel: WKInterfaceLabel!
@IBOutlet var destinationLabel: WKInterfaceLabel!

Here you’re simply adding outlets for the outer-most group and the two labels of the interface you just created. You’ll hook everything up momentarily.

Next, add the following just below the outlets:

var flight: Flight? {
  didSet {
    if let flight = flight {
      originLabel.setText(flight.origin)
      destinationLabel.setText(flight.destination)
    }
  }
}

You know the score by now! Here you’ve added an optional property of type Flight, which includes a property observer. When the observer is fired, you try to unwrap flight, and if that succeeds you use flight to configure the two labels. This is all familiar territory now, right?

Now you just need to set flight when the controller is presented. Add the following to CheckInInterfaceController:

override func awakeWithContext(context: AnyObject?) {
  super.awakeWithContext(context)
  if let flight = context as? Flight { self.flight = flight }
}

Again, this should be super familiar by now. You try to unwrap and cast context to an instance of Flight, and if that succeeds you use it to set self.flight, which in-turn triggers the property observer and configures the interface.

Finally, add the following action just below awakeWithContext(_:):

@IBAction func checkInButtonTapped() {
  // 1
  let duration = 0.35
  let delay = dispatch_time(DISPATCH_TIME_NOW, Int64((duration + 0.15) * Double(NSEC_PER_SEC)))
  // 2
  backgroundGroup.setBackgroundImageNamed("Progress")
  // 3
  backgroundGroup.startAnimatingWithImagesInRange(NSRange(location: 0, length: 10), duration: duration, repeatCount: 1)
  // 4
  dispatch_after(delay, dispatch_get_main_queue()) { () -> Void in
    // 5
    self.flight?.checkedIn = true
    self.dismissController()
  }
}

Here’s the play-by-play of what’s happening here:

  1. You create two constants: one for the duration of the animation, and one for the delay after which the controller will be dismissed. Instead of being a Double, delay is an instance of dispatch_time_t since you’ll be using it with Grand Central Dispatch.
  2. You load a sequence of images named Progress and set them as the background image of backgroundGroup. Remember that layout groups conform to WKImageAnimatable, which allows you to use them to play back animated image sequences.
  3. You begin playback of the image sequence. The range you supply covers the entire sequence, and a repeat count of 1 means the animation will play just once.
  4. You use Grand Central Dispatch to execute the closure after the given delay.
  5. In the closure, you mark flight as checked-in, and then dismiss the controller.

Now you just need to add the images to the project, and hook up the outlets and single action.

Download this zip file, unzip the file, and drag the folder into your Watch\Assets.xcassets.

Make sure you drag the folder and not it’s contents. This should create a new group in the asset catalog called Progress, containing several image sets:

Progress-Image-Group

With the images sorted, it’s time to sort the outlets and button action.

Open Watch\Interface.storyboard and select your new interface controller. In the Identity Inspector, change Custom Class\Class to CheckInInterfaceController:

Custom-Class

Right-click on CheckIn in the Document Outline to invoke the outlets and actions popup. Then, connect backgroundGroup to outer-most group in the interface controller:

Background-Group-Outlet

Connect destinationLabel to the label containing SFO, and connect originLabel to the label containing MAN.

Next, connect checkInButtonTapped to the big, round, pink button:

Connect-Action

The final change you need to make before you can build and run is to actually present this interface controller.

Presenting the Controller

Open ScheduleInterfaceController.swift, find table(_:didSelectRowAtIndex:), and replace its contents with the following:

let flight = flights[rowIndex]
let controllers = ["Flight", "CheckIn"]
presentControllerWithNames(controllers, contexts:[flight, flight])

Here you retrieve the appropriate flight from flights using rowIndex, create an array containing the identifiers of the two interface controllers you want to present, and then present them, passing flight as the context to both.

Build and run. Tap a flight and you’ll see a pair of interface controllers are presented. Swipe left to reveal the check-in controller, and then tap the button to trigger the animation and check-in:

Image-Animation

This looks great as-is, but it’d be even better if checked-in flights were highlighted on the schedule interface controller as well. You’ll address that in the next and final section.

Highlighting the Flight

Open FlightRowController.swift and add the following method to it:

func updateForCheckIn() {
  let color = UIColor(red: 90/255, green: 200/255, blue: 250/255, alpha: 1)
  planeImage.setTintColor(color)
  separator.setColor(color)
}

Here you’re creating an instance of UIColor, and then using it to set the tint color and color of planeImage and separator respectively. This method will be called from within an animation closure, so the color change will be nicely animated.

Next, open ScheduleInterfaceController.swift and add the following property to the top of the class:

var selectedIndex = 0

You’ll use this to remember which table row was selected when presenting the two interface controllers. Now you just need to set it when a table row is selected. Add the following just above the call to presentControllerWithNames(_:contexts) in table(_:didSelectRowAtIndex:):

selectedIndex = rowIndex

This sets selectedIndex to the index of the selected table row.

Finally, add the following to ScheduleInterfaceController, just below awakeWithContext(_:):

override func didAppear() {
  super.didAppear()
  // 1
  if flights[selectedIndex].checkedIn, let controller = flightsTable.rowControllerAtIndex(selectedIndex) as? FlightRowController {
    // 2
    animateWithDuration(0.35, animations: { () -> Void in
      // 3
      controller.updateForCheckIn()
    })
  }
}

Here’s what’s happening in the code above:

  1. You check to see if the selected flight is checked-in, and if so you try and cast the row controller at the corresponding index in the table to an instance of FlightRowController.
  2. If that succeeds, you use the new animation API on WKInterfaceController to execute the given closure, over a duration of 0.35 seconds.
  3. In the closure, you call the method you just added to FlightRowController, which changes the color of the plane image and separator of that table row, and provides the user with some visual feedback that they’re now checked-in.

Build and run. Follow the same steps as before to check in for a flight, and you’ll see that when you’re returned to the schedule interface controller, the colors of the plane image and separator on the corresponding table row crossfade to a new color:

Crossfade-Animation

Congratulations! You’ve now finished implementing your very first set of WatchKit animations.

Where to Go From Here?

Here is the finished example project from this tutorial series so far.

In this tutorial you’ve learnt how to create two different kinds of WatchKit animation. The first, using an animated sequence of images, and the second, using the new animation API on WKInterfaceController. You’re now suitably primed to add plenty of visual flair to your own watchOS 2 apps!

So, where to next? The fourth and final part of this session, of course! Where you’ll learn all about Watch Connectivity, a brand new framework in watchOS 2 and iOS 9.

You might also be interested in our book watchOS 2 by Tutorials that goes into much greater detail about making watchOS 2 apps – from beginning to advanced.

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

The post watchOS 2 Tutorial Part 3: Animation appeared first on Ray Wenderlich.


watchOS 2 Tutorial Part 4: Watch Connectivity

$
0
0
Note: This is a brand new tutorial released as part of the iOS 9 Feast. Enjoy!

Welcome back to our watchOS 2 tutorial series!

In the first part of this series, you learned about the basics of watchOS 2 development by creating your first interface controller.

In this second part of the series, you learned how to add tables to your app.

In this third part of the series, you learned how to use watchOS 2 animation.

In this fourth and final part of the series, you’ll learn how to use Watch Connectivity to fire off a request to your iPhone app to generate QR codes using Core Image. Thanks to Apple, this is much simpler than it sounds!

And with that, it’s time to crack on! ┗(°0°)┛

Note: This tutorial picks up where we left things off in the previous tutorial. You can either continue with the same project, or download it here if you don’t have it already.

Getting Started

Open Watch\Interface.storyboard and drag an Interface Controller from the Object Library onto the storyboard canvas. With the interface controller selected, open the Attributes Inspector and make the following changes:

  • Set Identifier to BoardingPass;
  • Set Insets to Custom;
  • Set the Top inset to 6.

As this interface is quite similar to the check-in interface you’re going to cheat a little bit, as building interfaces can get quite repetitive.

Expand CheckIn Scene in the Document Outline, select the group that contains the origin and destination labels, and select Edit\Copy:

Copy-From-Check-In

Then click anywhere in the new interface controller in the storyboard and select Edit\Paste. This only seems to work when you paste directly into the controller itself, rather than into the Document Outline, but I’m afraid I can’t tell you why.

Moving on, you’re new interface controller should now look like this:

Upper-Group

Next, drag an Image from the Object Library onto the new controller, making sure it’s positioned as a sibling of the group you just pasted, rather than a child:

Image-Sibling

This image is dual-purpose; initially it’ll display an animated image sequence to indicate to the user that something’s happening, and then when the watch receives the boarding pass from the phone, the image will display it.

Download this zip file, unzip the file, and drag the folder into your Watch\Assets.xcassets.

Make sure you drag the folder and not it’s contents. This should create a new group in the asset catalog called Activity, containing several image sets:

Activity-Image-Group

This is the image sequence that’ll act as the indeterminate progress indicator when you request the boarding pass from the paired phone.

Re-open Watch\Interface.storyboard and select the image. Using your ol’ friend the Attributes Inspector, make the following changes:

  • Set Image to Activity. The autocomplete might suggest something like “Activity1” so make sure you enter just Activity;
  • Set Animate to Yes;
  • Set Duration to 1;
  • Check Animate on Load;
  • Set the Horizontal alignment to Center;
  • Set the Vertical alignment to Center;
  • Set Width to Fixed, with a value of 66;
  • Set Height to Fixed, with a value of 66.

After making the changes, your Attributes Inspector should look like this:

Image-Attributes

The interface controller should look like the following:

Interface-Completed

Don’t worry about the image preview being a big blurry question mark; Interface Builder doesn’t preview animated images at this time, and since there isn’t technically an image named Activity – remember, all the images are suffixed with a number – Interface Builder is quite rightly stating it can’t load the image. This is all resolved at runtime though, trust me.

That’s it for the boarding pass interface. Now to create a WKInterfaceController subclass that does the heavy-lifting.

Creating the Controller

Right-click on the Watch Extension group in the Project Navigator and choose New File…. In the dialog that appears select watchOS\Source\WatchKit Class and click Next. Name the new class BoardingPassInterfaceController, and make sure it’s subclassing WKInterfaceController and that Language is set to Swift:

File-Options

Click Next, and then Create.

When the new file opens in the code editor, delete the three empty method stubs so you’re left with just the import statements and the class definition.

Then, add the following outlets at the top of the class:

@IBOutlet var originLabel: WKInterfaceLabel!
@IBOutlet var destinationLabel: WKInterfaceLabel!
@IBOutlet var boardingPassImage: WKInterfaceImage!

Here you’re simply adding outlets for the image and the two labels you just created. You’ll connect these up is just a moment.

Now, add the following just below the outlets:

var flight: Flight? {
  didSet {
    if let flight = flight {
      originLabel.setText(flight.origin)
      destinationLabel.setText(flight.destination)
    }
  }
}

It’s our ol’ friend flight and it’s property observer! I bet you were wondering if it was going to make an appearance this time around. You know what’s going on by now, but just to recap, you’ve added an optional property of type Flight, which includes a property observer. When the observer is fired, you try to unwrap flight, and if that succeeds you use flight to configure the two labels.

Now you just need to set flight when the controller is first presented. Add the following to BoardingPassInterfaceController:

override func awakeWithContext(context: AnyObject?) {
  super.awakeWithContext(context)
  if let flight = context as? Flight { self.flight = flight }
}

Another old friend; I guess you could call this a reunion of sorts! But just in case you’ve forgotten what this does, you try to unwrap and cast context to an instance of Flight, and if that succeeds you use it to set self.flight, which in-turn triggers the property observer and configures the interface.

That’s it for the boilerplate code in this exercise, I promise. :]

Now, open up Watch\Interface.storyboard and select the boarding pass interface controller. In the Identity Inspector, change Custom Class\Class to BoardingPassInterfaceController:

Custom-Class

Then, right-click on BoardingPass in the Document Outline to invoke the outlets and actions popup. Connect boardingPassImage to the image:

Image-Outlet

Finally, connect destinationLabel to the label containing SFO, and connect originLabel to the label containing MAN.

With that done, you now need to update ScheduleInterfaceController so it presents the boarding pass interface controller once a user has checked-in.

Presenting the Boarding Pass Interface

Open ScheduleInterfaceController.swift and find table(_:didSelectRowAtIndex:). Replace this statement:

let controllers = ["Flight", "CheckIn"]

With this one:

let controllers = flight.checkedIn ? ["Flight", "BoardingPass"] : ["Flight", "CheckIn"]

Here you’re simply checking whether or not the user has checked-in for the selected flight, and if so you present the flight details and boarding pass interface controllers. If they haven’t, you present the flight details and check-in interface controllers instead.

Build and run. Tap the first flight, swipe left, and tap Check In. Tap the same flight again, swipe left, and you’ll now see the boarding pass interface controller instead, displaying the indeterminate progress indicator:

Progress-Indicator

It’s now time to dig into the new Watch Connectivity framework and request the actual boarding pass.

Requesting the Boarding Pass

Open BoardingPassInterfaceController.swift and import the Watch Connectivity framework:

import WatchConnectivity

Next, add the following property just below where you’ve declared flight:

var session: WCSession? {
  didSet {
    if let session = session {
      session.delegate = self
      session.activateSession()
    }
  }
}

Here you’ve added a new optional property of the type WCSession. All communication between the two devices, your watch and phone, is handled by WCSession; you don’t instantiate an instance of this class yourself, rather you use a singleton provided by the framework. You’ve also added a property observer that, when triggered, attempts to unwrap session. If that succeeds then it sets the session’s delegate before activating it.

Even though you won’t be implementing any of the delegate methods in this class, you’re still required to set the delegate prior to activating the session, otherwise things get a bit unpredictable.

Xcode will now likely be complaining that BoardingPassInterfaceController doesn’t conform to WCSessionDelegate, so add the following empty extension at the very bottom of BoardingPassInterfaceController.swift, outside of the class:

extension BoardingPassInterfaceController: WCSessionDelegate {
 
}

Next, add the following helper method to BoardingPassInterfaceController:

private func showBoardingPass() {
  boardingPassImage.stopAnimating()
  boardingPassImage.setWidth(120)
  boardingPassImage.setHeight(120)
  boardingPassImage.setImage(flight?.boardingPass)
}

This will be called from two places – from within the property observer of flight if the flight already has a boarding pass, and from within the reply handler of the message you fire off to the iPhone. The implementation is pretty straightforward – you stop the image animating, increase the size of the image, and then set the image being displayed to the boarding pass.

You’ll update the property observer first. Add the following to the bottom of if statement in the property observer for flight:

if let _ = flight.boardingPass {
  showBoardingPass()
}

Here you call showBoardingPass() only if flight already has a boarding pass.

The final piece of the puzzle is to actually send the request off to the iPhone. Add the following just below awakeWithContext(_:):

override func didAppear() {
  super.didAppear()
  // 1
  if let flight = flight where flight.boardingPass == nil && WCSession.isSupported() {
    // 2
    session = WCSession.defaultSession()
    // 3
    session!.sendMessage(["reference": flight.reference], replyHandler: { (response) -> Void in
      // 4
      if let boardingPassData = response["boardingPassData"] as? NSData, boardingPass = UIImage(data: boardingPassData) {
        // 5
        flight.boardingPass = boardingPass
        dispatch_async(dispatch_get_main_queue(), { () -> Void in
          self.showBoardingPass()
        })
      }
    }, errorHandler: { (error) -> Void in
      // 6
      print(error)
    })
  }
}

Here’s the play-by-play of what’s happening in the code above:

  1. If you have a valid flight that has no boarding pass, and Watch Connectivity is supported, then you move onto sending the message. You should always check to see if Watch Connectivity is supported before attempting any communication with the paired phone.
  2. You set session to the default session singleton. This in-turn triggers the property observer, setting the session’s delegate before activating it.
  3. You fire off the message to the companion iPhone app. You include a dictionary containing the flight reference that will be forwarded to the iPhone app, and provide both reply and error handlers.
  4. The reply handler receives a dictionary, and is called by the iPhone app. You first try to extract the image data of the boarding pass from the dictionary, before attempting to create an instance of UIImage with it.
  5. If that succeeds, you set the image as the flight’s boarding pass, and then jump over to the main queue where you call showBoardingPass() to show it to the user. The reply and error handlers are called on a background queue, so if you need to update the interface, as you are here, then always make sure to jump to the main queue before doing so.
  6. If the message sending fails then you simply print the error to the console.

That’s the watch app side of the conversation catered for. Now you need to update the iPhone app.

Responding to Requests

Open AppDelegate.swift, which can be found in the AirAber group in the Project Navigator.

First, import the Watch Connectivity framework:

import WatchConnectivity

Then, add the following property just below window:

var session: WCSession? {
  didSet {
    if let session = session {
      session.delegate = self
      session.activateSession()
    }
  }
}

This behaves exactly the same as its namesake in BoardingPassInterfaceController. It’s simply an optional property of the type WCSession, which includes a property observer that, when triggered, attempts to unwrap session. If that succeeds then it sets the session’s delegate, before activating it.

Next, add the following extension outside of the class in AppDelegate.swift:

extension AppDelegate: WCSessionDelegate {
 
  func session(session: WCSession, didReceiveMessage message: [String : AnyObject], replyHandler: ([String : AnyObject]) -> Void) {
    if let reference = message["reference"] as? String, boardingPass = QRCode(reference) {
      replyHandler(["boardingPassData": boardingPass.PNGData])
    }
  }
 
}

Here you implement the WCSessionDelegate method responsible for receiving realtime messages. In it, you extract the flight reference from the dictionary you passed above, and then use that to generate a QR code with the amazing QRCode library from Alexander Schuch. If that’s successful then you call the reply handler, passing the image data back to the watch app.

Finally, you need to set session. Add the following to application(_:didFinishLaunchingWithOptions:), just above the return statement:

if WCSession.isSupported() {
  session = WCSession.defaultSession()
}

Here you make sure Watch Connectivity is supported, and if it is you set session to the default session singleton provided by the framework.

And with that you should now be able to have a two-way conversation with the iPhone app.

Build and run. Follow the steps above to check-in and then view the boarding pass. This time around the boarding pass should appear after a short while:

Boarding-Pass

Note: If the boarding pass doesn’t appear at the first time of asking, try a second time. This seems to happen intermittently, and appears to be an issue with the latest beta of Xcode 7, as it worked every time without fail in the earlier betas.

Congratulations! You’ve now finished adding support for requesting boarding passes from the iPhone app using Watch Connectivity; nice work.

Where to Go From Here?

Here is the finished example project from this tutorial series.

In this tutorial you’ve learned how to send realtime messages between the watch app and companion iPhone app, and how to use them to transfer image data between the two devices.

But Watch Connectivity doesn’t stop there, oh no! Remember, you can also use the framework to update the application context, as well as send and receive background messages and files, which are delivered even when the receiving app isn’t running.

If you enjoyed this series and would like to learn more about developing for watchOS 2, check out our book watchOS 2 by Tutorials that teaches you everything you need to know to make great watchOS 2 apps.

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

The post watchOS 2 Tutorial Part 4: Watch Connectivity appeared first on Ray Wenderlich.

Swift Apprentice Now Available!

$
0
0

Swift Apprentice Now Available!

Note from Ray: Happy Wednesday – it’s book release day during the iOS 9 Feast!

Today we are happy to release our brand new book on beginning programming with Swift: the Swift Apprentice.

The Swift Apprentice is for people who want to learn Swift 2 programming – whether you are a complete beginner to programming, or a developer with experience in another language.

In this book, you’ll start with the basics like data types, functions, and collection types, and move all the way to advanced topics like error handling, functional programming, and protocol-oriented programming.

Everything you’ll learn is platform-neutral; you’ll have a firm understanding of Swift 2 by the end of this book, and you’ll be ready to move on to whichever app platform you’re interested in.

Keep reading to find out what’s inside, and how to get your copy!

What’s Inside

The Swift Apprentice is 23 chapters and 310 pages. Here’s a brief overview of the four sections in the book:

Section I: Swift Basics

The first section of the book starts at the very beginning of the computing environment: first, how computers work, and then, how Swift’s playgrounds feature works. With those logistics out of the way, you’ll take a tour of the fundamentals of the Swift language and learn the basics of managing data, structuring your code and performing simple operations and calculations.

Section II: Collection Types

Stored data is a core component of any app, whether it’s a list of friends in your social networking app or a set of unlockable characters in your hit game. In this section, you’ll learn how to store collections of data in Swift.

Section III: Building Your Own Types

Swift comes with basic building blocks, but its real power is in the custom things you can build to model parts of your app. Swift has no idea about playable characters and monsters and power-ups, for example—these are things you need to build yourself! You’ll learn how to do that in this section.

Section IV: Advanced Topics

The final section of the book covers a few advanced topics in Swift. You’ll learn about specific things, such as how to handle problems that come up as your code runs, as well as about more general things, like generics, which help you understand some of Swift’s behind-the-scenes mechanisms.

After reading this book and completing your Swift apprenticeship by working through the included exercises and challenge, you’ll be ready to take on app development on the platform of your choice!

Where To Go From Here?

Here’s how you can get your copy:

  • If you are a Swift by Tutorials Customer: We are offering this book at 50% off this new book to thank you for your support – check your email for a coupon code. If you don’t see it, check your spam or contact us.
  • If you preordered the Swift Apprentice: You can download the book immediately on your My Loot page.
  • If you don’t have the book yet: What are you waiting for – grab your copy now! :]

With the advent of Swift 2 and growing popularity of the language in production apps, if you haven’t started learning Swift 2 yet, now’s a great time.

Prepare yourself for your own private tour through programming in Swift 2. Janie, Alexis, Matt, Eli, Erik, Ben and I hope you enjoy the book!

The post Swift Apprentice Now Available! appeared first on Ray Wenderlich.

New Video Tutorial Series: Auto Layout

$
0
0

As part of this year’s iOS 9 Feast, we are releasing a new video tutorial series every Thursday.

This week, we are happy to release a Swift 2 and iOS 9 update to our popular Introduction to Auto Layout series!

Auto Layout video tutorial

This is an exciting series for us, because it is the first video tutorial series by Jerry Beers, one of our new video team members. Jerry is a co-founder of Five Pack Creative, a mobile development company that has worked on projects for American Airlines, Match.com, Tapity, and more.

In this update, Jerry has updated the series to Swift 2 and iOS 9. He also has updated the series to cover new material in iOS 9, such as UILayoutGuide, new methods and properties on UIView, NSLayoutAnchor, and more.

All 12 parts of the series are available today. You can check them out here:

If you haven’t learned Auto Layout yet, now there’s no excuse – we have a fully updated video tutorial series ready for you! :]

So what are you waiting for – check out the videos and learn Auto Layout! And be sure to come back next Thursday for one final new video tutorial series during the iOS 9 Feast.

The post New Video Tutorial Series: Auto Layout appeared first on Ray Wenderlich.

Swift Tutorial: Variables and Constants

$
0
0
Note from Ray: This is an abridged version of a chapter from the Swift Apprentice, to give you a sneak peek of what’s inside the book, released as part of the iOS 9 Feast. We hope you enjoy!

A Swift 2 tutorial for the iOS 9 Feast!

At its simplest, computer programming is all about manipulating data.

Everything you see on your screen can be reduced to numbers that you send to the CPU. Sometimes you yourself represent and work with this data as various types of numbers, but other times the data comes in more complex forms such as text, images and collections.

In this tutorial, you’ll discover constants, variables, types and tuples, and learn how to declare them, name them and change them. You’ll also learn about type inference, one of Swift’s most important features and one that will make your coding life a lot easier.

Naming data

In your Swift code, you can give each piece of data a name you can use to refer to it later. The name carries with it an associated type that denotes what sort of data the name refers to: text, numbers, a date, etc.

Constants

Take a look at your first bit of Swift:

let number: Int = 10

This declares a constant called number which is of type Int. Then it sets the value of the constant to the number 10.

The type Int can store integers—that is, whole numbers. It would be rather limiting be able to store only whole numbers, so there’s also a way to store decimals. For example:

let pi: Double = 3.14159

This is similar to the Int constant, except the name and the type are different. This time the constant is a Double, a type that can store decimals with high precision.

There’s also a type called Float, short for floating point, that stores decimals with lower precision than Double. A Float takes up less memory than a Double but generally, memory use for numbers isn’t a huge issue and you’ll see Double used in most places.

Once you’ve declared a constant, you can’t change its data. For example, consider the following code:

let number: Int = 10
number = 0

This code produces an error:

Cannot assign to value: 'number' is a 'let' constant

In Xcode, you would see the error represented this way:

01_Constant_reassign_error

Constants are useful for values that aren’t going to change. For example, if you were modeling an airplane and needed to keep track of the total number of seats available, you could use a constant.

You might even use a constant for something like a person’s age. Even though their age will change as their birthday comes, you might only be concerned with their age at this particular instant.

Variables

Often you want to change the data behind a name. For example, if you were keeping track of your bank account balance with deposits and withdrawals, you might use a variable rather than a constant.

If your program’s data never changed, then it would be a rather boring program! But as you’ve seen, it’s not possible to change the data behind a constant.

When you know you’ll need to change some data, you should use a variable to represent that data instead of a constant. You declare a variable in a similar way, like so:

var variableNumber: Int = 42

Only the first part of the statement is different: You declare constants using let, whereas you declare variables using var.

Once you’ve declared a variable, you’re free to change it to whatever you wish, as long as the type remains the same. For example, to change the variable declared above, you could do this:

var variableNumber: Int = 42
variableNumber = 0
variableNumber = 1_000_000

To change a variable, you simply set it equal to a new value.

Note: In Swift, you can optionally use underscores to make larger numbers more human-readable. The quantity and placement of the underscores is up to you.

This is a good time to introduce the results sidebar of the playground. When you type the code above into a playground, you’ll see that the results sidebar on the right shows the current value of variableNumber at each line:

02_Variables_results_sidebar

The results sidebar will show a relevant result for each line, if one exists. In the case of a variable or constant, the result will be the new value, whether you’ve just declared a constant, or declared or reassigned a variable.

Naming

Always try to choose meaningful names for your variables and constants.

A good name specifically describes what the variable or constant represents. Here are some examples of good names:

  • personAge
  • numberOfPeople
  • gradePointAverage

Often a bad name is simply not descriptive enough. Here are some examples of bad names:

  • a
  • temp
  • average

The key is to ensure that you’ll understand what the variable or constant refers to when you read it again later. Don’t make the mistake of thinking you have an infallible memory! It’s common in computer programming to look back at code as early as a day or two later and have forgotten what it does. Make it easier for yourself by giving your variables and constants intuitive, precise names.

In Swift, you can even use the full range of Unicode characters. This means you could, for example, declare a variable like so:

var &#x1f436;&#x1f4a9;: Int = -1

That might make you laugh, but use caution with special characters like these. They are harder to type and therefore may end up causing you more pain than amusement.

bad_choice

Special characters like these probably make more sense in data that you store rather than in Swift code.

Type conversion

Sometimes you’ll have data in one format and need to convert it to another. The naïve way to attempt this would be like so:

var integer: Int = 100
var decimal: Double = 12.5
integer = decimal

Swift will complain if you try to do this and spit out an error on the third line:

Cannot assign a value of type 'Double' to a value of type 'Int'

Some programming languages aren’t as strict and will perform simple numeric conversions like this automatically. Swift, however, is very strict about the types it uses and won’t let you assign a value of one type to a variable of another type.

Remember, computers rely on us programmers to tell them what to do. In Swift, that includes being explicit about type conversions. If you want the conversion to happen, you have to say so!

Instead of simply assigning, you need to explicitly say that you want to convert the type. You do it like so:

var integer: Int = 100
var decimal: Double = 12.5
integer = Int(decimal)

The assignment on the third line now tells Swift unequivocally that you want to convert from the original type, Double, to the new type, Int.

Note: In this case, assigning the decimal value to the integer results in a loss of precision: The integer variable ends up with the value 12 instead of 12.5. This is why it’s important to be explicit. Swift wants to make sure you know what you’re doing and that you may end up losing data by performing the type conversion.

Tuples

Sometimes data comes in pairs or triplets. An example of this is a pair of (x, y) coordinates on a 2D grid. Similarly, a set of coordinates on a 3D grid is comprised of an x-value, a y-value and a z-value.

In Swift, you can represent such related data in a very simple way through the use of a tuple.

A tuple is a type that represents data composed of more than one value of any type. You can have as many values in your tuple as you like For example, you can define a pair of 2D coordinates where each axis value is an integer, like so:

let coordinates: (Int, Int) = (2, 3)

The type of coordinates is a tuple containing two Int values. The types of the values within the tuple, in this case Int, are separated by commas surrounded by parentheses. The code for creating the tuple is much the same, with each value separated by commas and surrounded by parentheses.

You could similarly create a tuple of Double values, like so:

let coordinates: (Double, Double) = (2.1, 3.5)

Or you could mix and match the types comprising the tuple, like so:

let coordinates: (Double, Int) = (2.1, 3)

And here’s how to access the data inside a tuple:

let coordinates: (Int, Int) = (2, 3)
let x: Int = coordinates.0
let y: Int = coordinates.1

You can reference each item in the tuple by its position in the tuple, starting with zero. So in this example, x will equal 2 and y will equal 3.

Note: Starting with zero is a common practice in computer programming and is called zero indexing.

In the example above, it may not be immediately obvious that the first value, at index 0, is the x-coordinate and the second value, at index 1, is the y-coordinate. This is another demonstration of why it’s important to always name your variables in a way that avoids confusion.

Fortunately, Swift allows you to name the individual parts of a tuple, so you to be explicit about what each part represents. For example:

let coordinatesNamed: (x: Int, y: Int) = (2, 3)

Here, the code annotates the type of coordinatesNamed to contain a label for each part of the tuple.

Then, when you need to access each part of the tuple, you can access it by its name:

let x: Int = coordinatesNamed.x
let y: Int = coordinatesNamed.y

This is much clearer and easier to understand. More often than not, it’s helpful to name the components of your tuples.

If you want to access multiple parts of the tuple at the same time, as in the examples above, you can also use a shorthand syntax to make it easier:

let coordinates3D: (x: Int, y: Int, z: Int) = (2, 3, 1)
let (x, y, z) = coordinates3D

This declares three new constants, x, y and z, and assigns each part of the tuple to them in turn. The code is equivalent to the following:

let coordinates3D: (x: Int, y: Int, z: Int) = (2, 3, 1)
let x = coordinates3D.x
let y = coordinates3D.y
let z = coordinates3D.z

If you want to ignore a certain element of the tuple, you can replace the corresponding part of the declaration with an underscore. For example, if you were performing a 2D calculation and wanted to ignore the z-coordinate of coordinates3D, then you’d write the following:

let (x, y, _) = coordinates3D

This line of code only declares x and y. The _ is special and simply means you’re ignoring this part for now.

Note: You’ll find that you can use the underscore throughout Swift to ignore a value.

Type inference

Every time you’ve seen a variable or constant declared, there’s been an associated type. That is, until you saw the syntax for reading multiple values from a tuple at the same time. Take a look at it again:

let coordinates3D: (x: Int, y: Int, z: Int) = (2, 3, 1)
let (x, y, z) = coordinates3D

There’s nothing on the second line to indicate that x, y and z are of type Int. So how does Swift know that they are of type Int?

Reading the code yourself, it’s clear that the constants created on the second line are of type Int. You know that because the code declares a tuple comprising three Int values.

It turns out the Swift compiler can do this process of deduction, as well. It doesn’t need you to tell it the type—it can figure it out on its own. Neat! :]

As it happens, you can drop the type in other places besides tuples. In fact, in most places, you can omit the type because Swift already knows it.

For example, consider the following constant declaration:

let typeInferredInt = 42

The value on the right-hand side is an integer type. Swift knows this, too, and therefore it infers that the type of the constant should be an Int. This process is known as type inference, and it’s a key component of Swift’s power as a language.

Sometimes it’s useful to check the inferred type of a variable or constant. You can do this in a playground by holding down the Option key and clicking on the variable or constant’s name. Xcode will display a popover like this:

03_Type_inferred_Int

Xcode tells you the inferred type by giving you the declaration you would have had to use if there were no type inference. In this case, the type is Int.

It works for other types, too:

let typeInferredDouble = 3.14159

Option-clicking on this reveals the following:

04_Type_inferred_Double

You can see from this that type inference isn’t magic. Swift is simply doing what your human brain does very easily. Programming languages that don’t use type inference can often feel verbose, because you need to specify the often obvious type each time you declare a variable or constant.

Where to go from here?

In this tutorial you have learned about one of the fundamentals of Swift and programming in general. Variables and constants will follow you throughout the course of your Swift career.

By defining things as either variables or constants with a type, Swift will help you keep track of your data. With type inference, Swift also lets you be more concise with syntax when it can figure things out.

This post is an excerpt from the Swift Apprentice. Pick up a copy of the book if you’d like to learn more about Swift right from the foundations.

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

The post Swift Tutorial: Variables and Constants appeared first on Ray Wenderlich.

Readers’ App Reviews – October 2015

$
0
0

drawwithme

Trick or Treat!


Time flies when your entire community is working hard to release great apps. October is here already, and you’ve clearly been hard at work!

I have tried all the apps submitted this month, and have a few I’d like to share with you. I never have time to write about each app submitted, so make sure you checkout the Honorable Mentions below too.

This months community showcase includes:

  • An app for classroom teachers
  • A game after Elon Musk’s own heart
  • Addictive puzzle games you can’t put down
  • And of course, much more!

Read on to see what your community has been up to this month!

Crazy Planets

crazyplanets
Crazy Planets is a fun puzzle game that gives you control of the universe!

Aligning the planets is up to you now. Rotate each planet to control the flow from start to finish. Each of the seven planets has a unique ability from split shots to locked rotation and more.

You’ll get tons of practicing going through level after level of misaligned planets that need your help. You’ll have to analyze each pattern to find the optimum way to ensure each planet has a chance to pass along its energy to the next. Try not to go crazy in the process. ;]

Wee Puzzles

weepuzzles
Wee Puzzles is an adorable puzzle app for kids.

Wee Puzzles brings tons of very cute artwork into a drag and drop puzzle format. Kids can drag and drop individual parts of a picture. Each with a small hint where it should go. Once the puzzle is complete, it comes to life for a few moments. Super cool.

The sounds are one of the standout features. Tons of sound based feedback keeps things fun. Soothing background music really helps make the experience.

There is also an awesome Halloween version out just in time!

Oncore

oncore
Oncore is an app for classroom management build by teachers, for teachers.

Oncore users your seating chart as the interface, making it easy to find your students and collect one touch data on each student. You can track attendance, disciplinary actions, and concept retention. Oncore will help you keep track of which students have been engaged and which need more interaction.

Oncore’s most powerful feature is its integration directly with Common Core and Next Generation Science Standards. Teachers can connect classroom activities and assignments with necessary standards to track coverage overtime.

Oncore is a very powerful tool for teachers. Its free to get started before a $10 in app purchase to unlock the rest of the app. If you’re working with kids, give it a try.

Asteroid Tap

asteroidtap
Asteroid Tap is a simple, addictive game that combines a retro look and simple controls for a classic arcade feel.

Controlling your asteroid destroying ship is easy. Tap and hold on the screen to rotate. Release the screen to fire. Shoot the asteroids before they crush you! There are a variety of difficulties ranging from easy to impossible.

Asteroid Tap is integrated with Game Center. Achievements abound so you can show off how good you are. And of course Leaderboards will make sure you can check how you stack up against your friends.

DrawWithMePro

drawwithme
DrawWithMePro is a connected drawing application perfect for interactive group drawing.

DrawWithMePro uses bluetooth to setup drawing sessions for up to 7 iPads at a time. Each user is able to draw in realtime with the other users for maximum collaboration. DrawWithMePro is great for business meetings, planning sessions, or just a bit of fun.

DrawWithMePro has a number of expected drawing features. You can draw freeform or use several shape stamps as well as adjust color and stroke sizes. You can of course add text directly to the canvas using built in fonts. You can import pictures from your camera roll.

Paradot

paradot
Paradot is an additive yet simple puzzle game built around timing and circles.

Circles of colors dots rotate in the center of the screen. You have a single colored dot that you want to get to the middle of the stage. Taping advances your dot, but it must advance to a matching color or its game over. You must traverse each layered circle one at a time before making it to the center to complete the level.

Game Center makes it easy to compete with friends and family over who’s the best at passing the dot.

Vidblend

vidblend
VidBlend is a powerful video blending editor for iOS.

VidBlend begins with a powerful video editor that lets you add filters to video on the fly. There are 20+ filters to apply to your video. You can adjust colors, rotate, slow it down, add text and audio overlays, and more! But the real power begins when you blend two videos together. You can start with a simple overlay video, but more on to color dodges, exclusions, or any number of common blending effects.

Vidblend will then let you share your new creation with the world. Save it, mail it, message it, tweet it, whatever you like.

Railblazer

railblazer
You’ve got to keep the train moving in Railblazer!

There is a train moving along a short stretch of track. If you do nothing, it will run aground! Lay out track as fast as you can. But keep an eye on the horizon, don’t want too steer yourself into a tree or a mountain! Run your train through a station for a celebration and chance to shuffle your tracks.

Railblazer supports Game Center for a little competition between friends. There are two leaderboards, a highest score board for the longest track and a longest loop board for the longest track that ends in a loop instead of a crash. See if you can make your mark on either. ;]

SpaceX Falcon 9 Lander

spaceX
It is really hard to land a rocket upright on a floating barge in the ocean. Just ask Elon Musk.

SpaceX Falcon 9 Lander will give you a taste of what poor Elon is going through. You’ve got to control your main thrusters and the side thrusters that keep you upright. Steer yourself over to the platform and come in for a landing nice and slow. BOOM! Thats about the point I explode every single time. Its hard to get everything just right in this challenging game. But boy is it addicting. Now I know why Elon keeps trying. ;]

Draw Me That

drawmethat
What if an alien race threatened our planet with a challenge of drawing geometric shapes to save our lives? Would you be ready?

Draw Me That will make sure you are. With over 100 shapes ready to be drawn just right, you’ve certainly got your work cut out for you. The game is easy to play, simply tap each dot in the right order and watch the shape draw itself before your eyes. Tap them in the wrong order and you’ll find yourself stuck in the shape of shame.

Game Center will make sure your friends know who’s in the lead to represent earth in the intergalactic tournament.

Strategy Duel

strategyduel
Strategy Duel is a board game for your iPhone like Connect 4 and Rock Paper Scissors at the same time.

Strategy Duel starts with a checkerboard of tokens for both players. But you can’t see your opponents pieces. Each turn you can upgrade one of your tokens or attack a nearby token. The goal is to connect 6 of your tokens in a row to win.

You have a variety of options when playing your turn. You can upgrade your 1 star token to 2 star or 2 star to 3 star. You can convert your token in to a bomb, relinquishing your attack but making sure you’re safe from encroaching opponent tokens. You can take a peak at nearby tokens to plan your next move. Or you can do what you do best, attack a nearby token to take over more of the board.

Strategy Duel uses Game Center for multiplayer so you don’t just have to try out your strategies on the A9 chip, you can compete against your friends!

Honorable Mentions

Every month I get way more submissions than I have time to write about. I download every app to try them out, but only have time to review a select few. I love seeing our readers through the apps submitted to me every month. Its not a popularity contest or even a favorite picking contest. I just try to share a snapshot of the community through your submissions. Please take a moment and try these other fantastic apps from readers like you.

Finger Tap Challenge
What am I flying on?
Approximal
App Cost
Cartel Kings
Space Erase
Gobi
Painter X
Fourth Estate
Math Race – Race the car using brain power
App Cost
Water++
Periodic Table of Elements Bubble Pop
Chicken Madness: Catching Eggs
TSpeaker

Where To Go From Here?

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

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

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

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

Swift Tutorial: Repeating Steps with Loops

$
0
0
Note from Ray: This is an abridged version of a chapter from the Swift Apprentice, to give you a sneak peek of what’s inside the book, released as part of the iOS 9 Feast. We hope you enjoy!

A Swift 2 tutorial for the iOS 9 Feast!

In this tutorial, you’ll learn how to control the flow of execution, this time using loop statements.

Loop statements allow you to perform the same operation multiple times. That may not sound very interesting or important, but loops are very common in computer programs.

For example, you might have code to download an image from the cloud; with a loop, you could run that multiple times to download your entire photo library. Or if you have a game with multiple computer-controlled characters, you might need a loop to go through each one and make sure it knows what to do next.

Let’s get started!

Ranges

Before you dive into the loop statements themselves, you need to know about one more data type called a Range, which lets you represent a sequence of numbers. Let’s look at two types of Range.

First, there’s closed range, which you represent like so:

let closedRange = 0...5

The three dots (...) indicate that this range is closed, which means the range goes from 0 to 5, inclusive of both 0 and 5. That’s the numbers (0, 1, 2, 3, 4, 5).

Second, there’s half-open range, which you represent like so:

let halfOpenRange = 0..<5

Here, you replace the three dots with two dots and a less-than sign (..<). Half-open means the range goes from 0 to 5, inclusive of 0 but not of 5. That's the numbers (0, 1, 2, 3, 4).

You need to know about ranges because they're commonly used with loops, the main focus of this tutorial.

Loops

Loops are Swift's way of executing code multiple times. In the following sections, you'll learn about two variants of loops available to you in Swift: for loops and while loops. If you know another programming language, you'll find the concepts and maybe even the syntax familiar.

For Loops

First, let's turn to the for loop. This is probably the most common loop you'll see, and you'll use them to run code a certain number of times, incrementing a counter at each stage.

You construct a for loop like this:

for <INITIAL CONDITION>; <LOOP CONDITION>; <ITERATION CODE> {
  <LOOP CODE>
}

The loop begins with the for keyword, followed by three expressions:

  1. You set up the loop with an initial condition, such as the value of a variable.
  2. The loop runs as long as the loop condition is true.
  3. At the end of each loop, the loop runs the iteration code.

Here's an example:

let count = 10
 
var sum = 0
for var i = 1; i <= count; i++ {
  sum += i
}

In the code above, you set up the loop with a variable called i that you initially assign the value of 1; the loop runs until i is no longer less than or equal to count (that is, until i is greater than count).

Inside the loop, you add i to the sum variable, and at the end of each iteration of the loop, you increment i by 1.

In terms of scope, the i variable is only visible inside the scope of the for loop, which means it's not available outside of the loop.

This loop runs 10 times to calculate the sequence 1 + 2 + 3 + 4 + 5 + ... all the way up to 10.

Here are the values of the variables for each iteration:

  • Before iteration 1: i = 1, sum = 0
  • After iteration 1: i = 2, sum = 1
  • After iteration 2: i = 3, sum = 3
  • After iteration 3: i = 4, sum = 6
  • After iteration 4: i = 5, sum = 10
  • After iteration 5: i = 6, sum = 15
  • After iteration 6: i = 7, sum = 21
  • After iteration 7: i = 8, sum = 28
  • After iteration 8: i = 9, sum = 36
  • After iteration 9: i = 10, sum = 45
  • After iteration 10: i = 11, sum = 55
Note: If you're mathematically astute, you might notice that this example computes triangle numbers. Here's a quick explanation: http://bbc.in/1O89TGP

Xcode's playground gives you a handy way to visualize such an iteration. Hover over the sum += i line in the results pane, and you'll see a white dot on the right. Hover over that dot to reveal a plus (+) button:

01_Loop_before_graph

Click this plus (+) button and Xcode will display a graph underneath the line within the playground code editor:

02_Loop_after_graph

This graph lets you visualise the sum variable as the loop iterates.

There's another way to implement the same for loop, and it involves using a special for loop called a for-in loop. Instead of having to create a variable to hold the loop counter and increment it yourself, you can iterate through a range, like so:

let count = 10
var sum = 0
 
for i in 1...count {
  sum += i
}

This code executes in exactly the same way as the previous loop and computes the same number; it's simply a more succinct way of doing so. Because of this, for-in loops are desirable over standard for loops wherever possible.

Finally, sometimes you only want to loop a certain number of times, and so you don't need to use the loop variable at all. In that case, you can employ the underscore once again, like so:

let count = 10
var sum = 1
var lastSum = 0
 
for _ in 0..<count {
  let temp = sum
  sum = sum + lastSum
  lastSum = temp
}

This code doesn't require the loop variable; the loop simply needs to run a certain number of times. In this case, the range is 0 through count and is half-open. This is the usual way of writing loops that run a certain number of times.

While loops

The next type of loop continues to iterate only while a certain condition is true. Because of this, it's called the while loop.

You create a while loop this way:

while <CONDITION> {
  <LOOP CODE>
}

Every iteration, the loop checks the condition. If the condition is true, then the loop executes and moves on to another iteration. If the condition is false, then the loop stops. Just like for loops and if statements, while loops introduce a scope.

The simplest while loop takes this form:

while true {
}

This is a while loop that never ends, because the condition is always true. Of course, you would never write such a while loop, because your program would spin forever! This situation is known as an infinite loop, and while it might not cause your program to crash, it will very likely cause your computer to freeze.

force_quit

Here's a more useful example of a while loop:

var sum = 1
 
while sum < 1000 {
  sum = sum + (sum + 1)
}

This code calculates a mathematical sequence, up to the point where the value is greater than 1000. The loop executes as follows:

  • Before iteration 1: sum = 1, loop condition = true
  • After iteration 1: sum = 3, loop condition = true
  • After iteration 2: sum = 7, loop condition = true
  • After iteration 3: sum = 15, loop condition = true
  • After iteration 4: sum = 31, loop condition = true
  • After iteration 5: sum = 63, loop condition = true
  • After iteration 6: sum = 127, loop condition = true
  • After iteration 7: sum = 255, loop condition = true
  • After iteration 8: sum = 511, loop condition = true
  • After iteration 9: sum = 1023, loop condition = false

After the ninth iteration, the sum variable is 1023, and therefore the loop condition of sum < 1000 becomes false. At this point, the loop stops.

Repeat-while Loops

Another variant of the while loop is called the repeat-while loop. It differs from the while loop in that the condition is evaluated at the end of the loop rather than at the beginning.

You construct a repeat-while loop like this:

repeat {
  <LOOP CODE>
} while <CONDITION>

Here's the example from the last section, but using a repeat-while loop:

var sum = 1
 
repeat {
  sum = sum + (sum + 1)
} while sum < 1000

In this example, the outcome is the same as before. However, that isn't always the case—you might get a different result with a different condition. Consider the following while loop:

var sum = 1
 
while sum < 1 {
  sum = sum + (sum + 1)
}

And now consider the corresponding repeat-while loop, which uses the same condition:

var sum = 1
 
repeat {
  sum = sum + (sum + 1)
} while sum < 1

In the case of the regular while loop, the condition sum < 1 is false right from the start. That means the body of the loop won't be reached! The value of sum will equal 1, because the loop won't execute any iterations.

In the case of the repeat-while loop, however, sum will equal 3 because the loop will execute once.

Breaking out of a loop

Sometimes you want to break out of a loop early. You can do this using the break keyword, which immediately stops the execution of the loop and continues on to the code after the loop.

For example, consider the following code:

var sum = 1
 
while true {
  sum = sum + (sum + 1)
  if (sum >= 1000) {
    break
  }
}

Here, the loop condition is true, so the loop would normally iterate forever. However, the break means the while loop will exit once the sum is greater than or equal to 1000. Neat!

You've seen how to write the same loop in different ways, demonstrating that in computer programming, there are often many ways to achieve the same result. You should choose the method that's easiest to read and conveys your intent in the best way possible, an approach you'll internalize with enough time and practice.

Note: The break keyword also works in for loops, in exactly the same way it does in while loops.

Labeled Statements

Sometimes you want to be able to skip a loop iteration. For example, if you were going through a range but wanted to skip over all odd numbers, you don't want to break out of the loop entirely—you just want to skip the current iteration but let the loop continue.

You can do this by using the continue keyword, which immediately finishes the current iteration of the loop and begins the next iteration.

To demonstrate this, I'll use an example of a chess board that's an 8 by 8 grid, where each cell holds a value of the row multiplied by the column, like a multiplication table:

03_Full_board

The first code example will calculate the sum of all cells, excluding all even rows. To illustrate, it will sum the following cells:

04_First_board_example

Using a for loop, you can achieve this as follows:

var sum = 0
 
for row in 0..<8 {
  if row % 2 == 0 {
    continue
  }
 
  for column in 0..<8 {
    sum += row * column
  }
}

When the row modulo 2 equals 0, the row is even. In this case, continue makes the for loop skip to the next row.

Just like break, continue works with both for loops and while loops.

The second code example will calculate the sum of all cells, excluding those where the column is greater than or equal to the row. To illustrate, it will sum the following cells:

05_Second_board_example

Using a for loop, you can achieve this as follows:

var sum = 0
 
rowLoop: for row in 0..<8 {
  columnLoop: for column in 0..<8 {
    if row == column {
      continue rowLoop
    }
    sum += row * column
  }
}

This last code block makes use of labeled statements, labeling the two loops as the rowLoop and the columnLoop, respectively. When the row equals the column inside the inner columnLoop, the outer rowLoop will continue.

You can use labeled statements like these with break to break out of a certain loop, if you like. Normally, break and continue work on the inner-most loop, so you need to use labeled statements if you want to manipulate an outer loop.

Where To Go From Here?

In this tutorial, you've learned about all the kinds of loops you can use in Swift. With ranges, loops and loop control statements such as break and continue, you'll be able to get your Swift code running and repeating exactly as you intend!

Hopefully this has piqued your interest to learn more about Swift. This post is an excerpt from the Swift Apprentice. Pick up a copy of the book if you'd like to learn more about Swift right from the foundations.

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

The post Swift Tutorial: Repeating Steps with Loops appeared first on Ray Wenderlich.

Preorders for tvOS Apprentice Now Available!

$
0
0

TVT-Thumb

Happy Apple TV preorder day! Did you preorder yours yet?

But preordering just the hardware isn’t enough for developers – you need a book about developing for it too.

As you may have guessed, ever since the tvOS SDK was first announced the team has been hard at work on a new book about tvOS development – the tvOS Apprentice – and it is available for preorder today.

Keep reading to find out what’s inside the book and learn about the early access program and preorder discount!

What’s Inside

The tvOS Apprentice is a book for complete beginners to tvOS development, that teaches you everything you need to know to make great Apple TV apps. You don’t need any iOS development experience to enjoy the book, but some rudimentary Swift knowledge is required (see the Swift Apprentice).

Here’s the tentative table of contents:

Note: This book is still in development, so this is subject to change.
  • Chapter 1, Architecture: Covers the concept of JavaScript / TVML based UI, as well as Traditional UI, and pros and cons of both designs.
  • Chapter 2, Hello, TVML app: Make your first TVML app!
  • Chapter 3, Simple TVML templates: Learn about some simple TVML templates such as Alert, Descriptive Alert, Form, Main Menu, and Menu Bar.
  • Chapter 4, Advanced TVML templates: Learn about more advanced TVML templates such as Catalog, Compilation, List, Parade, Product, and Stack.
  • Chapter 5, TVJS: Learn how to use the TVJS framework to inspect, modify, and create TVML.
  • Chapter 6, TVMLKit: Learn how to use new TVMLKit as a Swift / TVML bridge.
  • Chapter 7, Harnessing the Server: Go through a real-world example of generating TVML from a web app.
  • Chapter 8, Hello, Traditional App: Make your first traditional tvOS app!
  • Chapter 9, Basic Controls: Learn about basic tvOS controls like Images, Buttons, Text Input.
  • Chapter 10, Stack Views: Learn how to use stack views to layout your tvOS apps.
  • Chapter 11, Collection Views: Learn how to use table views to display collections of data in your tvOS apps.
  • Chapter 12, Navigation: Learn how to add navigation into your tvOS apps using UITabBarController, UINavigationController, and more.
  • Chapter 13, Focus: Learn about the new tvOS focus engine and how to design your apps around this concept.
  • Chapter 14, Animation: Learn how to apply animation in tvOS and Apple’s recommendations on the matter from the HIG.
  • Chapter 15, Networking: Learn how to use NSURLSession to retrieve data from a server, including stuff like caching images, best practices, etc.
  • Chapter 16, Playing Video: The Basics: Learn how to play video content, full screen, not full screen, etc.
  • Chapter 17, User Input and the Controller basics: Learn about different button presses from the controller and how to handle them, plus how you can create gesture recognizers for the touch section of the controller.
  • Chapter 18, CloudKit: Learn how to use CloudKit to store data for your tvOS apps.
  • Chapter 19, Advanced Video Playback: Learn how to use AVFoundation for more advanced video manipulation.
  • Chapter 20, In-App Purchase: Learn how to make money in your tvOS apps with in-app purchase.
  • Chapter 21, On Demand Resources: Learn how to allow Apple to host some extra of your app’s assets so you don’t necessarily have to download them all at app download time.
  • Chapter 22, Mixing TVML and Traditional UI: Learn how you can leverage the power of TVML in traditional UI-based apps!
  • Chapter 23, Designing for tvOS: Learn how to design delightful tvOS apps, including dealing with different screen sizes, safe zones around the edges of the screen, the focus on images and minimal text, color palettes, parallax, focus, etc.
  • Chapter 24, Creating Layered Images: Learn how to create layered images, including using the preview tool, and how to manage them in Xcode.
  • Chapter 25, The Top Shelf: Learn how to create top shelf images for your apps, including dynamically changing their content.
  • Appendix I, Javscript Crash Course: TVML apps use Javascript. If you don’t know it already, this crash course may come in handy!
  • Appendix II, Web Development Crash Course: This appendix will cover the web development knowledge you’ll need to follow along with the book.

Where To Go From Here?

The tvOS Apprentice will be released in Q1 2016. If you preorder the book now, you’ll get two bonuses:

  1. Early access to the book: We plan on releasing a few early access versions of the book as chapters come in. Everyone who preorders the book gets access to the early access versions of the book as they become available!
  2. Preorder discount: Everyone who preorders the book before it is released gets the book at the lowest possible price – $10 off the regular price.

So preorder your copy of the tvOS Apprentice along with your new Apple TV, and you’ll be set to take advantage of this amazing new opportunity and create some great apps on the big screen.

Enjoy your new Apple TV – and book! :]

The post Preorders for tvOS Apprentice Now Available! appeared first on Ray Wenderlich.


Swift Tutorial: Introducing Structures

$
0
0
Note from Ray: This is an abridged version of a chapter from the Swift Apprentice, to give you a sneak peek of what’s inside the book, released as part of the iOS 9 Feast. We hope you enjoy!

A Swift 2 tutorial for the iOS 9 Feast!

Using the fundamental building blocks such as variables and constants (some of which you learned about in our previous free excerpt from the Swift Apprentice), you might think you’re ready to conquer the world! Almost ;]

Most programs that perform complex tasks would probably benefit from higher levels of abstraction. In other words, in addition to an Int, String or Array, they’ll need new types that are specific to the domain of the task at hand.

This tutorial will introduce structures, which are a “named type”. Like a String, Int or Array, you can define your own structures to create named types to later use in your code. By the end of this tutorial, you’ll know how to define and use your own structures.

Introducing Structures

Imagine you’re writing a program that calculates if a potential customer is within range of a pizza delivery restaurant. You might write code like this:

let latitude: Double = 44.9871
let longitude: Double = -93.2758
let range: Double = 200.0
 
func isInRange(lat: Double, long: Double) -> Bool {
  // And you thought in Math class
  // you would never use the Pythagorean theorem!
  let difference = sqrt(pow((latitude - lat), 2) +
    pow((longitude - long), 2))
  let distance = difference * 0.002
  return distance < range
}

Simple enough, right? A successful pizza delivery business may eventually expand to include multiple locations, which adds a minor twist to the deliverable calculator:

let latitude_1: Double = 44.9871
let longitude_1: Double = -93.2758
 
let latitude_2: Double = 44.9513
let longitude_2: Double = -93.0942

Now what? Do you update your function to check against both sets of coordinates? Eventually, the rising number of customers will force the business to expand, and soon it might grow to a total of 10 stores! Not only that, but some new stores might have different delivery ranges, depending on whether they’re in a big city or a sprawling suburb.

You might briefly consider creating an array of latitudes and longitudes, but it would be difficult to both read and maintain. Fortunately, Swift has additional tools to help you simplify the problem.

Your First Structure

Structures, or structs, are one of the named types in Swift that allow you to encapsulate related properties and behaviors. You can define it, give it a name and then use it in your code.

In the example of the pizza business, it’s clear that latitude and longitude are closely related—close enough that you could think of them as a single value:

struct Location {
  let latitude: Double
  let longitude: Double
}

This block of code demonstrates the basic syntax for defining a struct. In this case, it’s a type named Location that combines both latitude and longitude.

The basic syntax begins with the struct keyword followed by the name and a pair of curly braces. Everything between the curly braces is a “member” of the struct.

Now that you’ve defined your first struct, you can instantiate one and store it in a constant or variable just like any other type you’ve worked with:

let pizzaLocation = Location(latitude: 44.9871, longitude: -93.2758)

Instead of storing the coordinates in two separate variables, you store them together!

To create the Location value, you use the name of the type along with parentheses containing both the latitude and the longitude parameters. Swift defines this initializer automatically, and it’s a subject this tutorial will cover in more detail later.

You may remember that there’s also a range involved, and now that the pizza business is expanding, there may be different ranges associated with different restaurants. You can create another struct that represents the location and the range, like so:

struct DeliveryRange {
  var range: Double
  let center: Location
}
 
let storeLocation = Location(latitude: 44.9871, longitude: -93.2758)
var pizzaRange = DeliveryRange(range: 200, center: storeLocation)

Now there’s a new struct named DeliveryRange that contains a variable range of the pizza restaurant along with the Location center.

Accessing Members

With your DeliveryRange defined and an instantiated value in hand, you may be wondering how you can use these values. In Swift, structures and the other types you’ll learn about use a simple “dot syntax” to access their members:

print(pizzaRange.range) // 200

You can even access members of members using dot syntax:

print(pizzaRange.center.latitude) // 44.9871

Similar to how you can read values with dot syntax, you can also assign them. If the delivery range of one pizza location becomes larger, you could assign the new value to the existing variable:

pizzaRange.range = 250

image001

In addition to properties, you must declare the struct itself as a variable to be able to modify it:

let constPizzaRange = DeliveryRange(range: 200, center: storeLocation)
 
// Error: change ‘let’ to ‘var’ above to make it mutable
constPizzaRange.range = 250

Now that you have the range and location together in one struct, how would you rewrite isInRange(_:long:) to take a struct parameter instead of two Double values?

Solution Inside: Rewrite isInRange to use Location and DeliveryRange SelectShow>

Initializing a Struct

When you defined the Location and DeliveryRange structs, Swift automatically generated a way to create these values:

Location(latitude: 44.9871, longitude: -93.2758)

When you create an instance of a type such as Location, you need to use a special kind of function called an initializer. Swift will automatically create a default initializer, such as the one shown above, that takes each member as a named parameter.

You can also create your own initializer, which allows you to customize how a structure’s members are assigned:

struct Location {
  let latitude: Double
  let longitude: Double
 
  // String in GPS format "44.9871,-93.2758"
  init(coordinateString: String) {
    let crdSplit = coordinateString.characters.split(",")
    latitude = atof(String(crdSplit.first!))
    longitude = atof(String(crdSplit.last!))
  }
}

Here, the init keyword marks this function as an initializer for the Location struct.

In this case, the initializer takes a latitude and longitude together as a comma-separated string. This could be useful if you’re reading locations from a text file.

let coords = Location(coordinateString: "44.9871,-93.2758")
print(coords.latitude) // 44.9871
print(coords.longitude) // -93.2758

Keep in mind that as soon as you define a custom initializer, Swift won’t add the automatically-generated one. If you still need it, you’ll have to define it yourself!

Introducing Self

If a method parameter and property have the same name, you can use the self keyword to give the compiler explicit context if you want to operate on the property. When you use self in code, you’re explicitly accessing the current value of the named type.

In other words, using dot synax on self is just like using dot syntax on a variable storing that value.

self.latitude = atof(String(crdSplit.first!))

You’re not required to use self when writing code within a named type; Swift infers it automatically, which is why you’ve been able to write code without it so far.

Why use it then? It’s especially useful in initializers: When two variables of the same name exist in the same scope, self can prevent what’s known as shadowing.

init(latitude: Double, longitude: Double) {
  latitude = latitude
  longitude = longitude
}

There’s an initializer argument latitude as well as a property latitude. Which one are you referring to in this code snippet?

It’s actually the argument, which isn’t what you want. Instead, you can simply add self. before the variable you’re assigning, as follows:

init(latitude: Double, longitude: Double) {
  self.latitude = latitude
  self.longitude = longitude
}

This makes it clear that you’re assigning the parameter values to the properties.

Initializer Rules

Initializers in structs have a few rules that guard against unset values. By the end of the initializer, the struct must have initial values set in all of its stored properties.

If you were to forget to assign the value of longitude, for instance, you would see an error at compile time:

image001

Its purpose is simple: Stored properties need to be initialized with a value.

Other languages have types similar to structs and may assign default values, such as a value of 0 for an integer. Swift, focusing on safety, ensures that every value has been explicitly set.

There’s one exception to the rule that stored properties must have values: optionals!

struct ClimateControl {
  var temperature: Double
  var humidity: Double?
 
  init(temp: Double) {
    temperature = temp
  }
}

In this simplified example, humidity is an optional—perhaps an “optional” setting on a thermostat! Here, the initializer doesn’t specify a value for humidity. Because humidity is an optional, the compiler will happily oblige.

For convenience, you can specify another initializer that would include both values:

struct ClimateControl {
  var temperature: Double
  var humidity: Double?
 
  init(temp: Double) {
    temperature = temp
  }
 
  init(temp: Double, hum: Double) {
    temperature = temp
    humidity = hum
  }
}

Now you can create ClimateControl values with or without a humidity value:

let ecoMode = ClimateControl(temp: 75.0)
let dryAndComfortable = ClimateControl(temp: 71.0, hum: 30.0)

Optional variables do get a default value of nil, which means the first initializer with only a temperature parameter is valid.

Note: If you declare the optional as a constant, you must still provide an initial value, whether it’s nil or an actual value. Once the struct is defined, it can no longer be changed!

Introducing Methods

Using some of the capabilities of structs, you could now make a pizza delivery range calculator that looks something like this:

let pizzaJoints = [
  DeliveryRange(location: Location(coordinateString: "44.9871,-93.2758")),
  DeliveryRange(location: Location(coordinateString: "44.9513,-93.0942")),
]
 
func isInRange(location: customer) -> Bool {
  for pizzaRange in pizzaJoints {
    let difference = sqrt(pow((latitude - lat), 2) + pow((longitude - long), 2))
    if (difference < joint.range) {
      return true
    }
  }
  return false
}
 
let customer = Location(44.9850,-93.2750")
 
print(isInRange(location: customer)) // Pizza time!

In this example, there’s an array pizzaJoints and a function that uses that array to determine if a customer’s location is within range of any of them.

The idea of being “in range” is very tightly coupled to the characteristics of a single pizza restaurant. In fact, all of the calculations in isInRange occur on one location at a time. Wouldn’t it be great if DeliveryRange itself could tell you if the restaurant can deliver to a certain customer?

Much like a struct can have constants and variables, it can also define its own functions:

struct DeliveryRange {
  var range: Double
  let center: Location
 
  func isInRange(customer: Location) -> Bool {
    let difference = sqrt(pow((customer.latitude - center.latitude), 2) +
          pow((customer.longitude - center.longitude), 2))
    return difference < range
  }
}

This code defines the method isInRange(_:), which is now a member of DeliveryRange. In Swift, methods are simply functions that are associated with a type. Just like other members of structs, you can use dot syntax to access a method through a value of its associated type:

let range = DeliveryRange(range: 150, center: Location(coordinateString: "44.9871,-93.2758"))
let customer = Location(coordinateString: "44.9850,-93.2750")
 
range.isInRange(customer) // true!

Structures as Values

The term value has an important meaning when it comes to structs in Swift, and that’s because structs create what are known as value types.

A value type is an object or a piece of data that is copied on assignment, which means the assignment gets an exact copy of the data rather than a reference to the very same data.

// Assign the literal ‘5’ into a, an Int.
var a: Int = 5
 
// Assign the value in a to b.
var b: Int = a
 
print(a) // 5
print(b) // 5
 
// Assign the value ’10’ to a
a = 10
 
// a now has ’10’, b still has ‘5’
print(a) // 10
print(b) // 5

Simple, right! Obvious, even?

Notice that even though a and b have the same value to start, changing the value of a later doesn’t affect b. They’re separate variables with separate values.

How about the same principle, except with the Location struct:

// Build a DeliveryRange value
var range1: DeliveryRange = DeliveryRange(range: 200, center: Location(44.9871,-93.2758))
 
// Assign the value in range1 to range2
var range2: DeliveryRange = range1
 
print(range1.range) // 200
print(range2.range) // 200
 
// Modify the range of range1 to ‘100’
range1.range = 100
 
// range1 now has ’100’, b still has ‘200’
print(range1.range) // 100
print(range2.range) // 200

As with the Int example, range2 didn’t pick up the new value set in range1. The important thing is that this demonstrates the value semantics of working with structs. When you assign range2 the value from range1, it gets an exact copy of the value. That means you can modify range1 without also modifying the range in range2.

Where To Go From Here?

Structs are just one of the named types available to you in Swift, and now that you understand struct basics you’re ready to learn about their reference type counterparts: classes!

If you like what you see, we also cover enums and protocols and So Much More! in the book. These named types are what you’ll use to define the things specific to your apps—people, windows, in-app purchases, and so on—and are an important part of learning Swift.

This post is an excerpt from the Swift Apprentice. Pick up a copy of the book if you’d like to learn more about Swift right from the foundations.

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

The post Swift Tutorial: Introducing Structures appeared first on Ray Wenderlich.

2D iOS & tvOS Games by Tutorials Now Available!

$
0
0

Note from Ray: Happy Wednesday – it’s book release day during the iOS 9 Feast!

Today we are happy to release our brand new book 2D iOS & tvOS Games by Tutorials.

In this book, you will learn how to make iOS and tvOS games in Swift using Apple’s built-in 2D game framework: Sprite Kit. Through a series of mini-games and challenges, you will go from beginner to advanced and learn everything you need to make your own game.

Keep reading to learn more about the history of the book, what’s inside, and how you can get your copy!

History of This Book

2D iOS and tvOS Games by Tutorials Now Available!

Two years ago, we wrote a book called iOS Games by Tutorials, covering how to make 2D games with Sprite Kit. One year later, we released a second edition fully ported to Swift, as a free update for existing customers.

Then this year at WWDC, one of the biggest and most exciting changes announced was the new GameplayKit APIs. These are a set of APIs that make it easy to add pathfinding, AI, and other cool features into your games.

Then there was the elephant in the room – the announcement of tvOS, which now allows us to create games for the living room!

These changes were so significant that rather than trying to give them a token coverage in an update to iOS Games by Tutorials, we decided it would be better to revamp the book completely. Enter 2D iOS & tvOS Games by Tutorials!

2D iOS & tvOS Games by Tutorials teaches you everything you need to know about SpriteKit, GameplayKit, and related APIs like Game Center and ReplayKit. The book contains the classic games Zombie Conga, Cat Nap, and Circuit Racer (with plenty of updates along the way), but also introduces three new games to highlight the power of GameplayKit:

  • Drop Charge: Escape from an exploding alien spaceship, learning about the scene editor, juice, and GamePlayKit state machines along the way!
  • Dino Defense: Protect your village from an onslaught of dinosaurs in this tower defense game with GamePlayKit pathfinding and entity/component system!
  • Delve: Try to find your way through a procedurally-generated dungeon before you are destroyed by hordes of monsters!

This book is not a free update since over half of the book is completely new; it’s closer to a new book than an update. However, I sent a coupon for 50% off to former iOS Games by Tutorials PDF customers to thank you for your support – check your email and enjoy!

What’s Inside

2D iOS & tvOS Games by Tutorials is 29 chapters and 801 pages – yeah, it’s pretty huge :]

The book is split into five sections, moving from beginning to advanced topics. In each section, you will create a complete mini-game, from scratch! The book also includes some bonus chapters at the end that we think you’ll enjoy.

Let’s take a look at what’s inside!

Section I: Getting Started

This section covers the basics of making 2D games with Sprite Kit. These are the most important techniques, the ones you’ll use in almost every game you make. By the time you reach the end of this section, you’ll be ready to make your own simple game.

Zombie Conga

Throughout this section you will create an action game called Zombie Conga, where you take the role of a happy-go-lucky zombie who just wants to party!

You will build this game across seven chapters, in stages:

  1. Chapter 1, Sprites: Get started by adding your first sprites to the game: the background and the zombie.
  2. Chapter 2, Manual Movement: You’ll make the zombie follow your touches around the screen and get a crash-course in basic 2D vector math.
  3. Chapter 3, Actions: You’ll add cats and crazy cat ladies to the game, as well as basic collision detection and gameplay.
  4. Chapter 4, Scenes: You’ll add a main menu to the game, as well as win and lose scenes.
  5. Chapter 5, Camera: You’ll make the game scroll from left to right, and finally, add the conga line itself.
  6. Chapter 6, Labels: You’ll add a label to show the zombie’s lives and the number of cats in his conga line.
  7. Chapter 7, Beginning tvOS: You’ll get Zombie Conga working on tvOS, in just a few simple steps!

Section II: Physics and Nodes

In this section, you will learn how to use the built-in 2D physics engine included with Sprite Kit to create movement as realistic as that in Angry Birds or Cut the Rope. You will also learn how to use special types of nodes that allow you to play videos or create shapes in your game.

Cat Nap

In the process, you will create a physics puzzle game called Cat Nap, where you take the role of a cat who has had a long day and just wants to go to bed.

You will build this game across five chapters, in stages:

  1. Chapter 8, Scene Editor: You’ll begin by creating the first level of the game. By the end, you’ll have a better understanding of Xcode’s level designer, better known as the scene editor.
  2. Chapter 9, Beginning Physics: In this chapter, you’re going to make a little detour in order to learn the basics of creating physics simulations for your games. As a bonus, you’ll learn how to prototype games inside an Xcode playground.
  3. Chapter 10, Intermediate Physics: You’ll learn about physics-based collision detection and create custom classes for your Sprite Kit nodes.
  4. Chapter 11, Advanced Physics: You’ll add two more levels to the game as you learn about interactive bodies, joints between bodies, composed bodies and more.
  5. Chapter 12, Crop, Video and Shape Nodes: You’ll add special new blocks to Cat Nap while learning about additional types of nodes that allow you to do amazing things—like play videos, crop images and create dynamic shapes.
  6. Chapter 13, Intermediate tvOS: In this last chapter you are going to bring Cat Nap to the silver screen. You are going to take the fully developed game and add support for tvOS so the player can relax on their couch and play the game using only the remote.

Section III: Juice

In this section, you’ll also learn how to take a good game and make it great by adding a ton of special effects and excitement – a.k.a. “juice.”

Drop Charge

In the process, you will create a game called Drop Charge, where you’re a space hero with a mission to blow up an alien space ship – and escape with your life before it explodes. To do this, you must jump from platform to platform, collecting special boosts along the way. Just be careful not to fall into the red hot lava!

You will build this game across four chapters, in stages:

  1. Chapter 14, Making Drop Charge: You’ll put together the basic gameplay using the scene editor and code, flexing the Sprite Kit muscles you’ve developed working through previous chapters.
  2. Chapter 15, State Machines: You’ll learn what state machines are and how to use them.
  3. Chapter 16, Particle Systems: You’ll learn how to use particle systems to create amazing special effects.
  4. Chapter 17, Juice Up Your Game: You’ll trick out your game with music, sound, animation, more particles and other special effects, experiencing for yourself the benefits of mastering the details.

Section IV: GameplayKit

In this section, you’ll learn how to use iOS 9’s new GameplayKit to improve your game’s architecture and reusability, along with adding pathfinding and basic game AI.

Dino Defense

In the process, you’ll create a fun tower defense game called Dino Defense where you construct a perfect defense to save your village from an onslaught of angry dinosaurs!

You will build this game across three chapters, in stages:

  1. Chapter 18, Entity-Component System: You’ll learn all about modeling your game’s objects using the new `GKEntity` and `GKComponent` objects provided with GameplayKit, and you’ll use what you’ve learned to implement your first dinosaur and tower.
  2. Chapter 19, Pathfinding: You’ll use GameplayKit’s pathfinding features to move your dinosaurs across the scene, avoiding obstacles and towers.
  3. Chapter 20, Agents, Goals and Behaviors: Finally, you’ll add a second dinosaur to your game that will use a `GKAgent` with `GKGoal` and `GKBehavior` objects to move across the scene as a more organic alternative to pathfinding.

Section V: Advanced Topics

In this section, you’ll delve into some more advanced topics like procedural level generation, GameplayKit randomization, and game controllers.

Delve

In the proces, you’ll create a tile-based dungeon crawler called Delve where you try to guide your miner through a rock-elemental infested dungeon.

You will build this game across four chapters, in stages:

  1. Chapter 21, Tile Map Games: You’ll learn techniques for building tile map levels, including how to create a fully functional tile map game.
  2. Chapter 22, Randomization: Take advantage of the new GameplayKit class `GKRandom` to generate the game world.
  3. Chapter 23, Procedural Levels: Remove some of the random aspects of the level generation to make the process more predictable, but still an adventure into the unknown.
  4. Chapter 24, Game Controllers: This game is perfect for external game controllers; you’ll be adding a tvOS target and exploring how to use the Apple TV remote as a game controller.

Section VI: Bonus Chapters

And that’s not all – on top of the above, we have some bonus chapters for you!

In these bonus chapters, you’ll learn about some APIs other than Sprite Kit that are good to know when making games for iOS. In particular, you will learn how add Game Center leaderboards and achievements into your game, use the new iOS 9 ReplayKit API, and add iAds into your game.

Circuit Racer

In the process, you will integrate these APIs into a top-down racing game called Circuit Racer, where you take the role of an elite racecar driver out to set a world record. It would be no problem if it weren’t for the debris on the track!

You will work with this game across four chapters, in stages:

  1. Chapter 25, Game Center Achievements: Enable Game Center for your game and award the user achievements for accomplishing certain feats.
  2. Chapter 26, Game Center Leaderboards: Set up various leaderboards for your game and track and report the player’s scores.
  3. Chapter 27, ReplayKit: You’ll learn how to allow players to record and share videos of their games with iOS 9’s new ReplayKit.
  4. Chapter 28, iAd: You’ll learn how to integrate iAds into your game so you can have a nice source of revenue!

We have also included a bonus chapter about making your own game art:

  1. Chapter 29, Making Art for Programmers: If you liked the art in these mini-games and want to learn how to either hire an artist or make some art of your own, look no further than this chapter! This chapter guides you through drawing a cute cat in the style of this book with Illustrator.

Where To Go From Here?

Here’s how you can get your copy:

  • If you are an iOS Games by Tutorials Customer: We are offering this book at 50% off this new book to thank you for your support – check your email for a coupon code. If you don’t see it, check your spam or contact us.
  • If you preordered 2D iOS & tvOS Games by Tutorials : You can download the book immediately on your My Loot page.
  • If you don’t have the book yet: What are you waiting for – grab your copy now! :]

With the recent release of tvOS, you couldn’t ask for a better time to start learning how to make games – games feel simply incredible on the big screen and there are tons of new opportunities.

Prepare yourself for your own private tour on making 2D iOS and tvOS Games. Marin, Michael, Toby, Neil, Ali, Rod and I hope you enjoy the book!

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

New Video Tutorial Series: Table Views

$
0
0

During this year’s iOS 9 Feast, we are released new video tutorial series every Thursday.

This week, we are happy to release our 7th and final iOS 9 Feast video tutorial series: a Swift 2 and iOS 9 update to our Table View series!

Table views video tutorial

Before, this series had been Objective-C only. In this update, Brian has updated the series to Swift 2 and iOS 9. The update also makes use of iOS 9 related technologies such as Stack Views.

All 12 parts of the series are available today. You can check them out here:

We hope you have enjoyed all of the new video content we have released during the iOS 9 Feast – 78 videos all told! Thanks to everyone for subscribing and helping support all we do on this site.

The post New Video Tutorial Series: Table Views appeared first on Ray Wenderlich.

Sprite Kit Swift 2 Tutorial for Beginners

$
0
0

Learn how to create a simple 2D iOS game in this Sprite Kit Swift 2 Tutorial!

Note from Ray: This is a Swift 2 and iOS 9 update to a popular tutorial on our site, released as part of the iOS 9 Feast.

Like Batman and Robin or Superman and Lois Lane, Sprite Kit and Swift are an amazing combination:

  • Sprite Kit is one of the best ways to make games on iOS. It’s easy to learn, powerful, and is fully-supported by Apple.
  • Swift is an easy language to get started with, especially if you are a beginner to the iOS platform.

In this tutorial, you will learn how to create a simple 2D game using Apple’s 2D game framework, Sprite Kit – using Swift!

You can either follow along with this tutorial, or just jump straight to the sample project at the end. And yes. There will be ninjas.

Note: This tutorial has a special place in my heart, as the original version was one of the first tutorials ever released on our site. It was written in a completely different language (Objective-C) and a completely different game framework (Cocos2D). My, how times have changed! :]

Sprite Kit vs. Unity

The most popular alternative to Sprite Kit at the moment is a game framework called Unity. Unity was originally developed as a 3D engine, but it recently got full built-in 2D support too.

So before you get started, I recommend you put some thought into whether Sprite Kit or Unity is the best choice for your game.

Advantages of Sprite Kit

  • It’s built right into iOS. There is no need to download extra libraries or have external dependencies. You can also seamlessly use other iOS APIs like iAd, In-App Purchases, etc. without having to rely on extra plugins.
  • It leverages your existing skills. If you already know Swift and iOS development, you can pick up Sprite Kit extremely quickly.
  • It’s written by Apple. This gives you some confidence that it will be well supported moving forward on all of Apple’s new products. For example, you can use the same Sprite Kit code to make your game work on iOS, OS X, and tvOS without a hitch.
  • It’s free. Maybe one of the best reasons for small indies! You get all of Sprite Kit’s functionality at no cost. Unity does have a free version but does not have all of the features of the Pro version (you’ll need to upgrade if you want to avoid the Unity splash screen, for example).

Advantages of Unity

  • Cross-platform. This is one of the big ones. If you use Sprite Kit, you’re locked into the Apple ecosystem. With Unity, you can easily port your games to Android, Windows, and more.
  • Visual scene designer. Unity makes it extremely easy to lay out your levels and test your game in realtime with the click of a button. Sprite Kit does have a very basic scene editor, but it is very basic compared to what Unity offers.
  • Asset store. Unity comes with a built-in asset store where you can buy various components for your game. Some of these components can save you a good bit of development time!
  • More powerful. In general, Unity just has more features and functionality than the Sprite Kit / Scene Kit combination.

Which Should I Choose?

After this a lot of you may be thinking, “Well, which 2D framework should I choose?”

The answer that depends on what your goals are. Here’s my 2c:

  • If you are a complete beginner, or solely focused on the Apple ecosystem: Use Sprite Kit – it’s built in, easy to learn, and will get the job done.
  • If you’re want to be cross-platform, or have a more complicated game: Use Unity – it’s more powerful and flexible.

If you think Unity is for you, check out some of our Unity written tutorials or our new Unity video tutorial series.

Otherwise, keep reading on to get started with Sprite Kit!

Hello, Sprite Kit!

Let’s start by getting a simple Hello World project up and running by using the Sprite Kit Game template that comes built in to Xcode 7.

Start up Xcode, select File\New\Project, choose the iOS\Application\Game template, and click Next:

001_New_Game

Enter SpriteKitSimpleGame for the Product Name, Swift for Language, SpriteKit for Game Technology, iPhone for Devices, and click Next:

002_Options

Choose somewhere on your drive to save the project, and click Create. Select your iPhone 6s simulator, then click the play button to run the project as-is. After a brief splash screen, you should see the following:

003_Hello_World

Sprite Kit is organized into the concept of scenes, which are kind of like “levels’ or “screens” for a game. For example, you might have a scene for the main gameplay area, and another scene for the world map between levels.

If you take a look at your project, you’ll see the template has already created a scene for you by default – GameScene. Open GameScene.swift and you’ll see that it contains some code to put a label on the screen, and add a rotating spaceship when you tap somewhere.

In this tutorial, you’ll mainly be working within GameScene. But before you begin, you have to make a few tweaks because this game needs to run in landscape instead of portrait.

Initial Setup

The template provided to you has two issues. First, it’s set up the game to be Portrait, but you want landscape. Second, it is currently using Sprite Kit’s scene editor, which you don’t need for this tutorial. Let’s fix these issues.

First, open your target setting by clicking your SpriteKitSimpleGame project in the Project Navigator, selecting the SpriteKitSimpleGame target. Then, in the Deployment Info section, uncheck Portrait so only Landscape Left and Landscape Right are checked, as shown below:

004_Landscape

Second, delete GameScene.sks and choose Move to Trash when prompted. This file allows you to lay out sprites and other components of a scene visually, however for this game it’s just easier to create things programmatically, so you don’t need it.

Next, open GameViewController.swift and replace the contents with the following:

import UIKit
import SpriteKit
 
class GameViewController: UIViewController {
 
  override func viewDidLoad() {
    super.viewDidLoad()
    let scene = GameScene(size: view.bounds.size)
    let skView = view as! SKView
    skView.showsFPS = true
    skView.showsNodeCount = true
    skView.ignoresSiblingOrder = true
    scene.scaleMode = .ResizeFill
    skView.presentScene(scene)
  }
 
  override func prefersStatusBarHidden() -> Bool {
    return true
  }
}

GameViewController is a normal UIViewController, except that its root view is a SKView, which is a view that contains a Sprite Kit scene.

Here, you’ve implemented viewDidLoad() to create a new instance of the GameScene on startup, with the same size of the view itself.

That’s it for the initial setup – now let’s get something on the screen!

Adding a Sprite

First, download the resources for this project and drag them into your Xcode project. Make sure that “Copy items into destination group’s folder (if needed)” is checked, and that your SpriteKitSimpleGame target is selected.

Next, open GameScene.swift and replace the contents with the following:

import SpriteKit
 
class GameScene: SKScene {
 
  // 1
  let player = SKSpriteNode(imageNamed: "player")
 
  override func didMoveToView(view: SKView) {
    // 2
    backgroundColor = SKColor.whiteColor()
    // 3
    player.position = CGPoint(x: size.width * 0.1, y: size.height * 0.5)
    // 4
    addChild(player)
  }
}

Let’s go over this step-by-step.

  1. Here you declare a private constant for the player (i.e. the ninja), which is an example of a sprite. As you can see, creating a sprite is easy – simply pass in the name of the image to use.
  2. Setting the background color of a scene in Sprite Kit is as simple as setting the backgroundColor property. Here you set it to white.
  3. You position the sprite to be 10% across vertically, and centered horizontally.
  4. To make the sprite appear on the scene, you must add it as a child of the scene. This is similar to how you make views children of other views.

Build and run, and voila – ladies and gentlemen, the ninja has entered the building!

005_Ninja

Moving Monsters

Next you want to add some monsters into your scene for your ninja to combat. To make things more interesting, you want the monsters to be moving – otherwise there wouldn’t be much of a challenge! So let’s create the monsters slightly off screen to the right, and set up an action for them telling them to move to the left.

Add the following methods to GameScene.swift:

func random() -> CGFloat {
  return CGFloat(Float(arc4random()) / 0xFFFFFFFF)
}
 
func random(min min: CGFloat, max: CGFloat) -> CGFloat {
  return random() * (max - min) + min
}
 
func addMonster() {
 
  // Create sprite
  let monster = SKSpriteNode(imageNamed: "monster")
 
  // Determine where to spawn the monster along the Y axis
  let actualY = random(min: monster.size.height/2, max: size.height - monster.size.height/2)
 
  // Position the monster slightly off-screen along the right edge,
  // and along a random position along the Y axis as calculated above
  monster.position = CGPoint(x: size.width + monster.size.width/2, y: actualY)
 
  // Add the monster to the scene
  addChild(monster)
 
  // Determine speed of the monster
  let actualDuration = random(min: CGFloat(2.0), max: CGFloat(4.0))
 
  // Create the actions
  let actionMove = SKAction.moveTo(CGPoint(x: -monster.size.width/2, y: actualY), duration: NSTimeInterval(actualDuration))
  let actionMoveDone = SKAction.removeFromParent()
  monster.runAction(SKAction.sequence([actionMove, actionMoveDone]))
 
}

I’ve spelled out things in a verbose manner here to make things as easy to understand as possible. The first part should make sense based on what we’ve discussed so far: you do some simple calculations to determine where you want to create the object, set the position of the object, and add it to the scene the same way you did for the player sprite.

The new element here is adding actions. Sprite Kit provides a lot of extremely handy built-in actions that help you easily change the state of sprites over time, such as move actions, rotate actions, fade actions, animation actions, and more. Here you use three actions on the monster:

  • SKAction.moveTo(_:duration:): You use this action to direct the object to move off-screen to the left. Note that you can specify the duration for how long the movement should take, and here you vary the speed randomly from 2-4 seconds.
  • SKAction.removeFromParent(): Sprite Kit comes with a handy action that removes a node from its parent, effectively “deleting it” from the scene. Here you use this action to remove the monster from the scene when it is no longer visible. This is important because otherwise you’d have an endless supply of monsters and would eventually consume all device resources.
  • SKAction.sequence(_:): The sequence action allows you to chain together a sequence of actions that are performed in order, one at a time. This way, you can have the “move to” action perform first, and once it is complete perform the “remove from parent” action.
Note: This code block includes some helper methods to generate a random number within a range using arc4random(). This suffices for our simple random number generation needs in this game, but if you want more advanced functionality, check out the random number APIs in iOS 9’s new GameplayKit.

One last thing before you go. You need to actually call the method to create monsters! And to make things fun, let’s have monsters continuously spawning over time.

Simply add the following code to the end of didMoveToView():

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

Here you run a sequence of actions to call a block of code (you can seamlessly pass in your addMonster() method here thanks to the power of Swift), and then wait for 1 second. You then repeat this sequence of actions endlessly.

That’s it! Build and run the project, now you should see monsters happily moving across the screen:

006_Monsters

Shooting Projectiles

At this point, the ninja is just begging for some action – so let’s add shooting! There are many ways you could implement shooting, but for this game you are going to make it so when the user taps the screen, it shoots a projectile from the player in the direction of the tap.

I want to use a “move to” action to implement this to keep things at a beginner level, but in order to use this you have to do a little math.

This is because the “move to” action requires you to give a destination for the projectile, but you can’t just use the touch point because the touch point represents just the direction to shoot relative to the player. You actually want to keep the bullet moving through the touch point until the bullet goes off-screen.

Here’s a picture that illustrates the matter:

Projectile Triangle

So as you can see, you have a small triangle created by the x and y offset from the origin point to the touch point. You just need to make a big triangle with the same ratio – and you know you want one of the endpoints to be off the screen.

To run these calculations, it really helps if you have some basic vector math routines you can call (like methods to add and subtract vectors). However, Sprite Kit doesn’t have any by default so you’ll have to write your own.

Luckily they are very easy to write thanks to the power of Swift operator overloading. Add these functions to the top of your file, right before the GameScene class:

func + (left: CGPoint, right: CGPoint) -> CGPoint {
  return CGPoint(x: left.x + right.x, y: left.y + right.y)
}
 
func - (left: CGPoint, right: CGPoint) -> CGPoint {
  return CGPoint(x: left.x - right.x, y: left.y - right.y)
}
 
func * (point: CGPoint, scalar: CGFloat) -> CGPoint {
  return CGPoint(x: point.x * scalar, y: point.y * scalar)
}
 
func / (point: CGPoint, scalar: CGFloat) -> CGPoint {
  return CGPoint(x: point.x / scalar, y: point.y / scalar)
}
 
#if !(arch(x86_64) || arch(arm64))
func sqrt(a: CGFloat) -> CGFloat {
  return CGFloat(sqrtf(Float(a)))
}
#endif
 
extension CGPoint {
  func length() -> CGFloat {
    return sqrt(x*x + y*y)
  }
 
  func normalized() -> CGPoint {
    return self / length()
  }
}

These are standard implementations of some vector math functions. If you’re confused about what’s going on here or are new to vector math, check out this quick vector math explanation.

Next, add a new method to the file:

override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
 
  // 1 - Choose one of the touches to work with
  guard let touch = touches.first else {
    return
  }
  let touchLocation = touch.locationInNode(self)
 
  // 2 - Set up initial location of projectile
  let projectile = SKSpriteNode(imageNamed: "projectile")
  projectile.position = player.position
 
  // 3 - Determine offset of location to projectile
  let offset = touchLocation - projectile.position
 
  // 4 - Bail out if you are shooting down or backwards
  if (offset.x < 0) { return }
 
  // 5 - OK to add now - you've double checked position
  addChild(projectile)
 
  // 6 - Get the direction of where to shoot
  let direction = offset.normalized()
 
  // 7 - Make it shoot far enough to be guaranteed off screen
  let shootAmount = direction * 1000
 
  // 8 - Add the shoot amount to the current position
  let realDest = shootAmount + projectile.position
 
  // 9 - Create the actions
  let actionMove = SKAction.moveTo(realDest, duration: 2.0)
  let actionMoveDone = SKAction.removeFromParent()
  projectile.runAction(SKAction.sequence([actionMove, actionMoveDone]))
 
}

There’s a lot going on here, so let’s review it step by step.

  1. One of the cool things about SpriteKit is that it includes a category on UITouch with locationInNode(_:) and previousLocationInNode(_:) methods. These let you find the coordinate of a touch within a SKNode’s coordinate system. In this case, you use it to find out where the touch is within the scene’s coordinate system.
  2. You then create a projectile and place it where the player is to start. Note you don’t add it to the scene yet, because you have to do some sanity checking first – this game does not allow the ninja to shoot backwards.
  3. You then subtract the projectile’s current position from the touch location to get a vector from the current position to the touch location.
  4. If the X value is less than 0, this means the player is trying to shoot backwards. This is is not allowed in this game (real ninjas don’t look back!), so just return.
  5. Otherwise, it’s OK to add the projectile to the scene.
  6. Convert the offset into a unit vector (of length 1) by calling normalized(). This will make it easy to make a vector with a fixed length in the same direction, because 1 * length = length.
  7. Multiply the unit vector in the direction you want to shoot in by 1000. Why 1000? It will definitely be long enough to go past the edge of the screen :]
  8. Add the shoot amount to the current position to get where it should end up on the screen.
  9. Finally, create moveTo(_:, duration:) and removeFromParent() actions like you did earlier for the monster.

Build and run, and now your ninja should be able to fire away at the oncoming hordes!

007_Shoot

Collision Detection and Physics: Overview

So now you have shurikens flying everywhere – but what your ninja really wants to do is to lay some smack down. So let’s add in some code to detect when your projectiles intersect your targets.

One of the nice things about Sprite Kit is it comes with a physics engine built right in! Not only are physics engines great for simulating realistic movement, but they are also great for collision detection purposes.

Let’s set up the game to use Sprite Kit’s physics engine to determine when monsters and projectiles collide. At a high level, here’s what you’re going to do:

  • Set up the physics world. A physics world is the simulation space for running physics calculations. One is set up on the scene by default, and you might want to configure a few properties on it, like gravity.
  • Create physics bodies for each sprite. In Sprite Kit, you can associate a shape to each sprite for collision detection purposes, and set certain properties on it. This is called a physics body. Note that the physics body does not have to be the exact same shape as the sprite. Usually it’s a simpler, approximate shape rather than pixel-perfect, since that is good enough for most games and performant.
  • Set a category for each type of sprite. One of the properties you can set on a physics body is a category, which is a bitmask indicating the group (or groups) it belongs to. In this game, you’re going to have two categories – one for projectiles, and one for monsters. Then later when two physics bodies collide, you can easily tell what kind of sprite you’re dealing with by looking at its category.
  • Set a contact delegate. Remember that physics world from earlier? Well, you can set a contact delegate on it to be notified when two physics bodies collide. There you’ll write some code to examine the categories of the objects, and if they’re the monster and projectile, you’ll make them go boom!

Now that you understand the battle plan, it’s time to put it into action!

Collision Detection and Physics: Implementation

Start by adding this struct to the top of GameScene.swift:

struct PhysicsCategory {
  static let None      : UInt32 = 0
  static let All       : UInt32 = UInt32.max
  static let Monster   : UInt32 = 0b1       // 1
  static let Projectile: UInt32 = 0b10      // 2
}

This is setting up the constants for the physics categories you’ll need in a bit – no pun intended! :]

Note: You may be wondering what the fancy syntax is here. Note that the category on Sprite Kit is just a single 32-bit integer, and acts as a bitmask. This is a fancy way of saying each of the 32-bits in the integer represents a single category (and hence you can have 32 categories max). Here you’re setting the first bit to indicate a monster, the next bit over to represent a projectile, and so on.

Next, mark GameScene as implementing the SKPhysicsContactDelegate protocol:

class GameScene: SKScene, SKPhysicsContactDelegate {

Then inside didMoveToView(_:) add these lines after adding the player to the scene:

physicsWorld.gravity = CGVectorMake(0, 0)
physicsWorld.contactDelegate = self

This sets up the physics world to have no gravity, and sets the scene as the delegate to be notified when two physics bodies collide.

Inside the addMonster() method, add these lines right after creating the monster sprite:

monster.physicsBody = SKPhysicsBody(rectangleOfSize: monster.size) // 1
monster.physicsBody?.dynamic = true // 2
monster.physicsBody?.categoryBitMask = PhysicsCategory.Monster // 3
monster.physicsBody?.contactTestBitMask = PhysicsCategory.Projectile // 4
monster.physicsBody?.collisionBitMask = PhysicsCategory.None // 5

Let’s go over what this does line by line.

  1. Creates a physics body for the sprite. In this case, the body is defined as a rectangle of the same size of the sprite, because that’s a decent approximation for the monster.
  2. Sets the sprite to be dynamic. This means that the physics engine will not control the movement of the monster – you will through the code you’ve already written (using move actions).
  3. Sets the category bit mask to be the monsterCategory you defined earlier.
  4. The contactTestBitMask indicates what categories of objects this object should notify the contact listener when they intersect. You choose projectiles here.
  5. The collisionBitMask indicates what categories of objects this object that the physics engine handle contact responses to (i.e. bounce off of). You don’t want the monster and projectile to bounce off each other – it’s OK for them to go right through each other in this game – so you set this to 0.

Next add some similar code to touchesEnded(_:withEvent:), right after the line setting the projectile’s position:

projectile.physicsBody = SKPhysicsBody(circleOfRadius: projectile.size.width/2)
projectile.physicsBody?.dynamic = true
projectile.physicsBody?.categoryBitMask = PhysicsCategory.Projectile
projectile.physicsBody?.contactTestBitMask = PhysicsCategory.Monster
projectile.physicsBody?.collisionBitMask = PhysicsCategory.None
projectile.physicsBody?.usesPreciseCollisionDetection = true

As a test, see if you can understand each line here and what it does. If not, just refer back to the points explained above!

As a second test, see if you can spot two differences. Answer below!

Solution Inside: What Are the Differences? SelectShow>

Next, add a method that will be called when the projectile collides with the monster. Note that nothing calls this automatically, you will be calling this later.

func projectileDidCollideWithMonster(projectile:SKSpriteNode, monster:SKSpriteNode) {
  print("Hit")
  projectile.removeFromParent()
  monster.removeFromParent()
}

All you do here is remove the projectile and monster from the scene when they collide. Pretty simple, eh?

Now it’s time to implement the contact delegate method. Add the following new method to the file:

func didBeginContact(contact: SKPhysicsContact) {
 
  // 1
  var firstBody: SKPhysicsBody
  var secondBody: SKPhysicsBody
  if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
    firstBody = contact.bodyA
    secondBody = contact.bodyB
  } else {
    firstBody = contact.bodyB
    secondBody = contact.bodyA
  }
 
  // 2
  if ((firstBody.categoryBitMask & PhysicsCategory.Monster != 0) &&
      (secondBody.categoryBitMask & PhysicsCategory.Projectile != 0)) {
    projectileDidCollideWithMonster(firstBody.node as! SKSpriteNode, monster: secondBody.node as! SKSpriteNode)
  }
 
}

Since you set the scene as the contactDelegate of the physics world earlier, this method will be called whenever two physics bodies collide (and their contactTestBitMasks are set appropriately).

There are two parts to this method:

  1. This method passes you the two bodies that collide, but does not guarantee that they are passed in any particular order. So this bit of code just arranges them so they are sorted by their category bit masks so you can make some assumptions later.
  2. Finally, it checks to see if the two bodies that collide are the projectile and monster, and if so calls the method you wrote earlier.

Give it a build and run, and now when your projectiles intersect targets they should disappear!

Finishing Touches

You’re pretty close to having a workable (but extremely simple) game now. You just need to add some sound effects and music (since what kind of game doesn’t have sound!) and some simple game logic.

You already have some cool background music I made and an awesome pew-pew sound effect in your project, from the resources for this tutorial you added to your project earlier. You just need to play them!

To do this, add these line to the end of didMoveToView(_:):

let backgroundMusic = SKAudioNode(fileNamed: "background-music-aac.caf")
backgroundMusic.autoplayLooped = true
addChild(backgroundMusic)

This uses SKAudioNode, a new class introduced in iOS 9, to play and loop the background music for your game.

As for the sound effect, add this line to the top of touchesEnded(_:withEvent:):

runAction(SKAction.playSoundFileNamed("pew-pew-lei.caf", waitForCompletion: false))

Pretty handy, eh? You can play a sound effect with one line!

Build and run, and enjoy your groovy tunes!

Note: If you don’t hear the background music, try running on a device instead of the simulator.

Game Over, Man!

Now, let’s create a new scene that will serve as your “You Win” or “You Lose” indicator. Create a new file with the iOS\Source\Swift File template, name the file GameOverScene and click Create.

Then replace GameOverScene.swift with the following:

import Foundation
import SpriteKit
 
class GameOverScene: SKScene {
 
  init(size: CGSize, won:Bool) {
 
    super.init(size: size)
 
    // 1
    backgroundColor = SKColor.whiteColor()
 
    // 2
    let message = won ? "You Won!" : "You Lose :["
 
    // 3
    let label = SKLabelNode(fontNamed: "Chalkduster")
    label.text = message
    label.fontSize = 40
    label.fontColor = SKColor.blackColor()
    label.position = CGPoint(x: size.width/2, y: size.height/2)
    addChild(label)
 
    // 4
    runAction(SKAction.sequence([
      SKAction.waitForDuration(3.0),
      SKAction.runBlock() {
        // 5
        let reveal = SKTransition.flipHorizontalWithDuration(0.5)
        let scene = GameScene(size: size)
        self.view?.presentScene(scene, transition:reveal)
      }
    ]))
 
  }
 
  // 6
  required init(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
  }
}

There are five parts to point out here

  1. Sets the background color to white, same as you did for the main scene.
  2. Based on the won parameter, sets the message to either “You Won” or “You Lose”.
  3. This is how you display a label of text to the screen with Sprite Kit. As you can see, it’s pretty easy – you just choose your font and set a few parameters.
  4. Finally, this sets up and runs a sequence of two actions. I’ve included them all inline here to show you how handy that is (instead of having to make separate variables for each action). First it waits for 3 seconds, then it uses the runBlock action to run some arbitrary code.
  5. This is how you transition to a new scene in Sprite Kit. First you can pick from a variety of different animated transitions for how you want the scenes to display – you choose a flip transition here that takes 0.5 seconds. Then you create the scene you want to display, and use the presentScene(_:transition:) method on the self.view property.
  6. If you override an initializer on a scene, you must implement the required init(coder:) initializer as well. However this initializer will never be called, so you just add a dummy implementation with a fatalError(_:) for now.

So far so good, now you just need to set up your main scene to load the game over scene when appropriate.

Switch back to GameScene.swift, and inside addMonster(), replace the last line that runs the actions on the monster with the following:

let loseAction = SKAction.runBlock() {
  let reveal = SKTransition.flipHorizontalWithDuration(0.5)
  let gameOverScene = GameOverScene(size: self.size, won: false)
  self.view?.presentScene(gameOverScene, transition: reveal)
}
monster.runAction(SKAction.sequence([actionMove, loseAction, actionMoveDone]))

This creates a new “lose action” that displays the game over scene when a monster goes off-screen. See if you understand each line here, if not refer to the explanation for the previous code block.

Also, another pop-quiz for you: why do you run the loseAction before actionMoveDone? Try reversing them to see what happens if you don’t know.

Solution Inside: Why is Lose Action First? SelectShow>

Now you should handle the win case too – don’t be cruel to your players! :] Add a new property to the top of GameScene, right after the declaration of player:

var monstersDestroyed = 0

And add this to the bottom of projectile(_:didCollideWithMonster:):

monstersDestroyed++
if (monstersDestroyed > 30) {
  let reveal = SKTransition.flipHorizontalWithDuration(0.5)
  let gameOverScene = GameOverScene(size: self.size, won: true)
  self.view?.presentScene(gameOverScene, transition: reveal)
}

Go ahead and give it a build and run, and you should now have win and lose conditions and see a game over scene when appropriate!

008_YouWin

Where To Go From Here?

And that’s a wrap! Here is the full source code for this Sprite Kit Swift Tutorial for beginners.

I hope you enjoyed learning about Sprite Kit and are inspired to make your own game!

If you want to learn more about Sprite Kit, you should check out our book 2D iOS & tvOS Games by Tutorials:

In this book we’ll teach you everything you need to know to make great games for iOS & tvOS – from physics, to tile maps, to particle systems, and even how to make your games “juicy” with polish and special effects.

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

The post Sprite Kit Swift 2 Tutorial for Beginners appeared first on Ray Wenderlich.

Introduction to the Sprite Kit Scene Editor

$
0
0
Note: This is a brand new tutorial released as part of the iOS 9 Feast. Enjoy!
Run, run, run!

Run, run, run!

Does the tedious task of manually positioning everything in your game’s levels via code make you think you’ll break out in hives?

Worry no more – creating levels can be easy, fun and done with almost no contact with code. In this tutorial, you’ll learn just how to do just that using the powerful Sprite Kit scene editor.

In this Sprite Kit scene editor tutorial, you’ll create a fancy level for a spooky 2D zombie game named Fear the Dead. In the process, you’ll learn:

  • What the scene editor is, how to navigate its layout and how you can add sprites to it.
  • How you can use file references to reuse an SKScene.
  • How to create a dark vibe using an SKLightNode.
  • How to work with the new iOS 9 SKCameraNode.
  • How to use the Action Editor to add animations to nodes without any code.
  • How to use SKAudioNodes to create positional audio.
  • How to survive a zombie apocalypse. :]

As you can see we have a lot to cover, so let’s get started!

Note: This Sprite Kit scene editor tutorial assumes that you already know the basics of Swift as well as the basics of the Sprite Kit. If you’re new to Swift, check out the Swift Apprentice book series, and if you’re new to Sprite Kit, check out the Sprite Kit Swift 2 Tutorial for Beginners tutorial.

Alright, let's do this.

Getting Started

In order to get you up and running without a bunch of noise, download the starter project for this tutorial here. It’s based on the SpriteKit Game template and already has some of the more tedious work done for you.

This way you can focus on creating an awesome zombie-rich environment level without tinkering with all the underlying logic. The starter project comes with:

  • The logic needed for actually playing the game, like the logic for moving around the player and the zombies, as well as logic for when these collide.
  • All the sounds and images you need.
  • A MenuScene.swift that denotes the end of a game and also gives the option to restart the game.

Once you’ve downloaded and unzipped the project, open it in Xcode and build and run. After the splash screen intro, you should see the following appear on your device or in the simulator:

SKSE-image2

As you can see, there’s not much to play with yet, so let’s get started with the scene editor, shall we?

Getting Started with the Scene Editor

First, a bit about the game you’re building. Fear the Dead leads you on a nail-biting adventure where you have to escape from one room into another without being bitten by infected, nasty zombies. For a full-blown game, there would be tons of exciting levels.

Creating levels in code, however, can be very tedious and cumbersome, and could lead you to become one of the zombies you’re trying to escape. This is where the scene editor, a built-in Xcode tool designed to help you build levels without having to write everything in code, comes in.

Setting up the Scene

If you look in the project navigator you should see the file GameScene.sks. Select this file and you’ll see a new editor panel that shows a gray background as shown in the screenshot below:

SKSE-image3

Now, click the button in the lower mid-right corner until you see a yellow rectangle appear. It serves as the boundary of your scene and all of your level’s components will be placed within. Alternatively, you can also pinch your trackpad to zoom in and out. You should now have a view similar to:

SKSE-image4

When creating a new scene, the default scene size is 1024 x 768 pixels, but you want your level to be a bit bigger. First, make sure you have the utilities editor open on the right-hand side, and select the Attributes Inspector.

If you do not see the utilities editor, simply click View\Utilities\Show Attributes Inspector and it should show itself. Next, change the dimensions of the scene to be 1080 x 1920.

SKSE-image5

Awesome! The scene is now ready for some components, so now you get to move on to looking at what you can actually add.

The Object Library

SKSE-image6

First, at the bottom of the utilities editor, select the Object Library.

The Object Library displays all the different objects you can drop onto your scene and configure. In this tutorial you’ll be working primarily with Color Sprites, but there many other objects to choose from, including:

  • Shape Node: a special type of node that allows you to easily draw squares, circles and other shapes.
  • Label: surely you’ve used a label in your games before, and this one is no different. However, this time you’ll be able to easily place it on the screen and edit it with a few clicks.
  • Light: A very cool object you can add is a light, and by placing one on your scene you get a spotlight effect and have the option of making your other objects cast shadows. You’ll add a light later in the tutorial. :]

If you’ve used a SKSpriteNode or few in other games, then you’ll already be familiar with the configuration options that come with a Color Sprite. You can determine the node’s size, position, texture and even add a physics body to it.

Here’s the best part: No longer will you have to manage these in code nor re-run your program every few seconds to make sure everything is placed correctly. Quite neat, right?

Adding a Player Sprite

So how about you add a sprite to the scene?

First, drag and drop a Color Sprite onto the scene. You’ll notice that the sprite is selected by default and that a ton of properties are shown in the Attributes Inspector to the right.

Most of these properties should be recognizable. You can set the sprite’s name, position and anchor point, its parent node and the image file you want to use as the texture.

SKSE-image7

Make this sprite your player by adding the following properties:

  1. Change the sprite’s name to player
  2. Set its size to 75 x 75
  3. Set the texture to character
  4. Set its position by setting x to 200 and y to 1400

But wait! There’s more. If you look further down the Attributes Inspector, you’ll notice a section called Physics Definition where you can set the body type of your sprite. That way you do not have to define it in code. Awesome, right? 

When it comes to body type, you have three different options to choose from:

  1. Bounding rectangle: This sets the body be the exact size of the node.
  2. Bounding circle: This sets the body be a circle with a diameter the size of the node’s longest side.
  3. Alpha mask: This makes Sprite Kit define the physical shape of your node based on the outline of the sprite’s texture image – unless you’re working with rectangles and/or circles, this is the most accurate one of the three.

SKSE-image8

Generally, you want to choose the simplest possible shape to get the desired accuracy you need for your game, as the more complicated the shape the higher the performance cost. For this game, you want collisions to be very accurate (after all, it’s hard enough to survive a zombie apocalypse), so you will choose alpha mask.

With the player node selected in the scene, click the Body Type menu and select Alpha mask. Next, uncheck Allows Rotation and Affected By Gravity as neither are needed for this tutorial. Finally, change the Category Mask to 1.

Note: The category mask will come into play later to detect contacts between the player and other nodes.

As previously mentioned, Fear the Dead will also use lighting to create a spooky feel. To ensure that the game is ready for this, set the Lighting Mask, Shadow Cast Mask and Shadowed Mask of the player to be 1.

SKSE-image9

One last thing before you build and run. Open GameScene.swift and add the following lines to didMoveToView(_:), right after the contact delegate has been set:

// Setup player
player = self.childNodeWithName("player") as? SKSpriteNode

With this simple line of code you have hooked up the player sprite from the scene editor to the actual code inside GameScene.swift. This works because you set the name of the sprite to “player” inside the Scene Editor earlier.

Easy, right? Build and run the game and you should now be able to move the player around by touching the screen. Oh yeah, progress!

SKSE-image10

Adding Zombie Sprites

Now that you know how to add a sprite it’s time to practice by adding some brain-hungry zombies to the mix! In this level, you’ll add five zombie sprites. Every zombie sprite will have a unique position but all will have the following properties:

Note: A time-saving trick is to set this up for one zombie, then duplicate the zombie with Command-D and change the position appropriately.
  • Name: zombie
  • Texture: zombie
  • Size: 50 x 50
  • Lighting, Shadow Cast and Shadowed Mask: 1
  • Body Type: Alpha mask
  • Allows Rotation & Affected By Gravity: Disabled
  • Category Mask: 2
  • Contact Mask: 1

Now, add five zombie sprites with the following positions using the above properties.

  • 1: (900, 1800)
  • 2: (200, 800)
  • 3: (900, 1100)
  • 4: (150, 150)
  • 5: (950, 550)

Done? Awesome! Your game scene should now look like this:

SKSE-image12

So, there is a little more coding to do. You didn’t actually think that you could get out of a tutorial with zero coding, did you?

Just like you did with the player, you need to add a few lines of code before these zombies will operate with the rest of the game. Open GameScene.swift, and add the following lines to didMoveToView(_:) right after the line where you set up the player:

// Setup zombies
for child in self.children {
  if child.name == "zombie" {
    if let child = child as? SKSpriteNode {
      zombies.append(child)
    }
  }
}

These lines will find every child node with the name zombie and add them to an array of zombies – that sounds truly terrifying! This array will eventually move the zombies around the screen. 

Build and run the game and the zombies should now be chasing you. Yikes! Hope you’ve been keeping up on your cardio.

SKSE-image13

Adding a Goal, Walls and a Background

All this running about is tiresome, and the zombies have you trapped. Your player might as well be the main course at a buffet as far as they are concerned.

It would be great to have a way to complete the level, don’t you think?

Go ahead and add a goal to the lower-right corner. Select a Color Sprite from the Object Library and drop it on the scene. Then add the following properties to the sprite:

  • Name: goal
  • Texture: goal
  • Size: 50 x 170
  • Position: x: 1055, y: 135
  • Lighting, Shadow Cast, and Shadowed Mask: 1
  • Body Type: Bounding rectangle
  • Dynamic, Allows Rotation & Affected By Gravity: Disabled
  • Category Mask: 3
  • Contact Mask: 1

Just like before, you need to use this sprite in your code. Open GameScene.swift, and add the following lines to didMoveToView(_:) right after the lines where you set up the zombies:

// Setup goal
goal = self.childNodeWithName("goal") as? SKSpriteNode

Your game scene should now look like this:

SKSE-image14

When running the game, it’s hard to tell where the boundaries of the level are. In order to fix this you’ll need some walls around your level, in fact, you’ll need four walls with the following properties:

  • Lighting, Shadow Cast, and Shadowed Mask: 1
  • Body Type: bounding rectangle
  • Dynamic, Allows Rotation & Affected By Gravity: disabled

Add the four walls using the above and customize them with these properties:

Wall 1:

  • Texture: wall_50x1920
  • Position: (25, 960)
  • Size: 50 x 1920

Wall 2:

  • Texture: wall_50x1700
  • Position: (1055, 1070)
  • Size: 50 x 1700

Wall 3:

  • Texture: wall_1080x50
  • Position: (540, 1895)
  • Size: 1080 x 50

Wall 4:

  • Texture: wall_1080x50
  • Position: (540, 25)
  • Size: 1080 x 50

Good job! Your game scene should now look as follows:

SKSE-image15

Last, but not least, add a background to the game scene. Select a Color Sprite from the Object Library and drop it on the scene. Add the following properties to the sprite:

  • Texture: background
  • Size: 1080 x 1920
  • Position: (540, 960)
  • Lighting Mask: 1
  • Z-position: -1 (This layers the background behind all other nodes.)

Build and run the game. As you run around the level the walls should keep you in place – see if you can get to the goal before the zombies get to you.

SKSE-image16

Camera Positioning with SKCameraNode

Being able to view the whole level at once isn’t really the best experience. The player and the zombies look too small, and the game feels a bit too predictable. To fix this, you’ll just need to implement a camera node.

In iOS 9, Apple introduced a new class called SKCameraNode, which is an object used to specify a position in the scene from which it can render. Because the camera is a node, it can be moved just like any other node in the scene using actions, physics and so on. When a scene renders with a camera node, two things happen:

  1. The scene renders so that the origin of the camera node is placed directly in the middle of the scene.
  2. The inverse of the camera node’s xScale, yScale and zRotation properties are applied to all nodes in the scene.

What this means is that if, for example, the camera is moved 20 pixels to the right, then the scene is rendered as if everything else moved 20 pixels to the left.

Note: For a more in-depth description of the camera node, watch the WWDC 2015 talk What’s New in Sprite Kit. At about three minutes, you meet the SKCameraNode.

Adding a Camera to the Scene

So now you might be wondering if – possibly even dreading – the camera node is something you’ll have to create programmatically. The answer is, as you might expect, that you can create it using the scene editor. Whew!

Go to the Object Library, and locate the Camera node. Next, drag and drop it onto the scene on top of the player; it doesn’t have to be exactly on top as the camera’s position is updated in code. Open the Attributes Inspector, and change its name to be equal to camera and its scale to be equal to x = 0.5, y = 0.5, which is a quarter of the level’s total area).

SKSE-image18

If you were to run the game right now, the camera would not yet be activated because you need to tell the game scene to use the camera node as its camera.

Click outside the level’s boundary, and set its Camera property to be equal to the camera node you just created.

SKSE-image19

With this done, the camera should work as expected. Good job! Build and run the game and you should now only see a fourth of the level at any given time. The camera should also follow the player as you move it around.

SKSE-image20

File References

The scene editor allows you to reference content between different .sks (scene) files, meaning you can put together a bunch of sprites in a single scene file and then reference the file from another scene file.

You might wonder why you would need more than one scene, and there a couple of reasons:

  1. You can reuse the same collection of sprites in multiple different scenes, meaning you don’t have to recreate them over and over again.
  2. If you need to change the referenced content in all of your scenes, all you have to do is edit the original scene and the content automatically updates in every scene that references it. Smart, right?

Creating a Wall Scene

And now that you’ve read about it, you get to create some reusable components. For your game, it would be nice if you could add some walls, so kick off this part by adding a wall scene.

In the Project Navigator to the right, right-click the Scenes folder and from the pop-up menu, click New File…. Choose the iOS/Resource/SpriteKit Scene file template, and then click Next. Call the new file Wall.sks, and save it in the project’s folder.

Xcode automatically opens the newly created Wall.sks file and presents you with an empty editor window. In exactly the same way as before, your task is to resize the scene to your needs and add some sprites. Set the scene size to be 50 x 400 pixels.

Next, select a Color Sprite from the Object Library, drop it onto the scene and add the following properties to it:

  • Texture: wall_50x400
  • Position: (25, 200)
  • Size: 50 x 400
  • Lighting, Shadow Cast, and Shadowed Mask: 1
  • Body Type: Bounding rectangle
  • Dynamic, Allows Rotation, Affected By Gravity: Unchecked

That’s it – you now have a reusable wall!

SKSE-image21

Creating a Room Scene

SKSE-image22

Now that you have a reusable wall, you have the building blocks to create a new reusable room scene. Just like before, right-click the Scenes folder and select New File…. Choose the SpriteKit Scene file template, click Next, name the new file Room.sks and save it in the project’s folder. Next, set the scene’s size to be 400 x 400 pixels.

Now, instead of selecting Color Sprite, select a Reference from the Object Library. Drag and drop three reference objects onto the scene and give them the following properties:

Wall 1:

  • Reference: Wall.sks – this is the .sks file you’re referencing
  • Position: (0, 0)

Wall 2:

  • Reference: Wall.sks
  • Position: (350, 0)

Wall 3:

  • Reference: Wall.sks
  • Rotation: 270
  • Position: (0, 50)

With this in place your room should look as follows:

SKSE-image23

Note: It may be you don’t see the wall tiles appear in Room.sks. This appears to be a bug with the current version of the Sprite Kit scene editor. Don’t worry – it will show up OK in the game itself!

Adding Rooms and Walls to the level

Go back to the GameScene.sks file and add a Reference object from the Object Library for each of the following:

Rooms (Reference / Position)

  1. Room.sks / (0, 1250)
  2. Room.sks / (680, 1250)
  3. Room.sks / (0, 650)

Walls (Reference / Position / Rotation)

  1. Wall.sks / (750, 1000) / 90
  2. Wall.sks / (1080, 650) / 90
  3. Wall.sks / (1080, 350) / 90
  4. Wall.sks / (350, 0) / 0

That was quite the task, but with these fancy reference objects added your amazing level should look like this:

SKSE-image24

Build and run the game to see if you can complete your newly created level. It’s harder than it looks…

SKSE-image25

Positional Audio using SKAudioNode

In iOS 9, Apple added a cool new feature to the Sprite Kit framework. It added what’s known as an SKAudioNode to allow you to add positional sound right in your Sprite Kit game.

Best of all, it’s super simple to set up.

All you have to do is specify the sound asset that should play back, as well as the node that will be the listener for positional audio coming from SKAudioNodes. With these in place, Sprite Kit automatically takes care of the rest, ensuring immersive, positional audio in your game.

Note: For a more in-depth description of the positional audio feature, watch the WWDC 2015 talk What’s New in SpriteKit. The SKAudioNode is introduced about five minutes in.

A quiet zombie just isn’t right, so let’s add some sound to make them more, um, undead-like. First, open the GameScene.swift file, locate the didMoveToView(_:) method, and add the following line underneath the setup of the player:

self.listener = player

This sets the player as the node listening for positional audio.

Next, directly underneath, change the for-loop for adding zombies so that it looks like this:

for child in self.children {
  if child.name == "zombie" {
    if let child = child as? SKSpriteNode {
      // Add SKAudioNode to zombie
      let audioNode: SKAudioNode = SKAudioNode(fileNamed: "fear_moan.wav")
      child.addChild(audioNode)
 
      zombies.append(child)
    }
  }
}

Here you first create an audio node with the file named fear_moan.wav, and then add it to the individual zombie. This ensures that the moaning sound comes from the zombie and only the zombie itself.

Before running your code, try adding an audio node with the scene editor. Select GameScene.sks, open the Object Library and locate the Audio object. Drag and drop the object on top of the player and set its Filename to be fear_bg.mp3 and its parent to be player.

Easy, right?

SKSE-image26

Build and run the game, and you should be able to hear the zombies moaning and the background music. You should notice the zombie’s audio becoming richer, more centered and louder as it nears the player, which is the listener, and more one-sided and distant as it moves away.

For a more immersive feel, try wearing headphones.

Note: If you don’t hear the sounds, try letting the zombies get to you – they’re famished after all this running around. Truth be told, there’s an unknown bug that causes Sprite Kit to sometimes ignore the audio on launch.

Animations and Action-References

Wouldn’t it be cool if you could also add actions to nodes without having to write it all in code? Well, in Xcode 7 and later, you can! Apple added the Action Editor View so you can now drag and drop actions from the Object Library.

To open the Action Editor View, open GameScene.sks and find the arrow pointing upwards at the bottom of the Xcode window:

SKSE-image28

The action editor displays all the nodes in the scene and a timeline with rows that correspond to each node. If you’ve ever worked with animation or video software, you might be familiar with this user interface. You’re going to use the action editor to create a nifty zoom-out effect when you first launch the game.

Grab a Scale Action object from the Object Library and drop it onto the timeline track for the camera node. Next, locate the Attributes Inspector for the action up in the upper-right corner, and change the properties as follows:

  • Start time: 0.3
  • Duration: 1.5
  • Timing Function: Ease in, Ease out
  • Scale Amount: 5

SKSE-image29

With this action, you scale the camera by a factor of five, but you don’t want to change the scene-to-camera ratio you previously defined. Therefore, click the camera node in the scene and change it’s scale to be X = 0.1, Y = 0.1. After the action has been triggered, this will end up being 0.5, just like it was before.

Build and run the game, and you should see a cool zoom-out effect happening at launch.

Creating a Dark Vibe using SKLightNodes

Now, it was stated in the beginning that the game needed a spooky feel and so far it’s not very spooky. Change this by adding an SKLightNode to the player.

Because lights are nodes, you can move them or set them to perform actions. This means that if you add a light node to the player, it’ll follow the player around as it moves through the level – just the effect needed here.

The light node itself is invisible except for the effects you configure on the sprite nodes to interact with them.

Ah-ha!!! So that’s why I’ve had you setting the lighting, shadow cast and shadowed mask on all sprites throughout this tutorial. Each property has a different effect:

  • Lighting Mask: The sprite is illuminated by the light with specular, diffuse and ambient lighting.
  • Shadow Cast Mask: Whenever a sprite intersects with a light, a shadow projects past the sprite.
  • Shadowed Mask: If the sprite is inside a shadow cast by a light, and the sprite has a lower z position than the light, the shadow affects how the sprite is lit.

Time to light it up!

In GameScene.sks, locate the Light object from the Object Library and drop it on top of the player sprite’s torch. Next, change the light’s parent node to be equal to player and change its Falloff to be equal to 2.

The Falloff denotes the exponent for the rate of decay of the light source, so the higher the number, the spookier and darker the level.

SKSE-image30

One more thing before you’re done: The outside of the level is still a very non-spooky gray color. To fix this, select the scene by clicking outside the boundaries of the level, and change its Color to Black.

That’s it! Now you’ve created a terrifying place where zombies run wild. Build and run the game, and you should see the following:

SKSE-image31

Note: At the time of writing, the iOS Simulator is having a hard time running the game without lag after implementing the light. I’d suggest running it on a device, where it shouldn’t cause any problems, or simply disable the light while you build your level.

Where To Go From Here?

Very well done! You’ve made it to the end of this tutorial and have now built a complete level for Fear the Dead. You have learned a ton of cool new features that you’ll be able to implement in your own projects going forward. You can download the final project here.

One of the best ways to make sure you remember what you’ve learned is to apply it in practice. For that reason, you should try and create another level or maybe even build your own game full of increasingly challenging levels.

We love seeing what you guys come up with, so make sure to share your creations in the comments below or on the forums.

If you want to learn more about Sprite Kit, you should check out our book 2D iOS & tvOS Games by Tutorials:

In this book we’ll teach you everything you need to know to make great games for iOS & tvOS – from physics, to tile maps, to particle systems, and even how to make your games “juicy” with polish and special effects.

Enjoy playing your new game; I look forward to hearing from you with comments below or questions on the forums. :]

The post Introduction to the Sprite Kit Scene Editor appeared first on Ray Wenderlich.

Viewing all 4366 articles
Browse latest View live


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