Top Tips for iOS 9 Development

To celebrate the arrival of iOS 9, we asked a few of our friends to share the most useful thing they learned when looking to update their apps to support this latest version of iOS. Here is some fantastic advice to to get up to speed and make the most of development for iOS 9.

Dave Verwer

@daveverwer — Founder of Curated, Runs iOS Dev Weekly

It’s rare that a new API in the iOS SDK actually helps with app discovery and marketing. So, for me some of the most exciting features in iOS 9 are the new search APIs.

These features build on top of NSUserActivity which was introduced in iOS 8 for supporting Handoff. With iOS 9 additional metadata and deep link URLs can be added to your app so that it appears in iOS 9’s spotlight search, not only as an app for the user to launch but exposing its content as well.

This is going to be immediately beneficial to your existing users but Apple are also going to index these search results centrally as well. Your app could then appear as a suggestion when users who don’t yet have your app installed use spotlight. Free marketing? Well, maybe.

The interesting thing with this is that Apple are only going to suggest your app to new users when your existing users are regularly using and interacting with the search results you provide. This immediately cuts out spammy apps and focuses on those which provide real value and that’s got to be a good thing for the App Store.

There’s much more to this than there is room for in a quick tip. So, for a deeper look at these APIs and how to implement them you should watch Session 709 — Introducing Search APIs from WWDC. There’s also a handy tool for validating your web site to make sure that iOS can see your app links correctly.

Tim Oliver

@TimOliverAU — Creator of iComics

With the exciting announcement of iPhone 6s and iPhone 6s Plus, developers can now take advantage of enabling their apps with 3D Touch, adding (literally) a whole new dimension to UI interactions!

