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

iOS Apprentice Updated for Xcode 6.3 and Swift 1.2

$
0
0

iA_Thumb

Good news – Matthijs Hollemans has updated The iOS Apprentice for Xcode 6.3 and Swift 1.2!

As you may know, Swift 1.2 introduced some new syntax, such as an improved if let statement, and revised usage of as vs as! vs as?. To learn more about these changes, check out our What’s New in Swift 1.2 overview.

In this update, Matthijs has updated all chapters and sample code to use the new Swift 1.2 syntax, and has also fixed some of the errata reported on the forums.

Here’s how you can get the update:

  • If you’re an iOS Apprentice PDF customer, you can download the update for free on your My Loot page (version 3.3).
  • If you’re an iOS Apprentice Print Version customer, you can find the updated source code (and a “Changes for Swift 1.2″ PDF) at the URL given in the introduction of the book.
  • If you don’t have the iOS Apprentice yet, grab your copy now!

Matthijs and I hope you enjoy this update!

iOS Apprentice Updated for Xcode 6.3 and Swift 1.2 is a post from: Ray Wenderlich

The post iOS Apprentice Updated for Xcode 6.3 and Swift 1.2 appeared first on Ray Wenderlich.


View Debugging in Xcode 6

$
0
0
Debugging views in Xcode has never been easier

Debugging views in Xcode has never been easier

When you’re developing an app, sometimes there may be a bug with your views or auto layout constraints that isn’t easy to find just by looking through your code.

It pays to know the technique of view debugging – and this has never been easier with the advent of Xcode 6.

Instead of printing frames to the console and trying to visualize layouts in your head, you’re now able to inspect an entire view hierarchy visually – right from within Xcode. What an incredible time to be alive!

This tutorial will take you through all the different options that are at your disposal. So, are you ready to write some code? That’s too bad, because you won’t. :]

Instead, you’ll inspect the view hierarchy of an open source library to better understand how it was written — without even looking at any code.

Getting Started

The library you’ll use in this tutorial is JSQMessagesViewController, written by Jesse Squires. The UI for this library should look very familiar, as Jesse built it to look similar to the Messages app.

To get started, head over to the GitHub project page, download the source code, and unzip into a directory.

Note: The library uses CocoaPods to manage its dependencies on other libraries. If you’re unfamiliar with how CocoaPods works, please take a look at this CocoaPods tutorial here on the site before proceeding.

Next, navigate to the unzipped project directory in Terminal and run pod install to install the required dependencies. Then, open JSQMessages.xcworkspace and build and run the app on the iPhone 5s simulator. (You can use any simulator, but dimensions in this tutorial are based on a 4-inch display, so choosing the same will make it easier to follow.)

Note: Live View Debugging is only available if you run your app on iOS 8. You cannot use this tool on iOS 7, even if you’re working in Xcode 6.

Tap on Push via storyboard and you’ll notice you’re now in a text messaging thread with Steve Jobs and Tim Cook. (This may cause a flutter in your heart and make you question your perception of reality, but it’s not really them.) This is the view you’ll inspect.

Even Steve Wozniak joins the fun!

Even Steve Wozniak joins the fun!

Go back to Xcode and click on the Debug View Hierarchy button in the Debug bar. Alternatively, go to Debug\View Debugging\Capture View Hierarchy.

Screenshot 1

Xcode is now interrupting your app and handing the reigns to the debugger, just as if you had paused your app with the pause button on the Debug bar.

In addition, Xcode replaces the code editor with a canvas in which it draws the entire view hierarchy of the key window of your app, including thin lines (called wireframes) that indicate the boundaries of every view.

Screenshot 2

You may know that when you add a subview to a view hierarchy, you’re adding a layer on top of the current stack of views. Because most views don’t overlap, it looks like all views are just part of one big layer when you run your app. The screen you’re currently looking at is pretty close to that, but with a bunch of extra lines.

So how is that useful? Well, right now you’re seeing a visual of the view stack from overhead, but what if you could visualize where the layers fall within the stack? Click and drag in the canvas, and you’ll see that instead of a flat 2D view, you’re actually interacting with a 3D model of your view hierarchy.

Screenshot 3

You can view the hierarchy from the side, top, bottom, a corner and even from the back!

views

Note: It’s possible your canvas isn’t showing the same views as this tutorial assumes. To make sure you’re on the same page, press cmd + 6 to get to the Debug navigator.

At the bottom of the pane, you’ll see two buttons on the left. Deselect both of these buttons, as seen in this image. If not, some views will be hidden on the canvas.

filter image

Exploring the View Hierarchy

The most natural and common perspective of this 3D model is to look at it from the left side — you’ll see why a little later in this tutorial — so manipulate it to get a point of view like the one below.

Screenshot 4

This gives your view hierarchy some perspective that’s very useful if you want to visualize how it’s built. However, there seems to be many empty views at the “bottom” (on the left) of the stack. What’s that all about?

Click on the left-most view (i.e. the one in the very back) and you’ll see that Xcode highlights it to indicate your selection. You’ll also see the Jump Bar (just above the Canvas) update to show a UIWindow as the last item — that last item will always reflect the currently selected view and its class type.

Screenshot 5

Since this app uses only one window, it’s safe to assume the UIWindow at the start of the Jump Bar is the app’s key window, or in other words, the window property on AppDelegate.

OK, it’s good to know how to find the window, but it’s unlikely that you’ll need to inspect that. What about the next view? In the canvas, click on the view to the right (i.e. on top) of the window and look at the Jump Bar again. UILayoutContainerView. That’s not even a public class!

iw21s

From there, the view hierarchy looks like this:

  1. UINavigationTransitionView: The container view in which navigation controller transitions happen
  2. UIViewControllerWrapperView: A wrapper view that contains the view controller’s view property
  3. UIView: The top-level view of a view controller (the same as a view controller’s view property)
  4. JSQMessagesCollectionView: The collection view used by this project to display all messages

Focusing on Views of Interest

In debugging this particular view hierarchy, the first four views (starting with the window) are really just visual noise. They don’t bring anything meaningful; they distract in trying to understand what else is going on in this view hierarchy. It would sure be nice if you could filter out that visual noise…

And you can. :] Look at the double-thumbed slider in the bottom right of the canvas. By default, the thumbs are all the way on the left and right side of the slider.

Screen Shot 2015-04-07 at 12.24.14 PM

Drag the left thumb slowly to the right a little bit; you’ll see the wireframe that represents the app’s window disappear from the canvas. If you drag a little further, the UINavigationTransitionView disappears as well.

Drag the left thumb as far as needed to hide all the parent views of JSQMessagesCollectionView. Your canvas should now look similar to this:

Screenshot 6

On the right side, you might notice the navigation bar is not just distracting, but it’s actually laid out on top of the collection view, making it hard to see what’s going on underneath. Fortunately, you can hide it.

Because you’re focusing on a smaller area of the screen with many smaller views that comprise the navigation bar, it’s a good idea to zoom in on the nav bar so you can see what exactly you’re doing.

Use the zoom control buttons, which are in a group of three buttons centered at the bottom of the canvas:

Screen Shot 2015-03-15 at 5.03.26 PM

As you would expect, the + button zooms in, the – zooms out, and the = button resets the zoom to the normal zoom level. Zoom in to get a good visual of the navigation bar.

Screenshot 7

Note: If you use a trackpad, pinch gestures will also zoom. A trackpad is also useful to move around in the canvas if all parts of the screen can’t be shown at once because you zoom in really far.

You can also zoom with option-mousewheel.

The extra detail you get by zooming in on the toolbar is nice, but the views still slightly overlap, so it’s not easy to tell which view is which.

To solve that problem, use the spacing slider in the bottom left corner of the canvas. The further you drag the thumb of the spacing slider to the right, the more spacing Xcode shows between different views.

Screen Shot 2015-04-07 at 12.29.20 PM

In this particular case, move the slider to the right as much as needed to avoid overlapping views in the toolbar. You might have to play around with the perspective by click-dragging on the canvas to get the desired result.

Screenshot 8

The 3D model is now perfectly manipulated so you can easily hide the navigation bar.

In the slider on the right (the one that hides views), drag the right thumb slowly to the left, up to the UINavigationBar. Remember that you can use the Jump Bar to identify each view’s class by selecting the topmost layer as you go. You’ll see the navigation items disappear first, then the buttons that contain them, followed by a few private views, and lastly, the navigation bar.

Look ma, no nav bar!

Look ma, no nav bar!

Note: If you rotate the canvas to look at the 3D view hierarchy model with the top layer on the left, the slider’s left thumb still removes views from the bottom of the stack, which is now on the right. Similarly, the right thumb removes views from the left.

Moving a slider from the left to the right and having views disappear from the right to the left (and vice versa) is counterintuitive, so that’s why looking at the model with the top layer on the right is the most natural perspective.

Unfortunately, hiding the nav bar (with the root view of _UIBackdropView) view also causes the toolbar items’ content at the bottom of the screen to disappear. To see this, you may need to adjust the zoom level or move down the canvas.

You want to see the toolbar items as they are an important part of the screen, so only hide the views up until (but not including) the _UIBackdropView. The navbar stack should look something like the following once you’re done.

Screenshot 9

More View Options

Now that irrelevant views are hidden, it’s time to take a look at the screen from the front again. You can try to drag the model back into place, but sometimes it’s difficult to get it just right. Fortunately, there is a simpler way.

Look at the group of four buttons to the left of the zoom buttons. The third button from the left is the ResetViewing Area button. It undoes rotations and gives you the front perspective of the view hierarchy, just like in the simulator or on a device.

Screen Shot 2015-03-15 at 5.03.26 PM copy

Your canvas should look similar to the following at this point:
head on view with wireframes

You probably noticed that what you see in the debugger is still not exactly what you see when the app actually runs.

First of all, you still have wireframes around every single view; they allow you to see transparent views or views without any content, but if you don’t need the detail they can make things pretty noisy.

You can turn this off with the View Mode button — the one to the right of the Reset Viewing Area button. When you click the view mode button, you can specify if you want to see the views’ wireframes, their contents or both.

wireframes

A wireframes-only view is particularly useful if you’re mostly interested in positioning, and not so much about what a view looks like. Showing only the views’ contents is useful when you’re trying to debug a view’s appearance.

To reduce some of the clutter the wireframes cause in this case (especially near the navigation bar and toolbar), change the view mode to Contents to remove all the wireframes and leaves you with the core of the app.

no wireframes

Next, a couple of things are missing from the current view. When you run the app, you’ll see labels above the text bubbles that indicate the sender’s name or the message’s timestamp, as well as an image of the Golden Gate Bridge in the last bubble. But the debugger isn’t showing those labels and that image!

To solve this, look at the first button in the center row of buttons on the canvas. This is a toggle to show or hide clipped views. These are views that have their clipsToBounds property set to YES.

clip to bounds button

That is exactly what is happening with these labels, presumably because long names and dates should not extend beyond the bounds of their labels. The same applies to the image, which uses a corner radius and clipping to produce the rounded corners. Click on the toggle and you’ll notice these views now show up in Xcode.

Screenshot 11

Note: You may notice wireframes around the newly visible items. If that’s the case, toggle wireframes on and then off with the View Mode button you used previously. That should resolve the issue.

And there you have it: a near-perfect replica of your view hierarchy right within Xcode.

That was easy!

That was easy!

Inspecting Views

Now that the important parts are easily accessible, it’s time to look at layouts for these different views.

You already knew the collection view is what makes all these views come together, but wouldn’t it be great if you could just have an overview of the different elements that are at play here? Good news – you can!

Press cmd + 6 to go to the Debug navigator. Since this is a debugging session just like any other, the Debug navigator provides contextual information about the current session. For view debugging, this means Xcode provides a view tree of all the views for all windows. Expand the tree in the Debug navigator to look like this:

Screenshot 12

Note: At the bottom of the Debug navigator, you’ll see options that give a little bit of control over what kinds of items display in this tree. Apple’s documentation claims the button on the left filters private elements out of system view implementations, though this button does not seem to work as of Xcode 6.2.

The button to the right hides views that have their hidden properties set to YES, and the search bar only displays views and constraints that match the search criteria.

For the purposes of this tutorial, you should have both buttons deselected and no search filter applied.

This is a good point to start exploring a little bit. Expand the last JSQMessagesCollectionViewCellOutgoing. It only has one subview: a UIView.

If you’ve worked with collection views before, you know this makes sense because any UICollectionViewCell has a contentView property that contains the cell’s contents.

Click — don’t expand — on that UIView in the Debug navigator and you’ll see that Xcode has now highlighted it in the canvas so you know exactly where it is on the screen.

Screenshot 13

To really understand how iOS positions that cell, open the Size Inspector with cmd + option + 4. The top part of the visualizes the view’s bounds, position and anchor point.

Screenshot 14

However, the really interesting part is the list of Auto Layout constraints that apply to this view. You can immediately tell that the cell’s content view is 312 points wide, 170 points tall and centered in its parent. The containing cell is also 312 by 170 points, so you know the content view takes up the entire cell.

Below are constraints colored in gray that indicate those are constraints that dictate relationships between this view and its subviews.

To get more details about a particular constraint, first expand that view in the view tree and then the Constraints item. You’ll also see the same constraints you saw in the Size navigator listed here.

Screenshot 15

Click on the first constraint (for me it’s a constraint on self.midX) and switch to the Object inspector by pressing cmd + option + 3. You’ll see a constraint overview with the items, multiplier, constant and priority. This is much like the summary you see in Interface Builder when you edit a constraint.

Screenshot 16

In addition to sizing and constraint information, you can see other details related to the display of a particular view in the object inspector. Back in the Debug navigator, expand the UIView in the tree and you’ll see there are three JSQMessageLabels and two UIViews under it. Select the first JSQMessageLabel (the one with the timestamp), and open the Object inspector.

Screenshot 17

The first section indicates the object’s class name and memory address, and the second shows values for various public properties of the object that pertain to its appearance.

Here you can see the label’s text color is 0.67 gray with no alpha, and its font size is 12pt.
Other classes have useful information specific to how they’re visualized as well. Back in the Debug navigator, expand the second UIView under the cell’s root UIView and you’ll see a UIImageView.

Screenshot 18A

Select the image view from the tree and check out the Object inspector.

Screenshot 18B

Here you’re looking at the view that shows the user’s avatar — in this case, the author’s initials, JSQ. You can see the normal image, conveniently labeled Image, as well as the darker image, labeled Highlighted, that shows when the user taps on the cell.

The other two instances of JSQMessageLabel in this cell’s root view don’t currently have text, but they are used for the sender’s name in incoming messages and an error message when sending an outgoing message fails.

And that’s how easy it is to do view debugging in Xcode! To continue running the app, just click the Continue button on the Debug bar, or go to Debug\Continue, just like you would if you were in a normal debug session.

Live Modifications

Now that you know the basics of view debugging in Xcode 6, it’s time to put that knowledge to work with a small exercise: For the collection view you’ve been exploring throughout the tutorial, make its vertical scroll indicator red by only using the debugger.

Here are two tips to get you started:

  1. Since view debugging is just like any other debugging session, you can use expr and other commands in the console, but keep in mind changes won’t appear until you resume execution. For more information on these commands, take a look at this debugging apps in Xcode tutorial.
  2. Because pointers in Objective-C are really just memory addresses, you’re simply messaging a memory address when you message an object. This works in the debugger as well, so a command like po 0x123456abcdef would print the description of the object at that memory address.

Give it some solid attempts before you break down and look at the solution below!

Solution Inside: Solution SelectShow>


Congratulations, you now know the basics of view debugging with Xcode 6!

Old School Debugging

Live view debugging made debugging views in Xcode 6 a lot easier, but that doesn’t mean that your favorite old school tricks are now useless. In fact, iOS 8 introduces a very welcome addition to the family of view debugging tricks: _printHierarchy.

Note: You’ve already learned the basics of view debugging with Xcode 6, so feel free to skip this optional section if you’d like. However if you’re curious about some handy old-school techniques, read on!

Printing the View Controller Hierarchy

_printHierarchy is a private method on UIViewController that you can use to print the view controller hierarchy to the console. Build and Run, select Push via storyboard and then hit the pause button in the Debug bar.

