Over a million developers have joined DZone.

How to Safely Update Your App to iOS 10

With iOS 10 looming, it's time for a quick refresher on how to safely update that iOS app you developed so that it works with the latest iOS version as well as any previous versions you might support.

· Mobile Zone

In my last post, I highlighted a few of the new features launching in iOS 10 that developers can take advantage of. While it’s fun to go sprinting into the latest-and-greatest, you need to make sure your app is updated across the board. This means checking for reliance on any deprecated methods or classes, and verifying that users still running existing versions of iOS continue to be taken care of.

Before you go sifting through all the changelogs (which I highly recommend if you’re having trouble falling asleep tonight), there are a few things you can do to make sure your app is prepared for the iOS 10 transition.

Quick Story: Many years ago in a galaxy far, far away, I was working on an iOS app with something in the neighborhood of a few hundred thousand monthly active users. I built, tested and deployed an update with fresh iOS 5 support. I went out with some colleagues to celebrate the release but within a few hours, I started getting crash notices from Apteligent. Turns out, I included a method that was only available in iOS 5 without proper handling, so the app was broken for everyone using iOS 4 and earlier – around 30% of my user base. Whoops. Needless to say, my testing became more rigorous and [beware: shameless plug ahead] I was glad I had Apteligent installed to alert me quickly, but it was a lesson learned the hard way. Don’t let this happen to you!

Checking API Availability

When building against the new APIs in iOS 10, the best thing you can do to ensure your app still works on older versions is to do runtime API checking. This ensures the class or method you’re about to call exists on the device the app is currently running on. If you try to call an iOS 10 method on iOS 9, you’ll run into trouble (see my sad story above).

For classes, this is an easy check – and looks something like this:

if(NSClassFromString(@"MSMessage")) {
    // This class is available, go ahead and do something with it
} else {
    // This class is not available, handle it appropriately
}

Or if you prefer Swift:

if #available(iOS 10.0, *) {
  let message = MSMessage()
} else {
    // This class is not available, handle it appropriately
}

If the class (MSMessage) is weakly-linked, references to MSMessage outside of the block won’t immediately crash your app on pre-iOS 10 devices. This makes bugs harder to find and allows more issues to slip through testing. Even though you avoid a crash, your user experience will quickly degrade since your code doesn’t realize the MSMessage functionality is missing. This makes it critically important to handle both pre- and post-iOS 10 scenarios when implementing new features.

For new methods on existing classes, there is another easy check:

// Check if new API is available
if ([existingClassObject respondsToSelector:@selector(newMethod:)]){
    // Yes, we can safely call this method
    [existingClassObject newMethod:@”something”];
} else {
    // The new method is not available, handle accordingly
}

In Swift, you can use the same #available method as described above, particularly useful if you know the SDK level your method requires. Otherwise, you can use the equivalent method calls as shown:

// Check if new API is available
if existingClassObject.respondsToSelector(Selector(“newMethod”)){
    // Yes, we can safely call this method
    existingClassObject.newMethod()
} else {
    // The new method is not available, handle accordingly
}

We first check to see if the method will respond if we call it, and if it does, we go ahead and call it safely. This simple conditional handles the cases on both iOS 9, where the method will not respond, as well as iOS 10, where the method is available to be called.

If you attempt to call newMethod on an unsupported version of iOS, your app will crash with an NSInvalidArgumentException. This is one of the most common crashes on iOS, and it can be avoided with this simple check.

A Note on Macros

A macro is a bit of code that is executed by the compiler. With iOS, you can use something like this:

#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_10_0 
    // iOS 10+ code 
#endif

Many developers see this and add it to their code without fully understanding what is happening, but this should not be used to ensure a user is on iOS 10. Here’s why:

This code within the block is only compiled if the app deployment target is greater than or equal to iOS 10. More than likely, your app’s deployment target is lower than the current SDK. For example, your deployment target may be as low as iOS 8 since you still want to support existing users.

If you use the macro above with iOS 8 support, the code within the block will be omitted for all users since the macro is executed at compile time. You won’t see any warnings or get any errors, your code just won’t be included in your app!

For managing deprecation and new APIs, it’s best to do code checks at runtime to accommodate all operating system versions and devices that your app supports.

Pay Attention to Deprecation Warnings

At one point or another, every developer has said something along the lines of “pshh, I’ll deal with that later”. You’ve likely seen deprecation warnings within Xcode, which let developers know that a method or class is on its way out. At some point the code will be removed altogether; your app will crash if it attempts to reference the removed method on a newer operating system.

Generally, this is not a short process. Apple will usually spend multiple major OS releases with a ‘deprecated’ method or class before it is actually removed, which gives developers time to properly update their code. Regardless, the time does eventually come – so it’s something to keep on your radar.

There are very few class/method removals in iOS 10, which means this won’t be an issue for most developers, but do check out the changelogs – and stay on top of your compiler warnings just in case.

Test on All Supported iOS Versions

At the end of the day, it will be up to proper testing to verify that your app is working on all devices and operating systems you support. Don’t fall into the trap of “it works on my device so it must be fine”. Unfortunately, even the best testing can’t catch everything, which is where Apteligent comes in. Our SDK allows you to monitor for crashes and performance issues in your app to quickly track down bugs that slipped past testing.

Finishing Up

I highly recommend grabbing the latest version of iOS so your app can take advantage of the latest features Apple has to offer. Just make sure that you don’t neglect the stability and performance of your app across the rest of your app’s user base. It only takes one bad release to diminish the 5-star rating you’ve worked so hard for, so be thorough and test test test.

Follow these guidelines and your app will be all set for the official launch of iOS 10 this fall. And for the issues that inevitably slip out into your release – Apteligent has your back with real-time crash and performance monitoring. Get started for free and start tracking down issues in 10 minutes or less.

Topics:
app ,apis ,ios ,features ,deployment ,update

Published at DZone with permission of Chris Beauchamp. See the original article here.

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

SEE AN EXAMPLE
Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.
Subscribe

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}