deprecated in iOS 9, compatibility? - ios

I've upgraded my Xcode project with Xcode 7. I'm using Objective-C.
When I'm targeting iOS 9.0 in deployment target, I've 36 warnings :
UIAlertView is deprecated, use UIAlertController.
ABAddressBookRef is deprecated, use CNContactStore ...
setStatusBarStyle:animated is deprecated, use [UIViewController preferredStatusBarStyle]
and some other...
Well, I would like to keep compatibility with iOS 9 and at least iOS 8.
Do I have to disregard these warnings for keeping compatibility with different OS ?
If I use UIAlertController iOS 8, is it working ?
What the best thing I've to do ? Using deprecated or replace with new code ?

If you are no longer targeting the older versions of iOS then its recommended to update deprecated code. You don't absolutely have to though, deprecated methods are still officially supported in Apple's SDKs, but one day Apple may remove those methods.
Here's what Apple says about deprecation:
From time to time, Apple adds deprecation macros to APIs to indicate
that those APIs should no longer be used in active development. When a
deprecation occurs, it is not an immediate end-of-life to the
specified API. Instead, it is the beginning of a grace period for
transitioning off that API and onto newer and more modern
replacements. Deprecated APIs typically remain present and usable in
the system for a reasonable amount of time past the release in which
they were deprecated. However, active development on them ceases and
the APIs receive only minor changes—to accommodate security patches or
to fix other critical bugs. Deprecated APIs may be removed entirely
from a future version of the operating system.
As a developer, it is important that you avoid using deprecated APIs
in your code as soon as possible. At a minimum, new code you write
should never use deprecated APIs. And if you have existing code that
uses deprecated APIs, update that code as soon as possible.
Fortunately, the compiler generates warnings whenever it spots the use
of a deprecated API in your code, and you can use those warnings to
track down and remove all references to those APIs.
https://developer.apple.com/library/ios/releasenotes/General/WhatsNewIniOS/Articles/iOS7.html

"Deprecated" means at least one of the following:
This API isn't gone yet, but it might be in the future, or on future platforms/technologies. For example, all API deprecated before iOS 8 is unavailable in Swift.
There's a better alternative to this API, and the old one might not keep doing everything you need as the platform changes. For example, AssetsLibrary is still around even though it's deprecated, but it doesn't provide access to iCloud Photos or Live Photos — for those you need its replacement the Photos framework.
Those are things to consider when targeting an OS version where the API are deprecated.
However, deprecation warnings are based on your project's minimum deployment target. If you tell Xcode that you want to build for iOS 7 and newer, you won't see warnings for APIs that are deprecated as of iOS 8 or iOS 9.
If you want to deploy back to an older minimum OS target, but use features from a newer OS, you need to put availability checks in your code that uses the newer features. See Apple's docs on compatibility/availability and weak linking in general, and/or Checking API Availability for Swift.

Related

Xcode How to check if there is any API used in the whole project which is not available for the current development target

Recently my app was getting crashed on IOS8 because i have used an API which is only available for IOS 9 and above. I am wondering is there anyway to check the whole project and find out if I am using any API which is not available for the current development target. Something like the warnings for the deprecated APIs. Thanks.
In order to tell the compiler you want to support an earlier OS, you need to set the SDK to that earlier OS's SDK. If you set the SDK to iOS 8, then any time you use functionality from a later OS, you should get a compiler error.

Edit app in order to support both IOS 7 and 8

I had an app that worked with IOS7 now if I change the deployment target to IOS8 I get lot of Deprecated Methods, I want to edit the app in order to work for boht IOS versions, should I keep deployment target to IOS7 and change every deprecated method for IOS8?
Changing deployment target will not work.
Please keep deployment target to the lowest supported iOS version.
Also, Apple provides backward compatibility. So the deprecated methods will work.
For best result use respondsToSelector .
Try to replace deprecated methods but with caution. Keep your old methods as is. And conditionally give support for iOS 8 and above.
Hope i am helpful.
Thanks
If you intend support iOS 7. Set your Deployment Target to 7.0
Within your build settings, make sure that the Base SDK is at least 8.0 (the latest version you want to support) or typically most people will select Latest iOS which will list the latest version that the SDK would support. Currently iOS 8.1.
Deprecated Methods are referring to methods that are outdated BUT they still work because Apple provides backward compatibility. It is just a friendly warning. In the sense of, "Hey you don't need these older methods anymore since you're just supporting iOS 8. There's newer ways to do things in town."
In your case, change deployment target back to 7.0 and if you want to (optional), go ahead and update any remaining deprecated methods that are probably left from iOS 6, iOS 5, etc etc.

App migration between different iOS versions