Now type this in the console and press return:

po [[[[UIApplication sharedApplication] keyWindow] rootViewController] _printHierarchy]

You’ll get something very similar to this:

<UINavigationController 0x7fdf539216c0>, state: appeared, view: <UILayoutContainerView 0x7fdf51e33bc0>
   | <TableViewController 0x7fdf53921f10>, state: disappeared, view: <UITableView 0x7fdf5283fc00> not in the window
   | <DemoMessagesViewController 0x7fdf51d7d520>, state: appeared, view: <UIView 0x7fdf53c0b990>

This tells you that there is a UINavigationController whose first view controller is a TableViewController — the one where you chose how to push the controller. The second view controller is the DemoMessagesViewController, or the view controller you have been debugging.

It doesn’t seem too exciting in this particular example, but if you have several child view controllers within a navigation controller, and a tab bar controller in a popover in a modal view controller, (I’m not proud of some of my apps’ UI…) it can be immensely useful for figuring out exactly how the view controller hierarchy works.

Printing the View Hierarchy

If you’re not a very visual person and prefer a textual overview of a view hierarchy, you can always use the age-old, and also private, recursiveDescription on UIView. This prints a view hierarchy very similar to the view controller hierarchy as demonstrated above.

Open Views\JSQMessagesCollectionViewCellOutgoing.m and add a breakpoint in awakeFromNib.
breakpoint

Build and Run, then select Push via Storyboard. The debugger should break as a JSQMessagesCollectionViewCellOutgoing is loaded. Now type the following into the console:

po [self.contentView recursiveDescription]

This will print the hierarchy of the JSQMessagesCollectionViewCellOutgoing’s contentView, which will look something like this:

<UIView: 0x7fde6c475de0; frame = (0 0; 312 170); gestureRecognizers = <NSArray: 0x7fde6c484fe0>; layer = <CALayer: 0x7fde6c474750>>
   | <JSQMessagesLabel: 0x7fde6c475eb0; baseClass = UILabel; frame = (0 0; 312 20); text = 'Today 10:58 PM'; clipsToBounds = YES; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x7fde6c476030>>
   | <JSQMessagesLabel: 0x7fde6c476400; baseClass = UILabel; frame = (0 20; 312 0); clipsToBounds = YES; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x7fde6c476580>>
   | <UIView: 0x7fde6c476b50; frame = (70 20; 210 150); autoresize = RM+BM; layer = <CALayer: 0x7fde6c474dd0>>
   |    | <UIImageView: 0x7fde6c482880; frame = (0 0; 210 150); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x7fde6c476ae0>> - (null)
   | <UIView: 0x7fde6c482da0; frame = (282 140; 30 30); autoresize = RM+BM; layer = <CALayer: 0x7fde6c482d00>>
   |    | <UIImageView: 0x7fde6c482e70; frame = (0 0; 30 30); opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <CALayer: 0x7fde6c482f70>> - (null)
   | <JSQMessagesLabel: 0x7fde6c483390; baseClass = UILabel; frame = (0 170; 312 0); clipsToBounds = YES; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x7fde6c483510>>

It’s rudimentary, but can be helpful when you want to debug a view hierarchy pre iOS 8.

Using debugQuickLookObject

Lastly, Xcode 5.1 introduced a feature called Debug Quick Look. This feature is most useful when you’re already debugging and aren’t wondering what an object looks like at a certain point in your code.

Your custom class can implement the method debugQuickLookObject and return anything that is visually presentable by Xcode. Then, when you’re debugging and you have an object you want to inspect, you can use quick look and Xcode will show you a visual representation of that object.

For example, NSURL’s implementation of debugQuickLookObject returns a UIWebView with that URL so you can actually see what’s behind the URL.

For more information on debugging using Quick Look, take a look at the documentation.

Where To Go From Here?

And that’s it for Live View Debugging. It’s an easy tool and can save hours of manually sifting through a view hierarchy trying to understand how and where it’s drawing views.

If you’re looking for a more advanced and comprehensive tool than just Xcode, then take a look at Reveal. While it’s a paid app, it’s also more powerful than Xcode’s view debugging. You can view our Tech Talk on the subject over here.

We hope you enjoyed this tutorial and feel a little more comfortable debugging your UI. If you have comments or questions, please use the forum discussion below!

View Debugging in Xcode 6 is a post from: Ray Wenderlich

The post View Debugging in Xcode 6 appeared first on Ray Wenderlich.

iOS Animations by Tutorials Updated for Xcode 6.3 and Swift 1.2

$
0
0

Good news – Marin Todorov has updated iOS Animations by Tutorials for Xcode 6.3 and Swift 1.2!

As you may know, Swift 1.2 introduced some new syntax, such as an improved if let statement, and revised usage of as vs as! vs as?. To learn more about these changes, check out our What’s New in Swift 1.2 overview.

In this update, Marin has updated all chapters and sample code to use the new Swift 1.2 syntax, and has also fixed some of the errata reported on the forums.

Here’s how you can get the update:

  • If you’re an iOS Animations by Tutorials PDF customer, you can download the update for free on your My Loot page (version 1.4).
  • If you’re an iOS Animations by Tutorials Print Version customer, you can find the updated source code at the URL given in the introduction of the book.
  • If you don’t have iOS Animations by Tutorials yet, grab your copy now!

Marin and I hope you enjoy this update!

iOS Animations by Tutorials Updated for Xcode 6.3 and Swift 1.2 is a post from: Ray Wenderlich

The post iOS Animations by Tutorials Updated for Xcode 6.3 and Swift 1.2 appeared first on Ray Wenderlich.

Video Tutorial: Intermediate Swift Part 2: Properties

Background Modes Tutorial: Getting Started

$
0
0
Picture of app

Learn how to make your app do stuff even when it is no longer active

Update note: This tutorial was updated to iOS 8 and Swift by Ray Fix. Original post by Gustavo Ambrozio.

Since the ancient days of iOS 4, you can design your apps to stay suspended in memory when users push the home button. Even though the app is in memory, its operations are paused until the user starts it again. Or are they?

Of course there are exceptions to this rule! In specific situations, the app can still run some operations in the background. This tutorial will teach you how and when to use some of the most common background operations.

There are important restrictions on the use of background operations and the specifics have evolved with each release of iOS in an effort to improve user experience and extend battery life. Background modes are not a magic solution for getting “real” multitasking on iOS. Most apps will still get completely suspended when the user switches to another app. Your app is only allowed to keep running in the background in very specific cases. For example, these include playing audio, getting location updates, or fetching the latest content from a server.

Previous to iOS 7, apps were given up to 10 continuous minutes to finish whatever they were doing before being truly suspended. With the advent of NSURLSession there is a much more elegant way to handle large network transfers. Because of this, the available background time for arbitrary computation has been reduced to just a few minutes and is no longer necessarily continuous.

So backgrounding may not be for you. But if it is, keep reading!

As you’ll soon learn, there are several background modes available to you in iOS. The project you’ll build in this tutorial is a simple tabbed application that explores four of the most common modes – from continuously playing audio to periodically fetching updated content.

Getting Started

Before digging into the project, here’s a quick overview of the basic background modes available in iOS. In Xcode 6, you can see the list by pulling up the Capabilities tab of your app target. It looks like this:

background_modes

To get to the background modes capability list you (1) select the project from the Project Navigator, (2) select the app target, (3) select the Capabilities tab, and (4) turn the Background Modes switch on.

In this tutorial you will investigate four ways of doing background processing.

  • Play audio: the app can continue playing and/or recording audio in the background.
  • Receive location updates: the app can continue to get callbacks as the device’s location changes.
  • Perform finite-length tasks: the generic “whatever” case, where the app can run arbitrary code for a limited amount of time.
  • Background Fetch: Get updates to the latest content scheduled by iOS.

This tutorial will cover how to use these four modes in the above order, one for each section of the tutorial. If you are only interested in one or several of the modes, feel free to skip ahead!

To get started with the project that will be your tour bus through backgrounding, first download the starter project. Here’s some sweet news: the user interface has been pre-configured for you.

Let’s keep backgrounding in the foreground!

Run the sample project and check out your four tabs:

four_tabs

These tabs are your road map for the rest of the tutorial. First stop… background audio.

Note: For the full effect, you should follow along on a real device. In my experience, if you forget a configuration setting, the app might appear to run fine in the background on the Simulator. However, when you switch to a real device, it doesn’t work at all.

Playing Audio

There are several ways to play audio on iOS and most of them require implementing callbacks to provide more audio data to play. A callback is when iOS asks your app to do something (like a delegate method), in this case filling up a memory buffer with an audio waveform.

If you want to play audio from streaming data, you can start a network connection, and the connection callbacks provide continuous audio data.

When you activate the audio background mode, iOS will continue these callbacks even if your app is not the current active app. That’s right – the audio background mode is (almost) automatic. You just have to activate it and provide the infrastructure to handle it appropriately.

For those of us who are a bit sneaky-minded, you should only use the background audio mode if your app really does play audio to the user. If you try to use this mode just to get CPU time while playing silence in the background, Apple will reject your app!

Who_sneaky

In this section, you’ll add an audio player to your app, turn on the background mode and demonstrate to yourself that it’s working.

To get audio playback, you’ll need to lean on AV Foundation. Open AudioViewController.swift and add the import to the top of the file right after import UIKit:

import AVFoundation

Override viewDidLoad() with the following implementation:

override func viewDidLoad() {
  super.viewDidLoad()
 
  var error: NSError?
  var success = AVAudioSession.sharedInstance().setCategory(
                  AVAudioSessionCategoryPlayAndRecord,
                  withOptions: .DefaultToSpeaker, error: &error)
  if !success {
    NSLog("Failed to set audio session category.  Error: \(error)")
  }
}

This uses the audio session singleton sharedInstance() to set the category of playback and ensure sound goes through the speaker rather than the phone earpiece. It checks whether the call fails and logs the error if it ever does. An actual app might want to present an error dialog in response to a failure, but no need to get bogged down in details here.

Next you want to add a player property method to AudioViewController:

var player: AVQueuePlayer!

This is an implicitly unwrapped optional so it starts off as nil and you will initialize it in viewDidLoad().

The starter project includes audio files from incompetech.com, a favorite royalty-free music website. With credit given, you can use the music for free. So, here you go: all songs are by Kevin MacLeod at incompetech.com. Thanks, Kevin!

Going back to viewDidLoad() add the following to the end of the method:

let songNames = ["FeelinGood", "IronBacon", "WhatYouWant"]
let songs = songNames.map {
  AVPlayerItem(URL: NSBundle.mainBundle().URLForResource($0, withExtension: "mp3"))
}
 
player = AVQueuePlayer(items: songs)
player.actionAtItemEnd = .Advance

This takes the list of songs and maps them to URLs in the main bundle and turns them into AVPlayerItems that can then be put into a AVQueuePlayer. In addition, the queue is set up to play the next item when one item ends.

In order to update the song name as the queue progresses, you need to observe currentItem of the player. To do this, add the following to the end of viewDidLoad()

player.addObserver(self, forKeyPath: "currentItem", options: .New | .Initial , context: nil)

This makes it so that the class’s observer callback is called on initialization and whenever the player’s currentItem changes.

Now you can add the observer method. Put it below viewDidLoad().

override func observeValueForKeyPath(keyPath: String, ofObject object: AnyObject, change: [NSObject : AnyObject], context: UnsafeMutablePointer<Void>) {
  if keyPath == "currentItem", let player = object as? AVPlayer,
     currentItem = player.currentItem?.asset as? AVURLAsset {
     songLabel.text = currentItem.URL?.lastPathComponent ?? "Unknown"
  }
}

When the method gets called, you first make sure the property being updated is the one in which you’re interested. In this case, it’s not actually necessary because there’s only one property being observed, but it’s good practice to check in case you add more observers later. If it’s the currentItem key, then you use it to update songLabel with the file name. If for some reason the current item’s URL is not available, it falls back to the string “Unknown”.

You also need a way to update timeLabel to display the elapsed time of the currently playing item. The best way to do this is by using addPeriodicTimeObserverForInterval(_:queue:usingBlock:), which will call the provided block on a given queue. Add this to the end of viewDidLoad:

player.addPeriodicTimeObserverForInterval(CMTimeMake(1, 100), queue: dispatch_get_main_queue()) {
  [unowned self] time in
  let timeString = String(format: "%02.2f", CMTimeGetSeconds(time))
  if UIApplication.sharedApplication().applicationState == .Active {
    self.timeLabel.text = timeString
  } else {
    println("Background: \(timeString)")
  }
}

This adds a periodic observer to the player that gets called back every 1/100 of a second and updates the UI to the time if the app is in the foreground.

Important: Since you are going to update the UI in the closure, you must make sure the code is called on the main queue. This is why you specify dispatch_get_main_queue() for the queue parameter.

Pause here and consider the application’s state.

Your application can have one of five states. Briefly, they are:

  • Not running: Your app is in this state before it starts up.
  • Active: Once your app is started, it becomes active.
  • Inactive: When your app is running but something happens to interrupt it, like a phone call, it becomes inactive. Inactive means that the app is still running in the foreground but it’s not receiving events.
  • Backgrounded: In this state, your app is not in the foreground anymore but it is still able to run code.
  • Suspended: Your app enters this state when it’s no longer able to run code.

If you’d like a more thorough explanation of the differences between these states, the subject is well-documented on Apple’s website at Execution States for Apps.

You can check your app’s state by reading UIApplication.sharedApplication().applicationState. Keep in mind that you’ll only get three states back: .Active, .Inactive, and .Background. Suspended and not running obviously would never happen while your app is running code.

Returning to the code, if the app is in the active state, you need to update the music title label. You could still update the label text while in the background, but the point here is just to demonstrate that your app continues to receive this callback when your app is in the background.

Now all that’s remaining is for you to add the implementation of playPauseAction(_:) to get the play/pause button working. Update the empty implementation of playPauseAction(_:) in AudioViewController with:

@IBAction func playPauseAction(sender: UIButton) {
  sender.selected = !sender.selected
  if sender.selected {
    player.play()
  } else {
    player.pause()
  }
}

Great, that’s all your code. Build and run, and you should see this:

play_pause

Now hit Play and the music will start. Nice!

Test if backgrounding works. Hit the home button (if you’re using the Simulator, hit Cmd-Shift-H). If you are running on an actual device (and not the Simulator in Xcode 6.1) the music will stop. Why? Well, there’s still a very crucial piece missing!

For most background modes (the “Whatever” mode is the exception) you need to add a key in Info.plist to indicate that the app wants to run code while in the background. Fortunately, Xcode 6 makes this a matter of clicking on a checkbox.

Back in Xcode, do the following:

  1. Click the project on the Project Navigator;
  2. Click TheBackgrounder target;
  3. Click on the Capabilities tab;
  4. Scroll down to Background Modes and turn the switch on;
  5. Check Audio and AirPlay.

audio_enabled

Build and run again. Start the music and hit the home button, and this time you should still hear the music, even though the app is in the background.

You should also see the time updates in your Console output in Xcode, proof that your code is still working even though the app is in the background. You can download the partially finished sample project up to this point.

That’s one mode down, if you’re following through the entire tutorial – three to go!

Receiving Location Updates

When in location background mode, your app will still receive location delegate messages with the updated location of the user, even when the app is in the background. You can control the accuracy of these location updates and even change that accuracy while backgrounded.

Once again, for the sneaks: you can only use this background mode if your app truly needs this information to provide value for the user. If you use this mode and Apple sees nothing the user will gain from it, your app will be rejected. Sometimes Apple will also require you to add a warning to your app’s description stating that your app will result in increased battery usage.

The second tab is for location updates, so open LocationViewController.swift and add some properties with inline initialization to LocationViewController.

var locations = [MKPointAnnotation]()
 
lazy var locationManager: CLLocationManager! = {
  let manager = CLLocationManager()
  manager.desiredAccuracy = kCLLocationAccuracyBest
  manager.delegate = self
  manager.requestAlwaysAuthorization()
  return manager
}()

You’ll use locations to store the locations so you can plot them on the map. CLLocationManager is what you’ll use to get the device’s location updates. You instantiate it in a lazy way so the first time the property is accessed the function is called and it is initialized.