As expected of Apple, 3D Touch is exposed to developers via a very simple API, at its fundamental level, exposed simply as a new property in UITouch.

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
     guard let touch = touches.first else { return }
     if traitCollection.forceTouchCapability == .Available {
        println("Touch pressure is \(touch.force), maximum possible force is \(touch.maximumPossibleForce)")

This new API unlocks a vast amount of potential for new functionality in apps, such as additional control options in games, fine-grained control in drawing apps, or simply even a nicer alternative to the tap-and-hold paradigm we’ve had since the first iOS device.

In addition to the UITouch APIs, Apple has also provided two new sets of classes adding 3D Touch functionality to apps: UIPreviewAction and UIApplicationShortcutItem.

UIPreviewAction allows developers to quickly present content in a new ‘preview’ overlay when you 3D Touch a UI element. This is a fantastic way to allow a quick glance at app-specific content, such as email messages, photos, or even websites without needing to commit to a full view controller transition.

UIApplicationShortcutItem objects enable an amazing new feature right on the iOS Home screen. When users 3D Touch an app icon, a sheet of options is presented, allowing the user to quickly jump to a specific section of the app, or perform an in-app action.

iPhone 6s Application Shortcuts

Overall, the introduction of 3D Touch unlocks a whole new paradigm of iOS device interaction and will enable a new generation of innovation in upcoming iOS apps. Sample code, as well as more general info on 3D Touch itself is available on the 3D Touch page of the Apple Developer site. Good luck!

Alex Akers

@a2 — Software Engineer at Facebook

New in iOS 9.0 and OS X 10.11 are the UILayoutGuide and NSLayoutGuide classes, respectively. They allow you to create “view-like” objects that participate in the Auto Layout constraint solver without creating extraneous on-screen views. For example, you can use these new classes instead of creating empty views and constraining their dimensions, etc.

// Create the layout guides.
let layoutGuideA = UILayoutGuide()
let layoutGuideB = UILayoutGuide()

// Add them to the view.
let view: UIView = ...

// Add constraints using them.
layoutGuideA.heightAnchor.constraintEqualToAnchor(layoutGuideB.heightAnchor).active = true

// You can even set their identifiers...
layoutGuideA.identifier = "layoutGuideA"
layoutGuideB.identifier = "layoutGuideB"

// ...and get their calculated frames (valid once the owning view has been laid out)
print("layoutGuideA.layoutFrame -> \(layoutGuideA.layoutFrame)")

Indragie Karunaratne

@indragie — Mac and iOS Software Engineer, Student

The NSLayoutAnchor API introduced in iOS 9 not only makes it cleaner to declare constraints, but also makes additional guarantees regarding the correctness of your constraints through the power of static type checking. For example, consider this constraint, created using the old NSLayoutConstraint API:

NSLayoutConstraint *constraint = 
    [NSLayoutConstraint constraintWithItem:view1 

This constraint is invalid because you’re constraining an attribute on the X axis (leading) to an attribute on the Y axis (top). However, this will compile without any warnings and will proceed to run and fail silently, leaving your layout in an undefined state and leaving you with a difficult mess to debug, given that nothing is logged to inform you that one of your dozens (or hundreds, or thousands…) of constraints is invalid.

NSLayoutAnchor solves this issue by leveraging the power of generics in both Swift and Objective-C. The anchor accessors on UIView expose subclasses of NSLayoutAnchor that add type information to methods inherited from NSLayoutAnchor. There are separate subclasses of NSLayoutAnchor for X axis, Y axis, and dimension (width/height) anchors, since each of those types of anchors can only be constrained to another anchor of the same type. By constraining the anchor parameters in NSLayoutAnchor’s methods to the same generic type as the receiver, the API uses the type checker to enforce rules for creating valid constraints.

Going back to the prior example, here is the equivalent constraint declared using the NSLayoutAnchor API:

NSLayoutConstraint *constraint = 
    [view1.leadingAnchor constraintEqualToAnchor:view2.topAnchor];

Not only is this much more readable than with the old API, this also spits out an “Incompatible pointer type” compiler warning because the compiler knows that you can’t create a constraint using two different anchor types.

For more information, see the NSLayoutAnchor documentation.

Note regarding Swift and Objective-C Generics: At the time of this writing, using Xcode 7 beta 6, Objective-C generics don’t bridge correctly to Swift. This means that the additional type safety mentioned in this tip doesn’t apply if you use this API with Swift, but does work correctly if used with Objective-C, as confirmed by Joe Groff.

Ayaka Nonaka

@ayanonagon — iOS Engineer at Venmo

My top tip for iOS 9 is to drop iOS 7 and start using things like UIAlertController (iOS 8+) which I love that it enforces that only view controllers can present alerts and action sheets and UIStackView (iOS 9+) which is a much saner way to think about layouts. Seriously, try it out if you haven’t already. It’s so great. There are open source libraries (PSTAlertController and TZStackView) that back port these to previous iOS versions too, so worth using them and swapping them out with the UIKit versions once you’re ready to drop iOS 7 or iOS 8.

Conrad Kramer

@conradev — Creator of Workflow

Apple introduced App Transport Security in iOS 9, which requires all apps to use HTTPS by default. Because not every asset is served over HTTPS, Apple also provides a way to disable ATS, either selectively or as a whole.

If your app needs to be able to load arbitrary URLs (for example, in a UIWebView), then you probably disabled ATS as a whole, by setting the NSAllowsArbitraryLoads key to YES. This is okay, but if you disable ATS as a whole, then you should enable ATS selectively for important domains. You can do this by using the NSExceptionDomains key. For example, this is part of Workflow’s Info.plist:

Workflow Info Plist

You can see that we support users downloading files over HTTP, but we also require HTTPS when connecting to (and all of the API domains that Workflow uses).

Also important to note is that ATS is applied on a per-bundle basis. This means that you need to add the ATS dictionary to not only to your main app’s Info.plist, but also to your extensions’ Info.plist files as well.

Jake Marsh

@jakemarsh — Creator of Little Bites of Cocoa

Implement as much of the new search functionality as you can. Search is going to be incredibly important going forward, and iOS 9 is just the beginning. I’d recommend adding NSUserActivity support to your app as soon as possible. It’s incredibly straightforward, and when you’re done your app will support both Handoff and the new Proactive systems. If your app has any kind of searchable content, you should definitely take advantage of the awesome new Core Spotlight framework and tell the system how to index it all. You should also make sure any web content associated with your app is optimized for iOS 9’s new search results view, Apple has a great guide showing how a few simple meta tags can go a long way here.

The more the system knows about what a user is a doing, and what kind of content they’re creating or interacting with, the more intelligent suggestions and options it can present to them.

Sam Ritchie

@FakeSamRitchie — Chief codesplicer at codesplice

Everyone who’s worked on a shared iOS codebase eventually gets burnt by merge conflicts on a storyboard file, which often results in you manually redoing all your changes in IB. This can get so painful that some teams give up on concurrent storyboard development and implement some variant of the source control shingle.

If, unfortunately, you don’t have any roofing materials handy, the best way to minimize merge conflicts is to break your UI up into smaller storyboards. In the past this has meant you needed to perform your cross-storyboard navigation in code, but with Xcode 7 and iOS 9 you can now do this using a normal segue via a Storyboard Reference. These give you all the benefits of single-storyboard navigation, but let you split up the files for simpler merging.

The quickest & easiest way to start breaking up a monolithic storyboard is to zoom out, shift-select a group of related scenes and select ‘Editor > Refactor to Storyboard…’ (yes, storyboards get refactoring support before Swift). However, this will leave references for every scene and auto-generate unpleasant-looking Storyboard IDs where necessary, so personally I prefer doing a ‘File > Duplicate…’ and just deleting the extra scenes.

If you already have multiple storyboards, give yourself a high-five — you get to delete some code! Drag in a Storyboard Reference from the Object library and configure a segue, then remove your manual navigation code by pounding the delete key with excessive force.

Natasha Murashev

@NatashaTheRobot — iOS Engineer at Capital One, Blogger at Natasha The Robot

I haven’t looked into iOS 9 too much but I have been working with watchOS 2. If you have an Apple Watch app, I recommend re-writing it from scratch using the new Watch Connectivity framework. watchOS 2 is completely different and a lot more powerful than the preceding WatchKit extension. It’s the future, so keeping and maintaining your watch as a WatchKit extension is just adding to your technical debt.

Also, consider adding a Complication component to your Watch App. While currently the hierarchy of use on the Apple Watch is Notifications, Glances, and then App. The future #1 (or at least competing for #1) is going to be Complications — imagine having your app right there, every time the user raises their wrist!

To get started, check out these resources:

Riley Testut

@rileytestut — Creator of GBA4iOS, USC Student

If you’re anything like me, you use early exits in your code to better organize your validation logic. While early exits have been possible in Swift since day one, they brought with them a few caveats. First, they required you to check for the condition you didn’t want (e.g. if variable is nil), instead of what you do want. More importantly though, in the common case that you were wanting to exit if a variable is nil and continue if it isn’t, you would then have to unwrap the variable manually, following the early exit to continue using the variable for the rest of the scope.

With Swift 2, the Swift team has graced us with a new keyword to help us with early exits: guard. guard fixes both issues above. Imagine, for a second, you’re working on a game. Because the developer was too lazy to implement separate callbacks, all input changes are handled through one callback function:

func gameController(gameController: GameControllerType, didActivateInput input: InputType?)

Having a second callback dedicated to handling when inputs are deactivated would be better, but this demonstrates the helpfulness of guards; if the optional input is non-nil, then a button was pressed, and the game should react. To signal that the button is no longer pressed, input will be nil. If we only care about when a button is pressed, we could’ve used the following early-exit strategy in Swift 1 to accomplish this:

func gameController(gameController: GameControllerType, didActivateInput input: InputType?) 
    if input == nil

Notice that we compare input to the case we don’t want to handle, which in this case is it being a nil value. More importantly though, notice that because input is still an optional, we still have to force-unwrap the value later in the function, even though we know it is non-nil. With Swift 2, this becomes much better:

func gameController(gameController: GameControllerType, didActivateInput input: InputType?) 
    guard let unwrappedInput = input else { return } 
    // in development, I call the unwrapped variable the same name
    // as the variable. However, unwrappedInput demonstrates this better.

Here, we “guard” the condition that input is non-nil and store it into unwrappedInput, otherwise we return. Now, we can use unwrappedInput as a non-optional, and everyone is happy! Thus, guards help make your iOS 9 code cleaner and less error-prone.

Janie Clayton

@RedQueenCoder — iOS/Mac developer, Blogger at Red Queen Coder, Host of NSBrief

My projects are actually a little different than most people’s. I write control software for robots on the Mac. The biggest thing we did to get ready for the release of iOS 9/Swift 2/ El Capitan was updating our error handling for Swift 2. When Swift 1 came out, we wrote and implemented our own error handling methods because we had a lot of problems with NSError.

Since we’re working with hardware, error handling was a really important part of our software because if you don’t handle or anticipate errors properly, it causes lots of physical damage and physical damage is expensive!! So, if I was going to give a tip for iOS 9, I would say if you are using Swift to get familiar with error handling. I know it’s one of those things like unit tests that we know we’re supposed to do and it isn’t fun or flashy, but we don’t control the outside world and it’s important to think about how you want your app to respond when things go wrong.

Glen Low

@pixelglow — Creator of Instaviz, Apple Design Award Winner 2004

To cultivate the Tao of UIKit programming, you need to stop fighting the system, and instead surf with the flow of the framework. Otherwise you’ll be wiped out every time Apple releases a new iOS.

Case in point: UIKit really wants to keep your presented view controllers presented on screen, even adapting them to different screens and orientations, and repositioning the pointy end of popovers.

Work with the system by mostly accepting the adaptive presentation defaults and supplying a new popover location in UIAdaptivePresentationControllerDelegate / UIPopoverPresentationControllerDelegate. Don’t dismiss your view controllers on a size or size class change. These delegates also only offer limited customization: while adapting, it’s easy to swap in a new view controller but it’s hard to actually change the existing view controller e.g. if you wanted to disable a back button.

Otherwise, at best you’ll risk weird behavior while rotating the device or with the new iPad multitasking or the latest Apple magic tech, at worst crash and burn debugging on a sleepless midnight on the eve of that new iOS release.

Thanks for reading! Now go forth and make some amazing apps!

Get more development news like this

Next Up: New Features in Realm Obj-C & Swift

General link arrow white

About the content

This content has been published here with the express permission of the author.

Tim Oliver

Tim Oliver hails from Perth, Australia! He has been an iOS developer for 6 years, and recently joined Realm in March 2015. Tim has a cool app called iComics and he loves karaoke! He does, in fact, also sometimes have the problem of too many kangaroos in his backyard.

Alexsander Akers

Alexsander Akers

Dave Verwer

Dave Verwer

Indragie Karunaratne

Indragie Karunaratne

Ayaka Nonaka

Ayaka leads the iOS team at Venmo, where they write only Swift these days. She’s been doing iOS development since iOS 4 and loves writing Swift while listening to Taylor Swift. In the past, she’s given talks on NLP in Swift, Swift Scripting, and rewriting the Venmo app in Swift. She was born in Tokyo and was super excited to give her first talk there! 宜しくお願いします。

Conrad Kramer

Conrad Kramer started developing for iOS after he got involved with the jailbreak scene back in 2010 with his first tweak Graviboard. Since then, he has gotten into regular iOS development and worked on various open source projects in the Cocoa community, like AFOAuth2Client and WFNotificationCenter. Conrad now spends all of his waking hours on Workflow, an automation tool for iOS, where he works on anything from the server backend to building the complex drag and drop interactions.

Jake Marsh

Sam Ritchie

Sam Ritchie

Natasha Murashev

Natasha is secretly a robot that loves to learn about Swift and iOS development. She previously worked as a senior iOS Engineer at Capital One in San Francisco, but now she travels around, writing about her experiences with new technologies. In her free time, she works on personal projects, speaks at meetups and conferences, contributes to open source, and likes to cross things off her bucket list.

Riley Testut

Riley Testut

Janie Clayton

Janie Clayton

4 design patterns for a RESTless mobile integration »