Currently, I'm in the middle of adapting my app for iOS 7.1 to support iOS 8.
During this process, it dawned more and more on me that I may have seen the relationship between SDKs and OS versions wrong all the time.
I'll tell you with a concrete example:
The UIViewControllerContextTransitioning protocol gained some more methods for iOS8. So in order to support the new OS, I started implementing the new methods in my ContainerViewController.
When I came across the - (UIView *)viewForKey:(NSString *)key method, I naturally checked the key against the UITransitionContextFromViewKey constant.
This constant has the NS_AVAILABLE_IOS(8_0) suffix. So I assumed the constant is only available when running on iOS8 and above.
When I set the deployment target in Xcode from 8.0 to 7.1 and hit 'Build & Run', to my surprise there was no error at all and the app ran on my iOS7.1 device without any problem. - Even while the code contained the constant that should only be available at >= iOS8.
So here are the questions that came to my mind at this point:
The NS_AVAILABLE_IOS(8_0) suffix in the header files does not determine the iOS version, but rather the SDK version from which on the marked API is available. - is that correct?
Does this mean we are able to use APIs added in the iOS8 SDK in apps that are compiled for iOS7.1, as long as we use the new SDK to build the app?
I'm particularly curious about the second question, because that would mean we can use cool new stuff like the UIVisualEffectView for apps that run on iOS < 8. Also, this would mean much less headache for example when maintaining CoreLocation functionality while following all the changes made to it (kCLAuthorizationStatusAuthorized -> kCLAuthorizationStatusAuthorizedWhenInUse, etc.), because we can simply maintain a single code base and do not have to #ifdef a lot.
Please tell me if my assumptions are correct and if not, please correct them in your answer.
Thank you!
It's important to realize that linking against the iOS 8 SDK with a deployment target of iOS 7 allows you to create an application that will run on both, but there will be differences in API availability.
When the application is run on iOS 7, iOS 8 APIs will be unavailable. At runtime, acccessing an iOS 8 API can cause a crash or other undesirable behavior. The recommended way to handle this is when using classes, methods, or constants that are marked as available only on iOS 8 or later, you must query for their availability at runtime.
In the case of new UIViewControllerContextTransitioning methods, you would query for the presence of those iOS 8 methods at runtime:
if ([transitioner respondsToSelector:#selector(viewForKey:)]){
// It's available, you're set to call it
} else {
// The method is not available, you will have to work around it.
}
Obviously, this can complicate things significantly for some applications. The application DeployMate can be very useful for finding API disparities in your code base. It will scan your project and tell you where you are using a method that is iOS 8 only.
Guidance for supporting different SDK and OS versions and capabilities is explained in more detail in the iOS 7 Tech Talk Architecting Modern Apps, Part 2. While the examples are for supporting iOS 6 and 7, the guidance here applies to supporting more than one OS or SDK, no matter what the version.

Should I use methods deprecated in 7.0 if the user's iOS version is below 7.0?

I am using SDK 7.0
My deployment target is 4.3
I'm testing with the 5.0 simulator
I see a method that says "Method A is deprecated in iOS 7.0, instead use B" in Apple's documentation.
I think that I got things mixed up, so just to be clear:
If I identify the user's iOS version (5.0), should I use A or B? Since it is 5.0, A should be available, whereas B probably not because it was implemented later, right?
or does the fact that I used SDK 7.0 imply that I should always use B, regardless of the user's iOS version?
Use the older method. Method B won't be available under older versions of iOS. Deprecated methods rarely (never so far?) actually go away. The only example is the UIDevice uniqueIdentifier but even that didn't go away, it simply returns garbage now.
Of course you could do something like:
if ([someClass resondsToSelector(someNewerMethodSelector)]) {
// call the new method
} else {
// call the old method
}
Code like that will run the newer method if it exists or the old method if not. Similar checks can be made for newer classes too.
BTW - why spend the effort to support iOS 4.3 or even 5.x? Support iOS 7 and maybe iOS 6.x if you have a good reason. Unless you have a specific need or requirement, supporting 4.3 and 5.x is not worth your effort.
And if you do keep support for 4.3, you better test your app thoroughly on a device with 4.3 to be sure you don't accidentally call and 5.0+ APIs.
Sometimes a method will be added in an OS version and both the old and the new are supported, then the old method will be deprecated in a yet-newer OS release.
Lately Apple has been releasing an updated method/class/API and deprecating the old one at the same time.
That means that if you are supporting old OS versions, you have no choice. You HAVE to use the old way of doing things in the old OS because the new way doesn't exist. So if you support iOS 5, 6, and 7, you can only use the new method if you write runtime code that checks to see if it is supported. Then you need to decide what to do about the old OS versions.
Sometimes it's simpler to just use the deprecated method and be done with it. That code works for all supported OS versions. However, that's less "future-proof" than writing code that checks at runtime and only uses the deprecated method if the newer version isn't available.
Imagine you have an app that runs on iOS 5, 6, and 7. You use a method that changed in iOS 6. It was deprecated in iOS 7, but still works. If you just use the deprecated method, it works in all 3 target OS versions, but what about iOS 8 when it comes out? When Apple deprecates a method/API/class it means that at some future date they are going to remove it completely.
Doing a runtime check and using the deprecated method if the new version isn't available is the most work, but the most future-proof. In iOS 8, if Apple removes the deprecated method, your code works. In iOS 5, the new method isn't available, so your code uses the old method. It is a pain in the butt however.

Sanity-check for iOS API versions used within an application

I have an application where I am supporting a deployment target of 4.3 with a base SDK of 6.x.
I find myself having to weak link API methods and provide alternative workarounds for older runtime based on strategies found in the document "Using SDK-Based Development".
The problem I am facing is, occasionally and unintentionally, I would use a method that is available only in a newer SDK without realizing it and did not weak-link the method. This causes a crash for users running the app on an older version of the OS.
While I know the number of users having that old a runtime (iOS 4.3) is diminishing, I would like to know if there is a tool or a way for us to generate a report that would list APIs available in SDKs other than that of the deployment target, so that I may review the code to ensure proper weak-linking is performed, prior to shipping the product.
Off the top of my head, compiling the source to an older version of the SDK should throw errors, but then again, Apple's strategy has always been to ship new XCode without older SDKs.
I am not looking for a perfect solution. Any other workarounds would be helpful too.
If you don't mind paying, Deploymate can scan your project and identify API calls which may fail on older operating system versions. Works with Mac and iOS apps/projects.
Deploymate helps you identify unavailable, deprecated and obsolete API usage in your Xcode projects

Resources