The code sets the accuracy of the location manager to the most accurate, which you can adjust to whatever your app might need. You’ll learn more about those other accuracy settings and their importance in a moment. Notice that you also are calling requestAlwaysAuthorization(). This is a requirement in iOS 8, and brings up a user interface asking for permission to use location in the background.

Now you can fill in the empty implementation of accuracyChanged(_:) in LocationViewController:

@IBAction func accuracyChanged(sender: UISegmentedControl) {
  let accuracyValues = [
    kCLLocationAccuracyBestForNavigation,
    kCLLocationAccuracyBest,
    kCLLocationAccuracyNearestTenMeters,
    kCLLocationAccuracyHundredMeters,
    kCLLocationAccuracyKilometer,
    kCLLocationAccuracyThreeKilometers]
 
  locationManager.desiredAccuracy = accuracyValues[sender.selectedSegmentIndex];
}

accuracyValues is an array with all the possible values of desiredAccuracy of CLLocationManager. This property controls how accurate you want your location to be.

You might think that this is stupid. Why shouldn’t the location manager always give you the best accuracy possible? Well, there’s a reason for the other values: conservation of battery power. Lower accuracy means less battery used.

That means you should select the value for the least amount of accuracy that you can live with for your app. You can change this value whenever you want.

There’s another property that will control how often your app receives location updates, regardless of the value of desiredAccuracy: distanceFilter. This property tells the location manager that you only want to receive a new location update when the device has moved a certain value, in meters. Again, this value should be as high as it can be to conserve battery power.

Now you can add the code to start getting location updates in enabledChanged(_:):

@IBAction func enabledChanged(sender: UISwitch) {
  if sender.on {
    locationManager.startUpdatingLocation()
  } else {
    locationManager.stopUpdatingLocation()
  }
}

The storyboard has a UISwitch attached to this action that turns location tracking on and off.

Next you need to add a CLLocationManagerDelegate method to receive location updates. Add the following method to LocationViewController.

// MARK: - CLLocationManagerDelegate
 
func locationManager(manager: CLLocationManager!, didUpdateToLocation newLocation: CLLocation!, fromLocation oldLocation: CLLocation!) {
  // Add another annotation to the map.
  let annotation = MKPointAnnotation()
  annotation.coordinate = newLocation.coordinate
 
  // Also add to our map so we can remove old values later
  locations.append(annotation)
 
  // Remove values if the array is too big
  while locations.count > 100 {
    let annotationToRemove = locations.first!
    locations.removeAtIndex(0)
 
    // Also remove from the map
    mapView.removeAnnotation(annotationToRemove)
  }
 
  if UIApplication.sharedApplication().applicationState == .Active {
    mapView.showAnnotations(locations, animated: true)
  } else {
    NSLog("App is backgrounded. New location is %@", newLocation)
  }
}

If the app’s state is active, this code will update the map. If the app is in the background, you should see the log of location updates in your console output in Xcode.

Now that you know about Background Modes, you don’t need to make the same mistake as before! Check the box for Location updates to let iOS know that your app wants to continue receiving location updates while in the background.

capabilities_location

In addition to checking this box, iOS 8 also requires that you set a key in your Info.plist allows you to explain to the user why background updates are needed. If you do not include this, location will silently fail.

  • Select the Info.plist file.
  • Click on the + button to add a key.
  • Add the key named NSLocationAlwaysUsageDescription.
  • Write a convincing description of why you need location in the background.

Info_plist

Now build and run! Switch to the second tab and flip the switch to ON.

When you do this the first time, you will see the message that you put into your Info.plist. Tap Allow and go for a walk outside or around your building. You should start seeing location updates, even on the Simulator.

location_permission

After a while, you should see something like this:

location_done

If you background the app, you should see the app updating the location in your console log. Open the app again and you’ll see that the map has all the pins for the locations that were updated while the app was in the background.

If you’re using the Simulator, you can use it to simulate movement, too! Check out the Debug \ Location menu:

location_sim

Try setting the location to Freeway Drive and then hit the home button. You should see the console logs printing out your progress as you simulate that drive down a California highway:

2014-12-21 20:05:13.334 TheBackgrounder[21591:674586] App is backgrounded. New location is <+37.33482105,-122.03350886> +/- 5.00m (speed 15.90 mps / course 255.94) @ 12/21/14, 8:05:13 PM Pacific Standard Time
2014-12-21 20:05:14.813 TheBackgrounder[21591:674586] App is backgrounded. New location is <+37.33477977,-122.03369603> +/- 5.00m (speed 17.21 mps / course 255.59) @ 12/21/14, 8:05:14 PM Pacific Standard Time
2014-12-21 20:05:15.320 TheBackgrounder[21591:674586] App is backgrounded. New location is <+37.33474691,-122.03389325> +/- 5.00m (speed 18.27 mps / course 257.34) @ 12/21/14, 8:05:15 PM Pacific Standard Time
2014-12-21 20:05:16.330 TheBackgrounder[21591:674586] App is backgrounded. New location is <+37.33470894,-122.03411085> +/- 5.00m (speed 19.27 mps / course 257.70) @ 12/21/14, 8:05:16 PM Pacific Standard Time

You can download the partially finished sample project up to this point. On to the third tab and the third background mode!

Performing Finite-Length Tasks… or, Whatever

The next background mode is officially called Executing a Finite-Length Task in the Background. What a mouthful. I think Whatever is catchier!

Technically, this is not a background mode at all, as you don’t have to declare that your app uses this mode in Info.plist (or use the Background Mode checkboxes). Instead, it’s an API that lets you run arbitrary code for a finite amount of time when your app is in the background. Well… whatever!

In the past, this mode was often used to complete an upload or download and a generous (but not guaranteed) 10 minutes was provided to accomplish these tasks. But what if the connection was slow and the process still didn’t finish? It would leave your app in an odd state and you would have to add lots of error handling code to make things work sanely. Because of this, Apple introduced NSURLSession.

Although not a topic of this tutorial, NSURLSession is robust in the face of backgrounding and even device reboots and accomplishes this in a power efficient way. If you are dealing with large downloads, check out our NSURLSession tutorial.

A still very valid use case of the Whatever background mode is to complete some long running task, such as rendering and writing a video to the camera roll.

Whatever_cheers

But this is just one example. As the code you can run is arbitrary, you can use this API to do pretty much anything: perform lengthy calculations (as in this tutorial), apply filters to images, render a complicated 3D mesh… whatever! Your imagination is the limit, as long as you keep in mind that you only get some time, not unlimited time.

How much time you get after your app gets backgrounded is determined by iOS. There are no guarantees on the time you’re granted, but you can always check backgroundTimeRemaining on UIApplication. This will tell you how much time you have left.

The general, observation-based consensus is that you get 3 minutes. Again, there are no guarantees and the API documentation doesn’t even give a ballpark number – so don’t rely on this number. You might get 5 minutes or 5 seconds, so your app needs to be prepared for anything!

Here’s a common task that every CS student should be familiar with: calculating numbers in the Fibonacci Sequence. The twist here is that you’ll calculate these numbers in the background!

Open WhateverViewController.swift and add the following properties to WhateverViewController:

var previous = NSDecimalNumber.one()
var current = NSDecimalNumber.one()
var position: UInt = 1
var updateTimer: NSTimer?
var backgroundTask: UIBackgroundTaskIdentifier = UIBackgroundTaskInvalid

The NSDecimalNumbers will hold the two previous values of the number in the sequence. NSDecimalNumber can hold very large numbers, so it’s well suited for your purpose. position is just a counter that tells you the current number position in the series.

You’ll use updateTimer to demonstrate that even timers continue to work when using this API, and also to slow down the calculations a little so you can observe them.

Add some utility methods to WhateverViewController that reset the Fibonacci calculation and that start and stop a background-able task:

func resetCalculation() {
  previous = NSDecimalNumber.one()
  current = NSDecimalNumber.one()
  position = 1
}
 
func registerBackgroundTask() {
  backgroundTask = UIApplication.sharedApplication().beginBackgroundTaskWithExpirationHandler {
    [unowned self] in
    self.endBackgroundTask()
  }
  assert(backgroundTask != UIBackgroundTaskInvalid)
}
 
func endBackgroundTask() {
  NSLog("Background task ended.")
  UIApplication.sharedApplication().endBackgroundTask(backgroundTask)
  backgroundTask = UIBackgroundTaskInvalid
}

Now for the important part, fill in the empty implementation for didTapPlayPause(_:)

@IBAction func didTapPlayPause(sender: UIButton) {
  sender.selected = !sender.selected
  if sender.selected {
    resetCalculation()
    updateTimer = NSTimer.scheduledTimerWithTimeInterval(0.5, target: self,
      selector: "calculateNextNumber", userInfo: nil, repeats: true)
    registerBackgroundTask()
  } else {
    updateTimer?.invalidate()
    updateTimer = nil
    if backgroundTask != UIBackgroundTaskInvalid {
      endBackgroundTask()
    }
  }
}

The button will toggle its selected state depending on whether the calculation is stopped and should start, or is already started and should stop.

First you have to set up the Fibonacci sequence variables. Then you can create an NSTimer that will fire twice every second and call calculateNextNumber() (still to come).

Now comes the essential bit: the call to registerBackgroundTask() that in turn calls beginBackgroundTaskWithExpirationHandler(_:). This is the method that tells iOS that you need more time to complete whatever it is you’re doing in case the app is backgrounded. After this call, if your app is backgrounded it will still get CPU time until you call endBackgroundTask().

Well, almost. If you don’t call endBackgroundTask() after a period of time in the background, iOS will call the closure defined when you called beginBackgroundTaskWithExpirationHandler(_:) to give you a chance to stop executing code. So it’s a very good idea to then call endBackgroundTask() to tell the OS that you’re done. If you don’t do this and continue to execute code after this block is called, your app will be terminated!

The second part of the if is simple: it only invalidates the timer and calls endBackgroundTask() to indicate to iOS that you don’t need any extra CPU time.

It is important that you call endBackgroundTask() for every time you call beginBackgroundTaskWithExpirationHandler(_:). If you call beginBackgroundTaskWithExpirationHandler(_:) twice and only call endBackgroundTask() for one of the tasks, you’re still going to get CPU time until you call endBackgroundTask() a second time with the value of the second background task. This is also why you needed backgroundTask.

Now you can implement the little CS project method. Add the following method to WhateverViewController:

func calculateNextNumber() {
  let result = current.decimalNumberByAdding(previous)
 
  let bigNumber = NSDecimalNumber(mantissa: 1, exponent: 40, isNegative: false)
  if result.compare(bigNumber) == .OrderedAscending {
    previous = current
    current = result
    ++position
  }
  else {
    // This is just too much.... Start over.
    resetCalculation()
  }
 
  let resultsMessage = "Position \(position) = \(current)"
 
  switch UIApplication.sharedApplication().applicationState {
    case .Active:
      resultsLabel.text = resultsMessage
    case .Background:
      NSLog("App is backgrounded. Next number = %@", resultsMessage)
      NSLog("Background time remaining = %.1f seconds", UIApplication.sharedApplication().backgroundTimeRemaining)
    case .Inactive:
      break
  }
}

Once again, here’s the application state trick to show the result even when your app’s in the background. In this case, there’s one more interesting piece of information: the value of backgroundTimeRemaining. The calculation will only stop when iOS calls the block added through the call to beginBackgroundTaskWithExpirationHandler(_:).

Build and run, then switch to the third tab.

fib

Tap Play and you should see the app calculating the values. Now hit the home button and watch the output in Xcode’s console. You should see the app still updating the numbers while the time remaining goes down.

In most cases, this time will start with 180 (180 seconds = 3 minutes) and go down to 5 seconds. If you wait for the time to expire when you reach 5 seconds (could be another value depending on your specific conditions), the expiration block will be invoked and your app should stop outputting anything. Then if you go back to the app, the timer should start firing again and the whole madness will continue.

There’s only one bug in this code, and it gives me the opportunity to explain about the background notifications. Suppose you background the app and wait until the allotted time expires. In this case, your app will call the expiration handler and invoke endBackgroundTask(), thus ending the need for background time.

If you then return to the app, the timer will continue to fire. But if you leave the app again, you’ll get no background time at all. Why? Because nowhere between the expiration and returning to the background did the app call beginBackgroundTaskWithExpirationHandler(_:).

How can you solve this? There are a number of ways to go about it and one of them is to use a state change notification.

There are two ways you can get a notification that your app has changed state. The first is through your main app delegate’s methods. The second is by listening for some notifications that iOS sends to your app:

  • UIApplicationWillResignActiveNotification and applicationWillResignActive(_:) These are sent and called when your app is about to enter the inactive state. At this point, your app is not yet in the background – it’s still the foreground app but it won’t receive any UI events.
  • UIApplicationDidEnterBackgroundNotification and applicationDidEnterBackground(_:) These are sent and called when the app enters the background state. At this point, your app is not active anymore and you’re just getting this last chance to run some code. This is the perfect moment to call beginBackgroundTaskWithExpirationHandler(_:) if you want to get more CPU time.
  • UIApplicationWillEnterForegroundNotification and applicationWillEnterForeground(_:) These are sent and called when the app is returning to the active state. The app is still in the background but you can already restart anything you want to do. This is a good time to call endBackgroundTask() if you’re only calling beginBackgroundTaskWithExpirationHandler(_:) when actually entering the background.
  • UIApplicationDidBecomeActiveNotification and applicationDidBecomeActive(_:) These are sent and called right after the previous notification, in case your app is returning from the background. These are also sent and called if your app was only temporarily interrupted – by a call, for example – and never really entered the background, but you received UIApplicationWillResignActiveNotification.

You can see all this in graphic detail (literally – there are some nice flow charts) in Apple’s documentation for App States for Apps.

Time to fix the bug. First, override viewDidLoad() and subscribe to UIApplicationDidBecomeActiveNotification.

override func viewDidLoad() {
  super.viewDidLoad()
  NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("reinstateBackgroundTask"), name: UIApplicationDidBecomeActiveNotification, object: nil)
}

This designates the selector reinstateBackgroundTask to be called whenever the application becomes active.

Whenever you subscribe to a notification you should also think about where to unsubscribe. Use deinit to do this. Add the following to WhateverViewController:

deinit {
  NSNotificationCenter.defaultCenter().removeObserver(self)
}

Finally, implement reinstateBackgroundTask().

func reinstateBackgroundTask() {
  if updateTimer != nil && (backgroundTask == UIBackgroundTaskInvalid) {
    registerBackgroundTask()
  }
}

You only need to reinstate if there is a timer going but the background task is invalid.

Breaking your code into smaller utility functions that do one thing is paying off. You simply need to call registerBackgroundTask() when a background task not running for the current timer.

And there you have it. You can download the partially finished sample project up to this point.

On to the final topic for this tutorial: Background Fetching.

Background Fetch

Background fetch is a mode introduced in iOS 7 that lets your app appear always up-to-date with the latest information while minimizing the impact on battery. Suppose, for example, you were implementing a news feed in your app. Prior to background fetch, you might do this by getting new data in viewWillAppear(_:). The problem with this solution is that your user is looking at the old data for at least several seconds until the new data comes in. Wouldn’t it be better if right when they opened your app the new data was magically there? This is what background fetch gives you.

When enabled, the system uses usage patterns to determine when to best fire off a background fetch. For example, if your user opens the app at 9 AM each morning, it is likely that a background fetch will be scheduled sometime before that time. The system decides the best time to issue a background fetch and for this reason you should not use it to do critical updates.

In order to implement background fetch there are three things you must do:

  • Check the box Background fetch in the Background Modes of your app’s Capabilities.
  • Use setMinimumBackgroundFetchInterval(_:) to set a time interval appropriate for your app.
  • Implement application(_:performFetchWithCompletionHandler:) in your app delegate to handle the background fetch.

As the name implies, background fetch normally involves fetching information from an external source like a network service. For the purposes of this tutorial, you won’t use the network but just fetch the current time. This simplification will let you understand everything required to perform a background fetch and test it without worrying about an external service.

In contrast to finite-length tasks, you only have seconds to operate when doing a background fetch – the consensus figure is a maximum of 30 seconds, but shorter is better. If you need to download large resources as part of the fetch, this is where you need to use NSURLSession‘s background transfer service.

Time to get started. First, open FetchViewController.swift and add the following property and method to FetchViewController.

var time: NSDate?
 
func fetch(completion: () -> Void) {
  time = NSDate()
  completion()
}

This code is a simplified replacement of what you might actually do to fetch some data from an external source (such as a JSON or XML RESTful service). Since it might take several seconds to fetch and parse the data, you pass a completion handler that gets called when the process is done. You will see why this is important a little later.

Next, finish off the view controller. Add the following methods to FetchViewController.

func updateUI() {
  if let time = time {
    let formatter = NSDateFormatter()
    formatter.dateStyle = .ShortStyle
    formatter.timeStyle = .LongStyle
    updateLabel?.text = formatter.stringFromDate(time)
  }
  else {
    updateLabel?.text = "Not yet updated"
  }
}
 
override func viewDidLoad() {
  super.viewDidLoad()
  updateUI()
}
 
@IBAction func didTapUpdate(sender: UIButton) {
  fetch { self.updateUI() }
}

updateUI() formats the time and shows it. It is an optional type so if it is not set, it shows the message not updated yet. When the view is first loaded (in viewDidLoad()) you don’t fetch, but go straight to updateUI() which means the message “Not yet updated” will appear first. Finally, when the Update button is tapped it performs a fetch and as a completion updates the UI.

At this point, the view controller is working.

fetch_working

However, background fetching is not enabled.

The first step to enabling background fetching is to check Background fetch in the Capabilities tab of your app. By now this should be old hat. Go ahead and do this.

capability_fetch

Next, open AppDelegate.swift and request background fetches in application(_:didFinishLaunchingWithOptions:) by setting the minimum background fetch interval.

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
  UIApplication.sharedApplication().setMinimumBackgroundFetchInterval(
    UIApplicationBackgroundFetchIntervalMinimum)
 
  return true
}

The default interval is UIApplicationBackgroundFetchIntervalNever which you might want to switch back to, if, for example your user logs out and no longer needs updates. You can also set a specific interval in seconds. The system will wait at least that many seconds before issuing a background fetch.

Be careful not to set the value too small because it will chew through battery unnecessarily as well as hammer your server. In the end the exact timing of the fetch is up to the system but will wait at least this interval before performing it. Generally, UIApplicationBackgroundFetchIntervalMinimum is a good default value to use.

Finally, to enable background fetch you must implement application(_:performFetchWithCompletionHandler:). Add the following method to AppDelegate.swift:

// Support for background fetch
func application(application: UIApplication, performFetchWithCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
 
  if let tabBarController = window?.rootViewController as? UITabBarController,
         viewControllers = tabBarController.viewControllers as? [UIViewController] {
    for viewController in viewControllers {
      if let fetchViewController = viewController as? FetchViewController {
        fetchViewController.fetch {
          fetchViewController.updateUI()
          completionHandler(.NewData)
        }
      }
    }
  }
}

First you need to get the FetchViewContoller. Next, optionally cast since the rootViewController is not necessarily a UITabBarController in every app, although it is in this app so it will never fail.

Next, you loop though all of the view controllers in the tab bar controller and find the one that successfully casts to FetchViewController. In this app you know it is the last view controller so you could hard-code it, but looping makes it a little more robust in case you decide to add or remove a tab later.

Finally you call fetch(_:). When it completes, you update the UI and then call the completionHandler that was passed in as a parameter of the function. It is important that you call this completion handler at the end of the operation. You specify what happened during the fetch as the first parameter. Possible values are .NewData, .NoData, or .Failed.

For simplicity, the tutorial always specifies .NewData since getting the time will never fail and is always different than the last call. iOS can then use this value to better time the background fetches. The system knows at this point to take a snapshot of the app so it can present it in the card view of the app switcher. And that is all there is to it.

Note: Rather than passing the completion closure along, it can be tempting to save it away in a property variable and call that when your fetch completes. Don’t do this. If you get multiple calls to application(_:performFetchWithCompletionHandler:), the previous handler will get overwritten and never called. It is better to pass the handler through and call it as it will make this kind of programming error impossible.

Testing Background Fetch

One way to test background fetch is to sit around and wait for the system to decide to do it. That would require a lot of sitting. Fortunately, Xcode gives a way to simulate a background fetch. There are two scenarios that you need to test. One is when your app is in the background, and the other when your app is coming back from being suspended. The first way is the easiest and is just a menu selection.

  • Start the app on an actual device (not a simulator);
  • From the Debug menu in Xcode, select Simulate Background Fetch;
    Screen Shot 2015-01-16 at 9.57.24 PM
  • Reopen the app, noticing that it got sent to the background;
  • Switch to the Fetch tab, (Notice that the time is updated to when you simulated the background fetch and not “Not yet updated”.)

The other way you should test background fetch is to do it as a resume from suspension. There is a launch option that lets you launch your app directly into suspension. Since you might want to test this semi-often it is best to make a new Scheme with that option always set. Xcode makes this easy.

First select the Manage Schemes option.

Screen Shot 2015-01-16 at 10.10.42 PM

Screen Shot 2015-01-16 at 10.42.12 PM

Next, select the only scheme in the list, and then click on the gear icon and select Duplicate Scheme.

Screen Shot 2015-01-16 at 10.08.58 PM

Lastly, rename your scheme to something reasonable, like, “Background Fetch” and check the checkbox to Launch due to background fetch event.

launch_suspended

Note that in Xcode 6.1, this doesn’t work reliably with the simulator. In my own testing, I needed to use an actual device to launch into the suspended mode correctly.

Run your app with this scheme. You will notice that the app never actually opens but is launched into a suspended state. Now manually launch it and go to the Fetch tab. You should see that there is an updated time when you launched the app instead of “Not yet updated”.

Using background fetch effectively lets your users to seamlessly get the latest content.

Where to Go From Here?

You can download the fully finished sample project here.

If you want to read Apple’s documentation on what we covered here, the best place to start is in Background Execution. This documentation explains every background mode and has links to the appropriate section of the documentation for every mode.

A particularly interesting section of this document is the one that talks about being a responsible background app. There are some details that might or might not relate to your app here that you should know before releasing an app that runs in the background.

Finally, be sure to check out NSURLSession if you plan on doing large network transfers in the background.

I hope you enjoyed the tutorial. You’re now ready to go off on your own and create wonderful things with whichever of the background modes are useful for your purposes.

Background Modes Tutorial: Getting Started is a post from: Ray Wenderlich

The post Background Modes Tutorial: Getting Started appeared first on Ray Wenderlich.

Video Tutorial: Intermediate Swift Part 3: Protocols

Readers’ App Reviews – April 2015

$
0
0
blocks3DWorld

Apps Springing up everywhere!

April has arrived and that means more apps from readers like you!

Just like every month, you’ve packed my inbox with great new apps and games. And as expected, I’ve got a handful to share with you to give you a snapshot of what the community is building.

This month we’ve got:

  • My new favorite word game
  • An anonymous social network
  • Our first Apple Watch app
  • And naturally, much more!

Keep reading to catch a glimpse of what the community has built this month.

Lettercraft

Lettercraft
Lettercraft is a fresh new game from the team that brought you GREG that makes word searches fun again.

Lettercraft has a time sensitivity that makes word searches unique. Every few seconds the board advances a level of heat. When tiles get too hot they burn up and can’t be used. Each time you use a letter to make a word, that tile drops a level of heat.

In addition to survival mode, Lettercraft has 70 levels of challenging constraints to keep things interesting. Things like only making words that contain the letter A or 5 letter words only.

And to support the statistics nerd in all of us, Lettercraft a full stats page showing your favorite words, average correct, average length, most used letters, graphs, scores, and much more.

Lettercraft tops it off with GameCenter leaderboards and challenge modes to see how among you is the Lettercraft champion.

Countdown

countdown
Countdown is a minimal countdown timer that looks great on the retina display.

Countdown is clean and simple showing any metric you’d like for each countdown you schedule in a variety of popping colors. You can import countdowns from your calendar or birthdays. Schedule notifications for when a countdown finishes. And iCloud synchronization keeps your countdowns in sync on all your devices.

How many devices? Well you classic iPhone, powerful iPad, and now the convenient Apple Watch! Countdown is our first app to support the brand new Apple Watch. You’ll be able to check your countdowns anytime quickly and easily from the Countdown Apple Watch app.

Feed the Snake

feedthesnake
Feed the Snake is a beautiful modernization of a classic favorite.

Feed the snake has cute graphics to breath new life into the retro Snake genre. The rules are simple, don’t hit the edges and don’t hit yourself. But with the addition of a few powerups the game gets a bit more interesting.

Theres a special tongue powerup that lets you snatch up your prey from farther away. Then there is a magic skin powerup that lets you pass through obstacles unharmed and come out the otherside. Then there is a special degeneration powerup that helps you shrink slowly so you can live just a little longer. All this helps you put the combo multiplier to work to climb the GameCenter leaderboards and compete again your friends.

Gifts Planner

GiftPlanner
Gifts Planner helps with one of my biggest problems, remembering what to get someone as a gift.

It happens to us all, we think of something perfect for that special someone only to forget by the time an occasion comes around. Or worse we get that someone the perfect gift, only to find out we’ve given it to them before!

Gifts Planner is here to make it simple and easy to keep track. You can add gifts for any of your contacts marked as given or planned and include prices and occasions to make sure you don’t forget.

Next time you need a gift for someone, open up Gifts Planner and you’ll be quickly reminded of your great ideas for the perfect gift.

ChypIn

Chipin
ChypIn is a new social application that lets you share your two cents on photos posted for all to see. Its the first social network you can hear, and its surprisingly nice to just listen to people’s thoughts on various photos.

ChypIn is unique in that it builds a soundtrack for each photo made up of the voices of the entire social network. Anyone can listen and add to the banter. A variety of feeds let you browser for photos of anything you’d like to listen or contribute to.

Of course it wouldn’t be complete without the ability to upload your own photos and push notifications comments on them.

Track My TV

trackMyTV
Trying to keep up with all your favorite TV shows can be hard. There are so many, all on different networks, with different schedules, and different seasons.

Track My TV is a new app that will help manage some of that for you. You can choose from a database of 20,000 TV shows and add them to your list. Upcoming episodes will be presented and you can get notifications for them if you’d like.

You can pick a show and mark older episodes as watched to keep track of what you’ve seen. You can get cast lists, descriptions, lengths, and other meta data right inside the app.

There is no easier way to keep track of what you’ve seen and whats coming up. Looking forward to iCloud syncing and widgets in the next update.

One More Roll

onemoreroll
One More Roll is an addictive, fast moving game all about pushing your own luck.

Roll the dice and see a number. Roll up to three times each round. The next round you’re trying to get higher than the previous number. After each roll you’ve got a chance to bank your points or double down so to speak for more. Its a game of odds with a twist of greed pushing you over the edge. If you fail to roll higher all three rolls in a round, you bust and miss out on any points.

Roll the dice is definitely addictive. And with three game modes it will certainly stay that way. You can play against friends locally and remotely with GameCenter.

Hedge Loves to Ski

hedgeSkiing
Some bears hibernate during the winter, but Hedge loves to Ski.

Hedge heads to one of his favorite peaks, straps on his Skis, and rides effortlessly down the mountain. Well not quite effortlessly, Hedge needs your help to steer. Help guide Hedge through the endless gates down the mountain.

Helping Hedge is easy, just tilt your device and Hedge follows suit. As you get further down the mountain things get faster and more challenging. But I promise helping Hedge Ski is quite fun and worth the repeated attempts. ;]

Birdies

Birdies
Birdies is a unique challenge on the never ending scrolling dodge style game.

Birdies has not one but two characters that must move in unison to dodge obstacles. You spin them on a circle clockwise or counter clockwise as you maneuver both birds through a variety of stationary and moving obstacles.

After you think you’ve got the hang of this challenging game, compare your highscore with Facebook friends and players around the world to see how you stack up.

Airhoot

airhoot
Airhoot is an encrypted, private and anonymous social network right on your iPhone.

Airhoot leaves you anonymous when chatting in globally, commenting and annotating photos posted by anyone around the world. You can also find anonymous messages from those nearby.

You can doodle on images and comment on messages to share your creativity or make a point. Or you can draw a unique creation all your own. Anonymous others can make comments and redoodle your creation with their own spin.

Airhook also supports private chat rooms where you can invite only a select group of friends. Your messages here are securely encrypted between parties.

Blox 3D World Creator

blocks3DWorld
Box 3D World Creator is a sandbox of 3D creativity where you can build original cityscapes or wholly new creations.

Box 3D World Creator makes it easy for children to be creative with simple tap and pinch controls as they move around and build their own world. They have a variety of colors, objects, and characters to choose from. Build anything you’d like with the basic object provided, then drop in characters to watch them interact with your world. They walk up your stairs, through your door.

You can adjust the environment from day to night and even add rain. Its like being in control of your own miniature world.



Honorable Mentions

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

Lethal Lasers
BlackJack Saloon
Loops
Boletim PMPB
iNVESTaCALC
Coin Eater
Total Image Effects
3076 3D
100 Spots
My Food Storage
Bestiolis Recue Saga
Checka
Counta



Where To Go From Here?

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

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

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

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

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

Video Tutorial: Intermediate Swift Part 4: Extensions


RWDevCon Inspiration Talk – Contributing by Ryan Nystrom

$
0
0

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

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


Transcript

Thank you everybody for coming out here. It’s really exciting for me to be here and to be presenting to you guys.

I think our iOS community is something really special, in particular the raywenderlich.com community, and really I’m happy to be up here and giving back to the community that helped me get started.

Let’s clear something up really quick. You might think that because I’m a speaker and I’m up here, I’m an awesome engineer and I write awesome code. Let me show you just something I wrote like 2 weeks ago:

var photos = [PhotoModel]()
 
let options = [(kCGImageSourceShouldCache as String) : false]
 
if let imageURLs = fm.contentOfDirectoryAtPath(path, error: &error) as? [String] {
  for fileName in imageURLs {
    if let URL = NSURL(fileURLWithPath: path)?.URLByAppendingPathComponent(fileName) {
      if let imageSource = CGImageSourceCreateWithURL(url, nil) {
        if let imageProperties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, options) as? PropDictionary {
          if let exif = imageProperties[kCGImageProperityExifDictionary] as? PropDictionary {
            if let OriginalDateString = exif[kCGImagePropertyExifDateTimeOriginal] as? String {
              if let date = df.dateFromString(originalDateString) {
                photos.append(PhotoModel(title: fileName, imagePath: url, dateTaken: date))
              }
            }
          }
        }
      }
    }
  }
}

Look at that. That sucks. It’s doing some Core Image stuff. It’s dumb. It’s hacky. It works. Whatever. I’ve written other crappy code and I’ve written code that’s worse than this, and I’m willing to bet you guys probably have too.

But I’ve written better code. I’ve written code that I’m really proud of, and I bet you guys have too.

I bet you’ve written code that if you were to show it to me, I’d be like, “Whoa, that’s awesome. That’s really good.”

Screen Shot 2015-03-23 at 8.59.47 PM

That’s why I’m up here, because I have written things that I’m proud of and I know you have, and I want you to share them.

Like Ray mentioned in his keynote, our community is really special and we should be contributing to it. So I’m going to be up here trying to convince you why you should be doing it, how you can be doing it, and maybe give you some tips on how to get started.

Why Bother?

Is this just to become internet famous and get thousands of Twitter followers or something? Not really.

Take a look at all the leaders in our iOS community. They’re speakers. They contribute to open source. They blog. Maybe they do have thousands of Twitter followers because the things that they tweet are kind of important. :]

NSHipster

This is all about building a better community and strengthening the one that we’ve built so far. Whether it’s writing or giving a talk or building an open source project, there are a ton of benefits.

Personal and Professional Benefits

There are personal benefits:

  • I’ve made a lot of friends.
  • I’ve learned from a bunch of different unique experiences.
  • Whenever I do an open source project or I give a talk, I’m reiterating things that I’ve learned before and I’m strengthening that knowledge of it.

There are also professional benefits:

  • You build a network.
  • You might find other resources with people or companies or tools that’ll help you out.
  • You might actually find a way to get help when you’re stuck somewhere.

Awesome Tools

Tools

Another important reason we should be doing this is just take a look at the tools that we use every single day.

  • FreeBSD, which powers OS X
  • LLVM, which powers tools like Xcode
  • WebKit, which we’ve probably used before
  • Swift, which fingers crossed it’s going to be open source, but this is a tool that we’re going to be using, probably for a long time.

These are all awesome projects that you might be telling yourself, “These are amazing, built by really talented super smart people. How in the world could I ever contribute something and build something like this?”

Your Experience Can Help Someone

Last year I was at a conference called NSNorth and a guy by the name of David Smith, who does a podcast called Developing Perspective and writes a blog with the same name, said something that really struck me. He said:

“No matter how little experience you think you have, someone else has less experience than you.”

Now think about that. Think about when you were 2 days into doing iOS development. You probably thought, “Everything that I could say has been done before. Nothing that I say would really matter.”

But there’s somebody out there that’s been doing iOS for just 1 day.

Think about all the things that you learned on that second day:

  • Those Xcode shortcuts you learned
  • How you got that app to run on a real device
  • And how much of a pain in the a** that actually was!

Think about how you could share that to that person that’s still been doing this for just 1 day – and really teach them something and help them get moving faster.

How I Began Contributing

Jumping in to just contributing to our community might sound a little intimidating, so as an anecdote, I’m going to share how I got started.

Back in 2010, I was still in school. I was interested in learning how to build iOS apps.

I stumbled upon this little known website that had some pretty cool tutorials at the time and decided to start learning. In fact, this is actually a screenshot of the very first tutorial that I read:

Screen Shot 2015-03-23 at 8.38.04 PM

It is burned into my memory because of that freaking ladybug. Ray’s site really helped me get started.

When I got started, a lot of my colleagues and friends would ask me, “Hey, what you’re doing looks pretty cool. I like that animation or I like that you can make your own app to send a tweet.” They started asking, “How can I get started? How can I do this?”

I had enough people interested that I decided to build my own class while I was still in school. It was a little volunteer class.

Where I began teaching.

This is the room that I actually taught it in.

I called it iOS 101 and the attendance was awful. Single digits, people rarely showed up multiple times, but I had a core group of students that actually kept showing up.

These students were really interested and really wanted to hear what I had to say, and I really got hooked on that feeling of teaching somebody something.

It really reinforced the basics when I was building these presentations and slides and stuff, like having to remember what the actual difference between an integer and a float was at the time.

On the very last day, I was fortunate enough to email Ray and ask him to Skype in and give everybody a “Where to go from here?” talk.

Screen Shot 2015-03-23 at 9.01.36 PM

Meeting Ray had opened amazing opportunities for me. I soon after started tech editing for him, then I started writing, then I started writing books, and now I’m up here.

Enough about how I got started. Let’s talk about how you can get started and the different ways you can do that.

You Can Do It! – Writing

Let’s start with writing.

I’m going to preface with writing is super hard. It’s easy to just spew out words and fill up a page, but it’s really hard to actually write something and communicate effectively.

As engineers and developers, we’re stereotyped as introverts. We might be really logical with our brains but we might not be so eloquent with our words.

But think about how many emails you send, think about how many estimates or quotes you fill out, or how many times you have to explain to your manager, “That’s not a bug, it’s a feature.”

Writing and practicing writing helps you communicate better.

A Writing Example

As an example, for me in my day-to-day work, if I run across something interesting, I usually will copy and paste some notes and keep moving on.

Screen Shot 2015-03-25 at 7.19.16 PM

I’ll return to those notes and maybe put something … Maybe something will stand out and I’ll think, “You know, I should probably share that. That’s kind of interesting.” I’ll turn it into an outline and then I’ll eventually write it out as a real blog post.

For instance, when I was working on AsyncDisplayKit at Facebook, we ran into this really weird NSURLSessionTask issue, sort of like a iOS 7, iOS 8 compatibility thing. It’s really weird. The debugger had this in the output when I was done and fixed it.

I thought it was interesting. It was like a little weird class hierarchy difference between iOS 7 and iOS 8. Threw it into Day One, the app I use to take notes, and then I just moved on.

A week or 2 later, I came back to it. I saw this again and I was like, “Man, that was kind of cool.” This was useful. I whipped together a really simple outline and then after looking at that, I filled out all the bullet points into paragraphs and I published a blog post:

It’s not the most perfect blog post. It’s not even that super interesting, but it was kind of cool. A couple of people reached out and said, “Hey, thanks. That’s pretty neat.”

My process isn’t perfect, but it’s simple. If you decide to start writing, whatever process you use should be really simple too.

You Can Do It! – Tweeting

Screen Shot 2015-03-25 at 7.27.05 PM

If writing is a little bit intimidating because filling up blog posts with words is kind of a lot and takes a lot of work, I want to tell you about this awesome place that limits everything that you say to just 140 characters.

Twitter’s awesome! I love Twitter. I can immediately get in touch with peers in my industry, chat, talk about new tools or trends.

I can find out about new conferences or upcoming conferences or when tickets go on sale, except not WWDC. If you use Twitter for WWDC, they’re already sold out. :P

Sometimes I’ll find out that somebody’s nearby and I’ll just invite them to grab a beer, or other sort of tools and technologies when they come out.

You Can Do It! – Stack Overflow

There’s other online communities too. I don’t know if you guys have heard of this one, but Stack Overflow is an awesome place. I’m sure that we’ve used it to just Google answers and that’s great, but the community, the online community here, is kind of awesome.

If you’re really good at answering questions, if you’re thorough, you can actually build a reputation, and I’m not talking like vanity internet points. I’m talking about being The Core Data Guy and that’s pretty cool.

Honestly, if you’ve never sifted through some of the unanswered questions on Stack Overflow, you should, because they’re all a bunch of 5,000 piece puzzles and all I want to do is solve them. If you’re a puzzle solver, get on here.

You Can Do It! – Conference Speaking

If you like actually talking to somebody or you’re stuck behind a computer too often, there’s what I’m doing, actually speaking.

Screen Shot 2015-03-25 at 7.28.12 PM

Again, engineers and introverts and all that stuff, maybe we’re not that good at speaking, but I never liked getting up in front of people and speaking myself. It took me a while.

I started really small. At my last company, there’d be a group of four or five people, non-technical people, that were interested in iOS. They just want to learn how Apple works, how the App Store works, so I put together a 10 slide presentation and gave it to them.

Screen Shot 2015-03-25 at 7.28.36 PM

I got interested in doing that and eventually moved on to meetup groups, where there’d be a group of industry peers. I would give my presentation to them and be able to get some really good, critical feedback.

Moving on from that, I decided to get in touch with some small conferences. I’m sure Ray can attest that conference organizers are probably a little bit busy, so when you reach out to them, you might not hear back immediately. Sometimes you might not be able to get a spot, but be persistent, build a relationship, and eventually you’ll be invited out to speak.

If you really need help with speaking and you want to be doing this, I can’t recommend this group enough. It’s a meetup group called Toastmasters.

Screen Shot 2015-03-25 at 7.36.32 PM

They don’t really care about what you’re talking about. They’re just there to help you get better at talking and putting together presentations.

Speaking of meetups, there’s meetup.com. You can go on here, search for interests, and find local meetup groups. Usually they’re professionals and hobbyists that get together, really non-committal.

This is a picture of me with some of the guys from Ohio at 360|iDev last year.

Screen Shot 2015-03-25 at 7.29.03 PM

I still keep in touch with these guys. I went to NSCoder and a CocoaHeads meetup group. It’s awesome, really good friends. I love just showing up and getting into arguments about Interface Builder versus code.

Sometimes I’ll bring my laptop and be like, “I can’t figure out this bug. I need some help,” or “Hey, I’ve made this really sweet animation.” Somebody will look at it.

One of the things I loved the most was inviting or introducing new people, either new to the area or new to iOS and getting them up to speed, because there’s nothing like face-to-face interaction.

You Can Do It! – Open Source

One last thing that you could be doing is open source.

Now open source to me is kind of a personal subject. I think that my contribution to open source has led to me getting better as an engineer and it’s really contributed to some of the opportunities that I’ve been presented with.

At Facebook, working on AsyncDisplayKit, I learned so much in the past 2 months. I’ve actually been able to apply computer science skills that during university, I would have never imagined I’d ever use any of this theory stuff again.

I’ve learned about collaborating with other engineers and I’ve actually learned a bit about public relations, communicating publicly with other people external to your organization.

Open source, just like speaking, was not something that just came naturally. It’s super intimidating.

Screen Shot 2015-03-25 at 8.37.11 PM

When I write a line of code, I write that line my way. I name my variables my way, my methods.

Other people out there could write that same line of code. They’ll do the exact same thing thousands of other ways, but I wrote it like that because that’s how my brain works.

Then I publish that work, I’m publishing my brain. It’s like a window into how I think. That makes me super vulnerable, especially when people are going to throw criticism.

But it’s a healthy exercise. You get better at it. You learn to take feedback and criticism and you learn from other people.

Honestly, right now is probably one of the best times to be contributing to open source, especially in iOS. These guys, CocoaPods, have set the iOS open source world on fire.

Screen Shot 2015-03-25 at 8.07.53 PM

It’s so easy to build something and let somebody else install it, try it out, and integrate it with their project. Just think about how many working hours AFNetworking has saved the world.

Whenever I do an open source project, for me personally, I’m an interface guy. I like shiny things.

Here’s what I’ll do:

  • Get Inspired. I’ll find something on this designer social network called Dribbble, some sort of animation or something.
  • Build it. I’ll pull it down, I’ll build the project in a weekend or 2, and then I’ll publish it.
  • Release it. I’ll write a readme and make some fancy gifs that catch people’s eyes or something, and then release it.
  • Maintain it? Sometimes I’ll come back and maintain it, or sometimes I won’t.
One of my recent projects.

One of my recent projects.

I really love doing this. I love doing interface work, because that gets me excited.

That’s really important about whatever you decide to do, is that you should love it. You don’t want to be releasing mediocre work, because if you release mediocre work, that could be harmful and that’s not what we want to be doing.

Especially when anybody in our industry asks, “What should I be doing to boost my portfolio and get better,” because maybe they’re going out to interview or something, I always say,

“Try and do something open source. Just get used to it. Put something out there that you really care about.”

Tips and Tricks

Enough about all the different things that you could be doing. Let’s talk about some tips.

Do the simple thing first

Specifically at Facebook, I work on Instagram. One of Instagram’s values is to do the simple thing first. I think that’s really important.

If you’re going to be writing, don’t edit for weeks on end. If you’re going to be building an open source project, don’t write unit tests into the ground.

Just get it out there and think of it, your project or your blog post or whatever, as a minimal viable product. Focus on shipping.

Set goals

It’s really important to be setting goals for yourself, setting dates.

Screen Shot 2015-03-25 at 8.16.58 PM

My wife would be able to tell you that if I don’t set a date on something, I will never do it.

Don’t burn out

Don’t be aggressive on this. If you’re going to be building an open source project, just limit it to 2 weekends. If you’re going to be going to meetups, just go once a month.

You’ve got priorities. You’ve got a job. You’ve got a family. Don’t burn yourself out.

Be authentic

Be your authentic self. Phonies suck. I’m sure we’ve met them. It’s not fun. It feels like an impostor. Don’t be that guy. Really care about what you’re doing and release good work.

Have humility

Lastly, remember to always have humility in whatever you do. It’s really, really important that our community remains humble. Remember that there’s always somebody out there that’s going to have less experience than you do, and there’s also always going to be somebody that’s smarter than you.

Just keep that in mind whenever you’re releasing work. Don’t put too much stress on it. Don’t burn yourself out. Be patient, and remember what they say when you teach a man to fish.

Jeff Atwood has a pretty nice quote. “No matter how much ‘karate’ you know, someone else will always know more.” Paul Graham has another great quote:

“If you want to build great things, it helps to be driven by a spirit of benevolence.”

I’m really excited to be here and I’m really appreciative that you all came to hear my talk. I’m really happy to be giving back to this community that helped me get started.

Start Contributing

No matter what you do, if it’s tweeting or speaking or open sourcing, just remember that your experiences are uniquely valuable.

Remember I wrote this:

var photos = [PhotoModel]()
 
let options = [(kCGImageSourceShouldCache as String) : false]
 
if let imageURLs = fm.contentOfDirectoryAtPath(path, error: &error) as? [String] {
  for fileName in imageURLs {
    if let URL = NSURL(fileURLWithPath: path)?.URLByAppendingPathComponent(fileName) {
      if let imageSource = CGImageSourceCreateWithURL(url, nil) {
        if let imageProperties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, options) as? PropDictionary {
          if let exif = imageProperties[kCGImageProperityExifDictionary] as? PropDictionary {
            if let OriginalDateString = exif[kCGImagePropertyExifDateTimeOriginal] as? String {
              if let date = df.dateFromString(originalDateString) {
                photos.append(PhotoModel(title: fileName, imagePath: url, dateTaken: date))
              }
            }
          }
        }
      }
    }
  }
}

…but I’m up here. Writing that doesn’t stop me from getting up here and it shouldn’t stop you either. I want you to get out there and start sharing your ideas.

I can’t wait to hear what you have to say.

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

RWDevCon Inspiration Talk – Contributing by Ryan Nystrom is a post from: Ray Wenderlich

The post RWDevCon Inspiration Talk – Contributing by Ryan Nystrom appeared first on Ray Wenderlich.

Video Tutorial: Intermediate Swift Part 5: Closures

Reveal Tutorial: Live View Debugging

$
0
0
Learn how to inspect your view hierarchy with Reveal!

Learn how to inspect your view hierarchy with Reveal!

It’s also no secret that debugging user interfaces in iOS can be a pain.

While using LLDB is great for debugging code, it doesn’t really lend itself to debugging the visual hierarchy of your app.

Fortunately, there are tools for visual debugging. One such tool, Reveal, is an extremely powerful visual debugger built by the team at Itty Bitty Apps.

Much like how Safari’s web inspector allows you to inspect and manipulate the DOM of a webpage, Reveal allows you to do the same with the view hierarchy of your app.

This tutorial will show you how to leverage Reveal for inspecting and debugging a complex interface, and will feature Artsy – an app made by a team of engineers that includes fellow tutorial team member Orta Therox!

Getting Started

First you’ll download and compile the source for Artsy from Github.

To do this, open the Terminal app, switch to the directory of your choice, and enter the following commands:

git clone https://github.com/artsy/eigen.git
cd eigen
git checkout 2d9bfb8fba58e6ec0f2f3a18da7fbf45aaef6ba8
bundle install
make oss
bundle exec pod install
open Artsy.xcworkspace

Note: This is a simplified version of the instructions found in the README file for Artsy. In order to build Arsty you’ll also need the following dependencies installed:

  1. CocoaPods: Learn about it in our Introduction to CocoaPods tutorial.
  2. Bundler: Bundler is a dependency manager for Ruby and you can install it via the command gem install bundler after you’ve installed Cocoapods

Note: If you have trouble installing nokogiri, this should fix it (courtesy StackOverflow):

brew install libxml2
bundle config build.nokogiri "--use-system-libraries --with-xml2-include=/usr/local/opt/libxml2/include/libxml2"
bundle install

The clone command will clone the Artsy repository, and checkout will point the Git repository to commit 2d9bfb8fba58e6ec0f2f3a18da7fbf45aaef6ba8 which is the commit I used at the time this tutorial was written, so there are no discrepancies between the latest version and the version I used to write this.

Once Artsy opens in Xcode, select the iPhone 6 Plus simulator and then build and run to verify everything works. You’ll see this splash screen:

Splash Screen

Continue to use the iPhone 6 Plus simulator for the remainder of the tutorial as it’s provides the biggest screen and is therefore perfect for view debugging.

Next, you’ll learn how to connect Artsy to Reveal for view debugging.

Integrating Reveal

Head over to the Reveal download page and click Download Trial to grab the trial version of Reveal – or if you’re already sold on the idea at this point then go ahead and click Buy Now at the top-right side of the page. :]

Unzip the downloaded archive and then drag Reveal.app into your Applications folder.

Now open Reveal – a quick and easy way is to trigger Finder by pressing ⌘+space and typing in “Reveal” – and you’ll see a first-launch splash screen. If you’d like, take some of the guided tours — don’t worry, we’ll wait for you.

After dismissing the splash screen, you’ll see Reveal’s main interface. At the moment it’s empty:

01

You’ll remedy that in a moment when you integrate Reveal into the Artsy app.

In a nutshell, Reveal needs to run some code in your app so it’s able to communicate with it via Bonjour. There are a few options for adding the Reveal framework to your app:

  • By statically linking the framework into your executable using Reveal.framework — this is the easiest and most common way to do this.
  • By dynamically linking the framework into the app at runtime using libReveal.dylib — this can give you more control over when the library loads into your application.
  • Using CocoaPods to import Reveal as a dependency.

For this tutorial, you’ll statically link the framework since it’s the most efficient approach. For detailed instructions on how to use the other methods, head on over to Reveal’s integration page.

  1. Make sure Reveal is the selected window and navigate to Help\Show Reveal Library in Finder. A Finder window will appear showing both the static library named Reveal.framework and the dynamic library named libReveal.dylib:
  2. 02

  3. Drag Reveal.framework into the Frameworks group in the Project Navigator in Xcode. Check Copy items if needed, and check the Artsy target. Finally click Finish:
  4. 03

  5. Select the Artsy project in the Project Navigator, then go to Build Phases\Link Binary with Libraries, and add libz.dylib by clicking the + in the lower-left corner. Enter libz into the search box, and then select libz.dylib and click Add:
  6. 04

  7. Delete the app from the simulator, then build and run. When it’s running you should see Artsy (iPhone Simulator) in the connection dropdown in the top-left of the Reveal app:
  8. 05

At this point, everything is ready for you to start debugging the view heirarchy.

In the connection dropdown, select Artsy (iPhone Simulator). The Reveal app will finally light up!

Screen Shot 2015-03-25 at 11.00.38 PM

Refreshing Reveal

You’re currently looking at a layered view of Artsy’s current view hierarchy. It’s important to emphasize current because any changes to the app’s view hierarchy outside of Reveal won’t be reflected until you refresh the hierarchy.

To see this in action, tap the SIGN UP button in Artsy. You’ll see the app navigate to the sign up view, but Reveal still shows the original splash screen.

To remedy this, click the refresh button in the top-right corner of the Reveal app, and voila, the view hierarchy updates to show new sign up view.

RefreshButton2

Tap the back button to return to the splash screen, and click Refresh again in Reveal. You’ll become very familiar with this navigate/refresh/debug cycle as you learn how to use Reveal.

A Quick Tour of Reveal

Next let’s take a quick tour of Reveal, looking in detail at the three panes that make up the window — the center pane, the left pane and the right pane.

The Center Pane

The center pane is the layered view of the current view hierarchy. Click+Drag anywhere in the center pane, and you’ll see the view hierarchy rotate in 3D. You’ll also notice Reveal adds a bit of space between each layer to help you visualize the view-subview relationships:

View hierarchy rotating in 3D

On the top of the center pane, you’ll also see 3 controls:

  • A segmented control with three icons that look like picture frames. From left to right, these show View Wireframes, View Contents and View Both. A view’s wireframe is just a thin border around a view, and it’s useful when you want to understand how a view is positioned on the screen.
  • A dropdown that shows the size of the view hierarchy’s future render; note that it’s relative to the native size.
  • Another segmented control that switches between 2D and 3D perspectives. 3D is the default, and what allowed you to rotate the view heirarchy a few moments ago.

The Left Pane

The left pane shows the view hierarchy, where each entry is labelled by it’s subclass. Scan up and down and you’ll see a mix of instances of UIView and instances of private UIKit view subclasses:

The left pane.

Scroll to the top, and you’ll see the root of the entire hierarchy is an instance of UIScreen, which you can then trace down to any child view. Back in the center pane, tap the SIGN UP button on the splash screen to select it.

You’ll see the corresponding ARWhiteFlatButton is also selected in the left pane — this also works the other way around. Now find where that button lies by traversing up the heirarchy until you get back to the root UIScreen.

A few purple lines appeared when you tapped the SIGN UP button in the center pane. This is a new feature introduced in Reveal 1.5 that lets you visualize Auto Layout constraints. You’ll find out more about how those work shortly.

AutoLayoutConstraints

The Right Pane

The right pane is what you’ll use to edit or debug the view hierarchy, and the organization is similar to Interface Builder’s inspector panes:

The right pane

The right pane has five tabs:

  1. Application Inspector: This provides application-wide information such as the device you’re connected to, the OS version, and even the current orientation!
  2. Identity Inspector: This shows the object of the node you select, such as class, memory location and accessibility information. One useful tool you’ll find here is View Controller, which displays the view controller that owns the selected view, provided it’s the root view within that view controller.
  3. Attributes Inspector: This shows some of the public properties for every class in that object’s class hierarchy, much like Interface Builder. If it’s a UILabel, for example, the top section will have attributes such as Text and Font. Further down — which ironically is actually moving up in the class hierarchy — you’ll see a section for UIResponder where you can see if the view is currently the first responder.
  4. Layout Inspector: This is where you’ll see the frame, bounds, auto-resizing mask and Auto lLayout characteristics, such as content hugging values and intrinsic content size.
  5. Layer Inspector: Like the name implies, this is where you access the view’s CALayer. Here you can view and edit the layer’s border, corner radius, and even if the layer should rasterize it’s contents.

Viewing Layout Constraints

Select the SIGN UP button by tapping it in the center pane. Next, expand the node of the corresponding ARWhiteFlatButton in the left pane to view its children.

You’ll find a Constraints node, along with the rest of the view hierarchy, that contains the layout constraints belonging to that view. If you expand it, you’ll see the button has two constraints that pin it’s width to 280 points and it’s height to 44 points:

AutoLayoutConstraints2

In the right pane, open the Layout Inspector – the fourth tab – and scroll to the bottom until you see the Participating Constraints section, which contains the same two constraints that belong to the LOG IN button, as well as two others that dictate the position of the UIButton:

ParticipatingConstraints

You may notice that the two size constraints are blue, and the other two constraints are purple.

  • Blue: Represents constraints generated automatically
  • Purple: Represents constraints added manually by the developer

In this case, blue represents the intrinsic content size of the button, which is why the system automatically created these constraints.

The purple constraints are created by the developer, and are related to the positioning of the label inside the button.

Inspecting Artsy’s Splash Screen

While a brief tour of Reveal is great for getting started, using it to debug a running app will really reveal the true value of this tool.

That's So "Punny"!

One of the best uses of Reveal is to help a developer understand the structure of an app’s interface. Since it’s likely you’re not overly familiar with Artsy, it’s a great example to demonstrate this.

Make sure Reveal is showing the Artsy splash screen, and providing you’ve not gone ahead and signed up, you’ll still see the the options to sign up or proceed without an account.

Select the 3D option at the top of the center pane, and make sure the zoom level is set so you can see the entire view hierarchy:

Screen Shot 2015-03-25 at 11.10.31 PM

First, you need to find out what view controller is responsible for the current view.

Activate the Identity Inspector in the right pane – the second tab – and click somewhere in the background view of the splash screen. In the left pane, you’ll see this view is now highlighted in the hierarchy:

Any view you select in the center pane will be reflected in the left pane.

In the right pane, you’ll see the Identity Inspector populate with the selected view’s details. More importantly, toward the bottom of the pane, the View Controller field is populated with the name of the splash screen’s view controller: ARSignUpSplashTextViewController.

Reveal will allow you to see the view controller responsible for a view.

Note: The view you select when you click in the center pane will be the topmost view under your mouse pointer. This is, of course, not necessarily the root of a view controller; for example, it could be a background image that covers the view. Sometimes, you need to traverse up the hierarchy in the left pane to find the root view, and thus the corresponding view controller.

In the center pane, there are some images peeking out of the bottom of the hierarchy that aren’t visible when looking at the app. Get a better look by clicking and dragging to the left in the center pane until the views are rotated about 45 degrees:

Rotate the views to get a better look at views that are hidden.

Interesting. There’s quite a bit hiding beneath the covers! What you see is an entire view already rendered underneath the splash screen. So, what’s going on here?

The displayed hierarchy is a bit messy to behold with so many layers. It would be much easier to see what’s going on by flattening the splash screen to isolate what presents itself on screen as opposed to what lurks beneath.

To flatten, go to the left pane, locate the view for ARSignUpSplashTextViewController and traverse up the hierarchy. As you move up, collapse the views below by clicking the disclosure triangle to the left of each node:

Collapsing nodes in the left pane will flatten them in the center pane.

Every time you collapse a node in the left pane, you’ll see the corresponding layers and borders around each layer merge in the center pane, making it a bit easier on the eyes. Continue to do this until you’ve collapsed everything up to UITransitionView:

Screen Shot 2015-03-25 at 11.16.09 PM

Select UILayoutContainerView, go back to the Identity Inspector tab in the right pane, and you’ll see the view controller AROnboardingViewController that appears to manage the splash screen and the rest of the startup experience, including the login screen you visited briefly earlier.

As it turns out, the splash screen is presented over some hidden content. Drill down into it to learn how the splash screen is presented with this stunningly low-tech approach. :]

In Xcode, open the Find in Workspace search box by pressing ⇧ + ⌘ + F and search for AROnboardingViewController to find where it’s presented from.

In the search results, look for the instance where it’s created in ARAppDelegate.m. Click on that result and Xcode will navigate to it.

You’ll find the following four lines that create and present the instance of AROnboardingViewController:

AROnboardingViewController *onboardVC = [[AROnboardingViewController alloc] initWithState:state];
onboardVC.trialContext = context;
onboardVC.modalPresentationStyle = UIModalPresentationOverFullScreen;
[self.viewController presentViewController:onboardVC animated:NO completion:nil];

Ah-ha! AROnboardingViewController is actually presented by another view controller, but the interesting twist is the modalPresentationStyle is set to UIModalPresentationOverFullScreen.

This presentation mode was introduced in iOS 8, and the UIModalPresentationStyle documentation reads:

A presentation style where the content is displayed over only the parent view controller’s content. The views beneath the presented content are not removed from the view hierarchy when the presentation finishes. So, if the presented view controller doesn’t fill the screen with opaque content, the underlying content shows through.

Ah, so by using this presentation mode both the presenting view controller’s view heirarchy and the presented view controllers view heirarchy are drawn on screen. Good to know!

Challenge: Changing Modal Styles

Though you may have known about these new modal presentation styles in iOS 8, have you been able to play around with them? Reveal actually helps you visualize the effect you get from using UIModalPresentationOverFullScreen.

Challenge: Change the modalPresentationStyle to UIModalPresentationFullScreen. How can you use Reveal to tell the difference between the two presentation styles?

Solution Inside: Answer SelectShow>

Inspecting Artsy’s Home Screen

You’ve paid enough attention to the splash screen, so it’s time to move on to the home screen.

If you haven’t already, dismiss the splash screen by tapping TRY WITHOUT AN ACCOUNT. The splash screen will dismiss and you’ll see the home screen that you previously saw lurking underneath the splash screen:

06

Take a moment to play around with the contents of the home screen. It’s fairly rich in content, with some artwork in the header and a plethora of controls in the white area below. If you scroll up, you’ll even see the white content scroll over the artwork.

There is clearly quite a bit going on here, but how is it built? Now that you have Reveal at your side, dissecting the view hierarchy will be no problem.

“Revealing” the Home Screen

Back in Reveal, hit the refresh button to update the view hierarchy. You should see Reveal look something like this:

Screen Shot 2015-03-25 at 11.24.32 PM

A couple of things that you’ll notice immediately:

  1. The artwork at the top appears to sit below the content area.
  2. The content area appears to be a UITableView, based on the numerous vertically stacked views, but is still too complex to understand from this vantage point.

It’s a good idea to dive into the table view to get a better idea of its construction.

In Reveal, focus on the table view by rotating the view 45 degrees to the right and clicking on the area below all the content and cells, which will select the instance of ARTopTapThroughTableView:

Screen Shot 2015-03-25 at 11.28.08 PM

Now that you’ve selected the table view, it’s fairly obvious how to achieve the effect where the table view appears to scroll over the content below.

The content view is not part of the table view, but the table view is on top of the content view. The content view is visible because the table view is allowed to scroll down far enough to show it!

With the table view selected, open the Attributes Inspector in the right pane. Scroll down to the UIScrollView section, and you’ll see the Y value of the content offset is -252, which moves the content down far enough to see the content behind it.

Set the Y value to 0, and then watch the content section snap to the top and cover the artwork behind it.

Double-click on the table view in the view hierarchy you just selected. Alternatively, double-click on ARTopTabThroughTableView in the left pane. You’ll see Reveal now focuses on the table view and the rest of the view hierarchy is no longer shown:

Screen Shot 2015-03-25 at 11.30.40 PM

Focusing on a particular view in the hierarchy makes it easier to concentrate on that one area, as well as being easier to navigate. The view hierarchy in the left pane is also much simpler now.

Note: You can return to the full view hierarchy by clicking the back button at the top-left of the Reveal window, or by using the breadcrumb trail that’s along the top.

With all that is going on in this view, it may surprise you that there is just a single UITableViewCell. If you look at the hierarchy in the left pane, there’s just one cell, ARModernPartnerShowTableViewCell, which encapsulates all of the content below CURRENT SHOWS header.

A vanilla UIView contains everything above, and you achieve this by setting a custom tableHeaderView on the table view.

One more observation to makes is that all the cell’s contents don’t reside in it’s contentView, but instead are placed directly inside it’s view.

Dive one level deeper by double-clicking on ARModernPartnerShowTableViewCell in the left pane to focus on the cells construction:

Screen Shot 2015-03-25 at 11.32.13 PM

From this perspective, it’s easy to see how the break down of the heirarchy. There are three separate instances of UILabel that display information about the collection, and a UICollectionView wrapped inside a UIView, which displays a collection of artwork.

There are many methods that you can use to center labels with Auto Layout, but which one did the Artsy engineers use?

Click on the top label and view the Participating Constraints section of the Layout Inspector to see how it’s done:

Screen Shot 2015-03-25 at 11.35.20 PM

Reveal reveals (sorry!) the layout is achieved by pinning the label to the center of its superview, combined with making the width 40 points less than the superview to provide padding.

Two additional constraints seem a bit out of place. Look at the most recent screenshot; there’s one constraint limiting the width to 167.66 and one keeping the height at 19.33. Look at the top of the Layout Inspector tab, and you’ll see that the label’s actual width and height is 280 x 19.333.

What’s happened with these constraints, and where did they come from?

In this case, the width and height in blue represent the intrinsic content size of the label, or in other words, the measured size of the text within the UILabel. Since these are system constraints, they are discarded when laying out the label in favor of those constraints added by the developer.

If you want a reminder of what the colors mean, expand this spoiler.

Solution Inside: Color SelectShow>

Good job! Without ever once touching the source code, you have a pretty good understanding of two of Artsy’s complex and beautiful screens. It looks especially sharp with all that extra real estate on the iPhone 6 Plus, doesn’t it?

Compatibility mode makes the author sad :[

Did you notice something funny a few paragraphs back? The UILabel was 280 points wide and 40 points narrower than the cell it was inside of. That means the width of the screen is only 320 points.

The iPhone 6 Plus should have a width of 414 points, which means Artsy isn’t natively taking advantage of the larger screen.

You’ll fix the project settings so Artsy runs using the native resolution of the 6 Plus, and you’ll use Reveal to debug any layout issues that arise from the changes.

Plus-Size Screen

Enabling native iPhone 6 Plus resolution in projects that existed prior to the iPhone 6 Plus is a bit obscure, and you do it by specifying a Launch Screen xib in the project settings.

In Xcode, create a new Launch Screen xib by selecting File\New\File… and then choosing iOS\User Interface\Launch Screen and clicking Next. Keep the name as Launch Screen and click Create.

Next, select the Artsy project in the Project Navigator. Click the General tab and scroll down to Launch Screen File. In the dropdown, select Launch Screen.xib:

07

Build and run. Voila! There is quite a bit more on the screen now that the app has more pixels to play with:

08

Just to make sure, go back to Reveal and once again click the refresh button, then look at the width of the cell in the Layout Inspector. You’ll see it’s now 414, the full width of the iPhone 6 Plus.

You’ll also notice that overall, the app looks pretty good. Auto Layout is used extensively throughout Artsy, so although it was largely developed before the advent of the iPhone 6, the layout adapts nicely to the new size.

Of course, there are some areas that didn’t fare so well. In the Artsy app, navigate to the YOU tab:

09

While it’s not broken by any means, it doesn’t utilize the full width of the screen, and looks as though it’s set to use a screen width of 320 points. What an excellent place to do some live view debugging!

Live View Debugging

In Reveal, hit refresh to update the view hierarchy with the YOU screen; it should look something like this:

The YOU screen, in Reveal

Right away, you see that the views containing the segmented control and the description are constrained.

Simplify your perspective by rotating the view hierarchy in the center pane 45 degrees. Then double-click on the white space to grab the visible view, and to discard the numerous nested views and navigation elements.

The view you selected should be a UICollectionView:

Select YOU view with help by rotating.

Oftentimes it’s easier to debug constraints in Wireframe Mode, which shows just the view’s boundaries and the layout constraints. So, at the top of the center pane, press the left-most button on the left segmented control. Then rotate the view back so you’re looking at it from the front:

Wireframe mode

You’re now looking at a focused view of the YOU screen, which shows only the view boundaries and layout constraints.

To figure out how the segmented control is sized, simply click one of the segmented control buttons in Reveal and observe the participating constraints in the Layout Inspector.

Tip: The class name should be UIButton.

Look for what’s controlling the width; you’ll see that it’s constrained to the width of the ARSwitchView with a multiplier of .33.

In other words, the width is a third of the containing switch view. Since that seems reasonable, it’s logical to assume the width of ARSwitchView is hardcoded.

Confirm this by selecting ARSwitchView – it’s one level up in the view hierarchy – and observe it’s constraints. There are quite a few, but the height and width constraints have clear labels:

ARSwitchView height and width

The height constraint is blue so it’s added by UIKit, but the width constraint is purple and therefore added by the developer, and is currently set to 279 points. At this point, it’s clear that this is the culprit causing the overly narrow controls.

You could assume that the design called for about 20 points of margin on each side of the control, but before diving into a heavy code-build-debug cycle, start by leveraging Reveal’s live view debugging to make sure it looks the way you intend.

Expand the width constraint in the Participating Constraints section to view its details:

Constraint details

Note: The priority field of the constraint is disabled because the priority of this constraint is 1000, which makes it a required constraint. If it was created with a priority less than 1000, it would be editable at runtime in Reveal.

To maintain margin parity with the previous screen size, the switch view should be 41 points narrower than the screen. Since you’re running the iPhone 6 Plus simulator, you’ll want a width of 373.

In the Constant field of the constraint, change the value from 279 to 373, and the wireframe will snap to the new size.

Now do the same for the label below, which will be a bit simpler. Click on the containing view, and find the width constraint. Then, change the constant from 270 to 364 and you’ll see that views size update again.

Go back to the simulator and check out the app now. You’ll see all the views are updated – yes, this is all in real time – and observe the effect of the new constraints you added without touching a single line of code!

10

Live debugging can greatly reduce your code-build-debug cycle, and even allows you to experiment with your design in real time.

Where To Go From Here

Well, this tutorial is done, and you should reward yourself for working through it! Try plugging one of your colleague’s apps into Reveal and see what you can find.

I bet you find a few holes here and there, and can even find ways to improve it with the powerful real-time view debugging. Then share what you find and get your colleague to buy you a beer or few in exchange for your valuable insight.

To view a thorough list of all the features Reveal supports, check out their Features page.

Also, have a look at the Release Notes for Reveal 1.5 to get more detailed descriptions of all the new features.

Finally, I recommend you check out this video of Sean Woodhouse from Itty Bitty Apps giving a live demo of Reveal in action.

I’d love to hear your take on Reveal 1.5, what you’ve learned as you’ve explored it, and of course, any questions that arose as you worked through this tutorial. Please leave your notes, brags, discoveries and questions below so that we can all learn together.

Reveal Tutorial: Live View Debugging is a post from: Ray Wenderlich

The post Reveal Tutorial: Live View Debugging appeared first on Ray Wenderlich.

Video Tutorial: Intermediate Swift Part 6: Access Control

Video Tutorial: Intermediate Swift Part 7: Initializers

UIKit Dynamics and Swift Tutorial: Tossing Views

$
0
0
Learn how to toss your views with gestures and physics behaviors in this UIKit Dynamics tutorial!

Learn how to toss your views with gestures and physics behaviors in this UIKit Dynamics tutorial!

Update note: This tutorial was updated to Swift and iOS 8 by Bjørn Ruud. Original post by Tutorial Team member Tony Dahbura.

In this UIKit Dynamics tutorial, you’ll learn how to toss views off-screen with gestures in a natural feeling way.

You may have seen this technique popularized in the popular app Tweetbot.

This tutorial is a good fit for intermediate developers because it covers some neat effects, such as rotation and fly-away animations using the native UIKit framework.

But if you’re completely new to UIKit dynamics, don’t fear – this tutorial will guide you through step by step.

Without further ado, let’s get to tossing!


Note from Ray: Full credit for this technique goes to Orta Therox, the newest member of our new “Code Team” at raywenderlich.com. Orta created the original sample project that Tony polished and converted into this tutorial.

The Code Team is a group of expert-level coders that spend their waking hours coming up particularly cool demos to demonstrate advanced techniques. The Tutorial Team then converts the best demos into high quality tutorials. If you’re an expert-level iOS developer and joining the Code Team piques your interest, check out the details and get in touch!

Getting Started

Note: This section is optional for those who want to make the project from scratch. Experienced iOS developers might want to skip this section and proceed to the next section, “UIDynamicAnimator and UIAttachmentBehavior” where we have a starter project waiting for you.

Start up Xcode, select File\New\Project…, choose iOS\Application\Single View Application template, and click Next. Name the project DynamicToss, make sure the selected language is Swift, and set the device family to iPhone.

Now select the project name on the left and select the General at the top of the Xcode window. Under Deployment Info/Device Orientation uncheck the Landscape Left and Landscape Right checkboxes, because your app will only run in portrait mode.

dynamictoss-orientation

Next, download an image that you’ll need for this project, courtesy of gameartguppy.com.

goldfish_feature

Unzip the file and add it to the Images asset catalog in your project.

Next, select Main.storyboard and go to the File Inspector in the utilities area on the right. To keep the scope of this tutorial small you will not use auto layout and size classes, so untick the Use Auto Layout checkbox. This will also disable size classes. In the dialog box that appears, choose to keep size class data for iPhone and select Disable Size Classes.

In the storyboard, add an image view to the default view controller and set the image to goldfish_feature. In the size inspector for the image view, set the following values: X=33, Y=137, Width=254, Height=172. Also, change the autoresizing mask to disable flexible height, width, right, and bottom margins. That means only the top and left margins stay “selected”.

Your screen should now look like this:

dynamictoss-imageview

Next, drag two plain Views into your view controller that you will use to help track your gestures. Set them to the following settings:

  • View 1: (X=156, Y=219, Width=8, Height=8, Background=red)
  • View 2: (X=80, Y=420, Width=8, Height=8. Background=blue)

When done your view should look like this:

dynamictoss-views

That covers the views you’ll need to set up in the storyboard. Next: on to some code!

Touch Handling

Open ViewController.swift and add the following properties to the class:

@IBOutlet weak var imageView: UIImageView!
@IBOutlet weak var redSquare: UIView!
@IBOutlet weak var blueSquare: UIView!
 
private var originalBounds = CGRect.zeroRect
private var originalCenter = CGPoint.zeroPoint
 
private var animator: UIDynamicAnimator!
private var attachmentBehavior: UIAttachmentBehavior!
private var pushBehavior: UIPushBehavior!
private var itemBehavior: UIDynamicItemBehavior!

You’ll connect the outlets in a moment. The other properties will control the image view’s movement and keep track of its state as the touch events go on.

Open Main.storyboard and right click (or control-click) on the View Controller. Drag from the circle to the right of the outlet named blueSquare onto the small blue square view and release the mouse. This links the property to the view object.

Do the same for the red square, and finally for the property named imageView, drag onto your jetpack-equipped goldfish. Your three view properties should now be linked, like this:

finallinking

The red and blue squares will represent points that the UIKit dynamics physics engine uses to animate the image.

The blue square will simply represent where your touch began, i.e., where your finger first made contact with the screen. The red square will track your finger as it moves.

You’ll configure the dynamics so that when you move that point around, the image view physically animates to move in tandem.

There’s one final thing you need to do – set up a gesture recognizer for the view. Open ViewController.swift and add this new method to the file:

@IBAction func handleAttachmentGesture(sender: UIPanGestureRecognizer) {
  let location = sender.locationInView(self.view)
  let boxLocation = sender.locationInView(self.imageView)
 
  switch sender.state {
  case .Began:
    println("Your touch start position is \(location)")
    println("Start location in image is \(boxLocation)")
 
  case .Ended:
    println("Your touch end position is \(location)")
    println("End location in image is \(boxLocation)")
 
  default:
    break
  }
}

You’re going add a gesture recognizer to detect dragging, aka panning, and call this method when panning occurs. For now, this method simply displays the position of your finger in two coordinate systems (the view, and the image view).

To add the gesture recognizer, open Main.storyboard and drag a Pan Gesture Recognizer onto the View. Then control-drag from the Pan Gesture Recognizer up to your View Controller, and connect it to the handleAttachmentGesture: action.

Now build and run. Swipe or drag across the screen and you should see messages coming out on the debug window:

Your touch start position is (125.0,227.0)
Start location in image is (92.0,90.0)
Your touch end position is (195.5,374.0)
End location in image is (162.5,237.0)

Great! You’ve got the basic UI set up – now it’s time to make it dynamic.

UIDynamicAnimator and UIAttachmentBehavior

Note: If you skipped ahead from the previous section, download the starter project to continue from this point.

The first thing you want to do is make the image view move as you drag it. You will do this with a type of UIKit Dynamics class called a UIAttachmentBehavior.

Open ViewController.swift and place the following code in viewDidLoad(), below super.viewDidLoad().

animator = UIDynamicAnimator(referenceView: view)
originalBounds = imageView.bounds
originalCenter = imageView.center

The above code sets up a UIDynamicAnimator, which is UIKit’s engine for physics-based animation. You provide the view controller’s view as a reference view which defines the coordinate system for the animator.

You add behaviors to an animator, which allow you to do things like attaching views, pushing views, making them be affected by gravity, and more.

You’ll start with a UIAttachmentBehavior, to make the image view track your finger when you make a pan gesture.

To do this, add the following code to handleAttachmentGesture(sender:), underneath the two println statements in the case .Began: section:

// 1
animator.removeAllBehaviors()
 
// 2
let centerOffset = UIOffset(horizontal: boxLocation.x - imageView.bounds.midX,
                            vertical: boxLocation.y - imageView.bounds.midY)
attachmentBehavior = UIAttachmentBehavior(item: imageView,
    offsetFromCenter: centerOffset, attachedToAnchor: location)
 
// 3
redSquare.center = attachmentBehavior.anchorPoint
blueSquare.center = location
 
// 4
animator.addBehavior(attachmentBehavior)

Let’s go over this section by section:

  1. First you remove any existing animation behaviors that might be hanging around.
  2. Next, you create a UIAttachmentBehavior that attaches the the point inside the image view where the user taps to an anchor point (which happens to be the exact same point). Later on, you will change the anchor point, which will cause the image view to move.

    Attaching an anchor point to a view is like installing an invisible rod that connects the anchor point to a fixed attachment position on the view.

  3. Update the red square to indicate the anchor point, and the blue square to indicate the point inside the image view that it is attached to. When the gesture starts, these will be the same point.
  4. Add this behavior to the animator to make it take effect.

Next you need to tell the anchor point itself to follow your finger. In handleAttachmentGesture(_:), replace the break statement in the default: case with the following code:

attachmentBehavior.anchorPoint = sender.locationInView(view)
redSquare.center = attachmentBehavior.anchorPoint

The default case handles the gesture update calls as the user pans around. The code here simply aligns the anchor point and red square to the finger’s current position. When the user’s finger moves, the gesture recognizer calls this method to update the anchor point to follow the touch. In addition, the animator automatically updates the view to follow the anchor point.

Build and run, and you are now able to drag the view around:

Dragged View

Notice how the view isn’t just translated around the screen; if you start the gesture in a corner of the image, the view will rotate as you move it because of the anchor point.

However it would be nice to return the view back to its original position when you’re done dragging. To fix this, add this new method to the class:

func resetDemo() {
  animator.removeAllBehaviors()
 
  UIView.animateWithDuration(0.45) {
    self.imageView.bounds = self.originalBounds
    self.imageView.center = self.originalCenter
    self.imageView.transform = CGAffineTransformIdentity
  }
}

Then call this in handleAttachmentGesture(_:), below the println calls in the .Ended: section:

resetDemo()

Build and run, and now after you drag an image it should revert to its original position.

UIPushBehavior

Next, you need to detach the view when you stop dragging, and endow it with momentum so that it can continue its trajectory when you release it while in motion. You will do this with a UIPushBehavior.

First, you’ll need two constants. Add these to the top of the file:

let ThrowingThreshold: CGFloat = 1000
let ThrowingVelocityPadding: CGFloat = 35

ThrowingThreshhold indicates how fast the view must be moving in order to have the view continue moving (versus immediately returning to its original spot). ThrowingVelocityPadding is a magic constant that affects how fast or slow the toss should be (this was chosen by trial and error).

Finally, inside handleAttachmentGesture(_:), replace the call to resetDemo() inside the .Ended case with the following:

animator.removeAllBehaviors()
 
// 1
let velocity = sender.velocityInView(view)
let magnitude = sqrt((velocity.x * velocity.x) + (velocity.y * velocity.y))
 
if magnitude > ThrowingThreshold {
  // 2
  let pushBehavior = UIPushBehavior(items: [imageView], mode: .Instantaneous)
  pushBehavior.pushDirection = CGVector(dx: velocity.x / 10, dy: velocity.y / 10)
  pushBehavior.magnitude = magnitude / ThrowingVelocityPadding
 
  self.pushBehavior = pushBehavior
  animator.addBehavior(pushBehavior)
 
  // 3
  let angle = Int(arc4random_uniform(20)) - 10
 
  itemBehavior = UIDynamicItemBehavior(items: [imageView])
  itemBehavior.friction = 0.2
  itemBehavior.allowsRotation = true
  itemBehavior.addAngularVelocity(CGFloat(angle), forItem: imageView)
  animator.addBehavior(itemBehavior)
 
  // 4
  let timeOffset = Int64(0.4 * Double(NSEC_PER_SEC))
  dispatch_after(dispatch_time(DISPATCH_TIME_NOW, timeOffset), dispatch_get_main_queue()) {
    self.resetDemo()
  }
} else {
  resetDemo()
}

Let’s go over this section by section:

  1. Ask the gesture for the velocity of the drag.

    Using velocity and your old friend the Pythagorean theorem, you compute the magnitude of the velocity — which is the hypotenuse of the triangle formed from the x direction velocity and the y direction velocity.

    To understand the theory behind this check out this Trigonometry for Game Programming tutorial.

  2. Assuming the gesture magnitude exceeds your minimum threshold set up for the action, you set up a push behavior.

    A push behavior applies a force to the specified items. In this case, it’s an instantaneous force against the image.

    The desired direction is composed of the x and y velocities converted to a vector that gives the directional portion. Once you have the push behavior set up, you add it to the animation sequence.

  3. This section sets up some rotations to make the image “fly away”. You can read up on the complicated math here.

    Some of this depends on how close to the edge your finger is when it initiates the gesture.

    Play around with the values here and watch how the movements change the effects. The values used give a nice, flowing rotation with a cool spinning effect!

  4. After a specified interval of time, the animation resets by sending the image back to its destination, so it zips off and returns to the screen — just like a ball bouncing off a wall!

Build and run, and you should now be able to toss your view offscreen in a pleasing manner!

Learn how to make tossable views with UIKit Dynamics!

Where To Go from Here?

Here is the final example project from this UIKit Dynamics tutorial.

Congratulations, you’ve now learned how to do some fancy UIKit dynamic animations that can give an app’s UI some pretty sweet effects.

If you want learn more about UIKit Dynamics, check out the two UIKit Dynamics chapters in iOS 7 by Tutorials.

Drop by the forums or leave a comment below to share your successes or ask questions about making cool animations in iOS. And use your new powers wisely!

UIKit Dynamics and Swift Tutorial: Tossing Views is a post from: Ray Wenderlich

The post UIKit Dynamics and Swift Tutorial: Tossing Views appeared first on Ray Wenderlich.

Video Tutorial: Intermediate Swift Part 8: Generics


iOS Games by Tutorials Updated for Swift 1.2

$
0
0

SKT-v2.3-Thumb

Good news – we have updated iOS Games by Tutorials for Swift 1.2!

As you may know, Swift 1.2 introduced some new syntax, such as an improved if let statement, and revised usage of as vs as! vs as?. To learn more about these changes, check out our What’s New in Swift 1.2 overview.

In this update, we have updated all chapters and sample code to use the new Swift 1.2 syntax, and has also fixed some of the errata reported on the forums.

Here’s how you can get the update:

  • If you’re an iOS Games by Tutorials PDF customer, you can download the update for free on your My Loot page (version 2.3).
  • If you’re an iOS Games by Tutorials Print Version customer, you can find the updated source code at the URL given in the introduction of the book.
  • If you don’t have the iOS Games by Tutorials yet, grab your copy now!

We hope you enjoy this update!

iOS Games by Tutorials Updated for Swift 1.2 is a post from: Ray Wenderlich

The post iOS Games by Tutorials Updated for Swift 1.2 appeared first on Ray Wenderlich.

Video Tutorial: Intermediate Swift Part 9: Memory Management

Swift by Tutorials Updated for Swift 1.2

$
0
0

SWT-Thumb

Good news – Colin and Matt have updated Swift by Tutorials for Swift 1.2!

As you may know, Swift 1.2 introduced some new syntax, such as an improved if let statement, and revised usage of as vs as! vs as?. To learn more about these changes, check out our What’s New in Swift 1.2 overview.

In this update, Colin and Matt have updated all chapters and sample code to use the new Swift 1.2 syntax, and have also fixed some of the errata reported on the forums.

Here’s how you can get the update:

  • If you’re an Swift by Tutorials PDF customer, you can download the update for free on your My Loot page (version 1.4).
  • If you’re an Swift by Tutorials Print Version customer, you can find the updated source code at the URL given in the introduction of the book.
  • If you don’t have the Swift by Tutorials yet, grab your copy now!

Colin, Matt, and I hope you enjoy this update!

Swift by Tutorials Updated for Swift 1.2 is a post from: Ray Wenderlich

The post Swift by Tutorials Updated for Swift 1.2 appeared first on Ray Wenderlich.

RWDevCon Inspiration Talk – Identity by Vicki Wenderlich

$
0
0

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

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


Transcript

Have any of you ever been at a conference or a party and had somebody walk up to you and say, “Hey it’s good to see you again.” And you look at them and you smile, but you’re thinking, “Who are you?”

Unless you’re really drunk, you usually figure out who it is. It’s just somebody you met earlier and forgot.

For me, there’s another option. Sometimes I realize that no, I have never met this person in my life. What I realize is that they’ve met my twin sister, Andrea.

Andrea, would you come up here for a moment?

How many of you have confused the two of us at this conference?

Can you tell which one is Vicki?

How many of you just now realized that there were two of us? If this happened to you, don’t worry. It happens to a lot of people, even including our friends.

I’ve been to a lot of parties at my sister’s house where I’m meeting her friends for the first time. Andrea often forgets to mention to her friends that she has an identical twin, so there are a lot of moments where her friends walk in the door and give me a big hug before I can say, “I’m not Andrea.”

Growing Up As A Twin

This kind of thing doesn’t bother me, but it makes me think a lot about my identity.

Can you imagine just for a moment what it’s like to be indistinguishable from another person, even on a superficial level? It kind of messes with your mind.

Screen Shot 2015-04-01 at 10.30.47 PM

When Andrea and I were young little munchkins, identity didn’t matter much to us. However, as we grew up of course, it did begin to matter.

We wanted to be seen as separate people with our own identities. We often get the question from people, “did you ever switch classes in school?”

The answer is no. We never wanted to be mistaken for each other. We wanted to stand out.

Unfortunately, my sister and I were very similar in both looks and personality, so this was often a losing battle.

Screen Shot 2015-04-01 at 10.31.08 PM

We both played soccer together, we had a lot of the same friends.

Sometimes people would helpfully suggest, “Hey, one of you should dye your hair purple.”

Neither one of us wanted to dye our hair, and plus that person would end up looking like this.

Screen Shot 2015-04-01 at 10.31.28 PM

All it would accomplish is that one of us would be known as the weird twin and one of us would be the normal twin.

At any rate, our acquaintances often couldn’t tell us apart. Classmates, teachers, even soccer coaches. There have been a lot of games where I’ve been standing on the sideline next to my coach, and he’s yelling, “Vicki, pass the ball.”

I have to poke him and say, “Coach I’m right here.”

Inside I saw myself as Vicki, but outside I was just one of the twins.

Screen Shot 2015-04-01 at 10.31.39 PM

Luckily we grew up, we went to college, started having different life experiences and finally being mistaken for my twin became a series of funny stories instead of a frustrating attempt to be seen as an individual.

This, by the way, is why Andrea forgot to mention that she had an identical twin to her friends. She wasn’t trying to instigate awkward moments; she just actually forgot, because being a twin isn’t a big part of her identity.

Identity Problems: It’s Not Just a Twin Thing

You don’t have to be a twin in order to struggle with your identity. In fact it’s a much more powerful force in your life than most of you might realize.

We all have our own personal sense of identity and it’s split into two parts:

  1. Inner identity: This is how we see ourselves. You might think of yourself as a good daughter, or a writer, or an iOS developer.
  2. Outer identity: This is how other people see us. You might actually be helping out your parents a lot, or writing every day or have a day job as an iOS developer.

However, sometimes people see us differently than how we see ourselves. Let’s take this kitten. (There’s got to be a kitten right?)

Screen Shot 2015-04-01 at 10.31.56 PM

When he looks in the mirror, he sees a lion. The problem is, everyone else looks at him and sees a kitten.

Does anybody have a cat like that? My sister does.

Now, kittens aside, a serious problem arises when your inner identity and your outer identity don’t match up. It can make you unhappy.

The discord between the two of them can make you feel like there’s something not quite right. That’s going to make you depressed even if you might not understand why.

Vicki’s Struggle with Identity

This leads us to my next major struggle with identity. After college, I became a ceramic artist. I’d always worked with ceramic art, but after college I threw my whole being into this new identity. It was so fulfilling.

Screen Shot 2015-04-01 at 10.32.16 PM

Unfortunately, it didn’t make much money. Somewhere along the line, I started helping out this cute guy I happened to be married to with his iPhone apps.

Eventually, it got to the point where I was spending more time on his apps and our blog than I was on my own art. Finally, I decided to make the decision to stop trying to make my ceramic art into a business and instead focus on the thriving business that Ray and I already owned.

Now I told myself that I was happy about this decision, but the truth was I was miserable. I resented every minute of it even though the work was interesting and challenging and paid the bills.

Why? This was because my inner identity was still stuck as a ceramic artist.

Every minute that I spent working on the business, I was thinking, I should really be making a sculpture. Why am I wasting my time, wasting my life, on all of this other stuff?

Screen Shot 2015-04-01 at 10.32.28 PM

There was this idea in my head, this identity that I clung to, that I was a ceramic artist. Now it might sound like a small problem, but there was a point that I didn’t want to get up in the morning.

Ray would jump out of bed enthusiastic and ready for the day. I would look at his energy and think, what is wrong with me?

We work from home, so I took every opportunity I could to get out of the house. I would invent errands that I had to go run.

Screen Shot 2015-04-02 at 3.07.34 AM

When I did work at my desk, I would work slowly and reluctantly.

Okay. I know some of you out there are thinking, “What is this girl’s problem? Either work with your ceramic art or work with Ray, but stop moping!”

It didn’t make sense to me either. I knew I didn’t want to go backwards and do my ceramic art and try to keep making that a business, but I couldn’t seem to move forward either. I felt empty and lost.

Ray’s Struggle with Identity

Now, most of the time, Ray is ridiculously enthusiastic about his work, but even he went through his own identity crisis.

He’s a programmer you may have heard. That’s how I got started here. Being a programmer is his identity.

As the business grew, though, he found himself having to shift his time more and more towards management in order to keep things running smoothly. It got to the point where he was hardly doing any programming at all.

Screen Shot 2015-04-02 at 1.10.31 AM

The trouble is, to Ray, the word manager was a dirty word. He subscribed to the very popular programmer belief that managers don’t get any work done.

It’s the programmers that do the real work.

He wasn’t very happy when every time he looked in the mirror he expected to see a programmer and instead he saw a manager.

Do Your Inner and Outer Identities Match?

When your inner identity and your outer identities don’t match up, you can feel false. That’s going to make you feel frustrated, irritable, and depressed.

When your inner identity and your outer identities don't match up, you can feel false. That's going to make you feel frustrated, irritable, and depressed.

When your inner identity does match up with your outer identity, you feel happy and confident because you’re acting in a way that’s true to yourself and your goals.

When your inner identity does match up with your outer identity, you feel happy and confident because you're acting in a way that's true to yourself and your goals.

What do you do if you realize that your inner and outer identities have drifted apart? What do you do when your mirror shows two different reflections?

Screen Shot 2015-04-01 at 10.34.32 PM

You have two choices. You can change your inner identity, or you can change your outer identity.

Option 1: Change Your Outer Indentity

Changing your outer identity means changing what you’re doing on the outside to match what’s happening on the inside. This might mean:

  • Quitting your job
  • Moving to a different location
  • Starting up a hobby
  • Joining a club

If you see yourself as a healthy, fit person and you’re not – we’ve all been there – then you can start up an exercise habit.

If you see yourself as a free spirit, but you’ve been feeling trapped working at a bank, save up your money and finally go on that backpacking trip that you’ve been dreaming about.

If you see yourself as a brilliant app developer, but you haven’t gotten around to learning Swift yet, then come to RWDevCon.

Learn the skills that you need in order to become the person you see inside. Change what’s happening on the outside to match what’s happening on the inside.

Jeff’s Story

A great example of this comes from Jeff Wolski of the raywenderlich.com tutorial team.

Screen Shot 2015-04-01 at 10.35.23 PM

Once upon a time, Jeff taught app development courses at a technical college. He spent his nights and weekends coding.

Did I mention that he also had a wife and two young children? All of these demands on his time took a heavy toll.

At one point, the stress load was so high that he landed in the hospital.

Jeff took this opportunity to reevaluate his life. He realized that he’d always thought of himself as an app developer who used teaching to make money, but in reality, he was a teacher with a coding habit that he didn’t have time for. And a teacher is not what Jeff wanted to be.

Screen Shot 2015-04-01 at 10.35.35 PM

Jeff quit his teaching career of over a decade and became a full time app developer. Of course, that meant he was full time unemployed for a while.

They moved out of their house and back into his mother’s house for a time. It took six months before they could even make rent again.

He worked hard and things improved and now he’s working at a job he loves, making apps.

Screen Shot 2015-04-01 at 10.35.48 PM

It was worth all the stress. His outer identity now matches up with his inner identity as an app developer.

That’s what happens when you’re changing your outer identity to match your inner identity. What about the opposite?

Option 2: Change Your Inner Identity

What if you decide, hey I want to keep my job. I like it. It’s helping me accomplish my goals.

Then you need to change your inner identity.

Changing your inner identity means embracing your outer identity with open arms. It means saying to yourself, “Hey this is who I am – and I like it!”

Screen Shot 2015-04-01 at 10.34.19 PM

Ray’s Solution

In Ray’s case it meant recognizing that managing his team was really important. Somebody needed to do that work.

The alternative to being a manager was shutting the website down completely. Ray didn’t want to do that. He wanted to keep growing the website and growing his company.

He had to change his way of thinking. He had realize that:

  • The manager is the person who keeps things running and organized.
  • That’s really important work.
  • He had to change his inner identity from programmer to manager.
  • He should be proud of being a manager.

Screen Shot 2015-04-01 at 10.36.06 PM

Changing your inner identity is not an instantaneous process. You can’t just flip a switch.

It’s rooted very deeply in your psyche, but it is possible to change your inner identity. It takes three things:

  • Patience
  • Self awareness
  • Words
Note: Words are powerful, so pick out the great things about who you are in reality and write them down. Say them to yourself every day. The way we talk to ourselves is really important.

For Ray, instead of saying to himself, “Another day wasted answering emails,” he learned to say, “I answered a lot of emails today that were really important and all of my team made progress on all of their projects.”

Eventually, your identity will shift to match your words and you’ll feel like your acting true to yourself once more.

Vicki’s Solution

Here’s what those two choices looked like for me:

  • Change my outer identity which meant saying to my husband, “Sorry I am going back to the studio and you are own your own with the business.”
  • Change my inner identity and embrace my new role as an entrepreneur.

I chose the latter because I realized that I liked a lot of what I was doing as an entrepreneur.

I liked creating art that was used and appreciated, like the art that you can see in our books and in our tutorials. Here’s some of the game art I made that I’m particularly proud of.

Screen Shot 2015-04-01 at 10.37.01 PM

I liked learning what it takes to publish books or be a better speaker or run a conference.

It was only this identity as a ceramic artist that I’d been clinging to that was making me really unhappy.

Use Your Words!

Once I realized this I started changing how I talked to myself.

I started purposely picking out the great things about what I was doing and describing what I did in a more positive way.

For example, you might notice that I call myself an:

Screen Shot 2015-04-01 at 10.36.54 PM

I don’t know if I technically fit the description of an entrepreneur, but it makes me sound cool to myself and it’s a lot shorter than saying artist, accountant, book publisher, jack of all trades who does whatever is needed to keep the business running.

Once I started shifting my inner identity to being an entrepreneur, I got a lot more excited about my work.

  • Before my inner identity was: I’m an artist, but right now I’m helping out my husband with his business.
  • Now my identity is: I’m an entrepreneur and I can handle anything that comes my way.

See what a difference that makes?

Not Just “One Of The Twins”

Remember back to the beginning of this speech when I was talking about my frustration growing up as a twin? Looking back, that was another case of my inner identity not matching up with my outer identity.

Screen Shot 2015-04-01 at 10.37.16 PM

I saw myself as a wonderful, unique, special snowflake and everybody else saw me as one of the twins. It was the discord between those two identities that caused me so much anguish.

As an adult, I don’t have that problem. Most of the world sees me as very different from my sister, even if they do confuse us still at parties sometimes, or conferences. Being a twin is only one small part of my identity rather than the entire thing.

Don’t worry. If you come up to me and think that I’m my sister, I’m not going to hate you. Just don’t hug me until we get to know each other better. :]

Now It’s Your Turn

My challenge to you today is to take stock of your own inner and outer identities.

Screen Shot 2015-04-02 at 1.19.10 AM

When they match up, it’ll make you happy and confident and successful.

If they don’t match up it’s going to make you feel depressed and apathetic, which can hold you back both in your personal life and in your career.

Give this concept of identity the respect that it deserves. Take a look at yourself and see if something’s not right. If you do realize that you’re depressed and it’s because your inner identity and your outer identity are not in alignment, be brave enough to take the steps to bring them back together again.

Every so often, look in the mirror and ask yourself, “Am I being true to myself?”

If the answer is no, it’s time to make a change.

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

RWDevCon Inspiration Talk – Identity by Vicki Wenderlich is a post from: Ray Wenderlich

The post RWDevCon Inspiration Talk – Identity by Vicki Wenderlich appeared first on Ray Wenderlich.

Video Tutorial: Intermediate Swift Part 10: Operator Overloading

Viewing all 4370 articles
Browse latest View live


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