How to detect unavailable API of the deployment platform?

Hi,


Currently I made of mistake that make my app crash on iOS7. Dues to no iOS7 simulator available now, so I met a big trouble to find the problem. Finally, I borrowed a iOS7's iPod touch from my friend to find the root cause.


The problem is I accident used a new API


- (BOOL)containsString:(NSString *)str NS_AVAILABLE(10_10, 8_0);

of NSString.

It only available after iOS8 but my min deploy platform is iOS7.

Fortunately I find the solution this time. But I really want to avoid this kind of error in future.

Does anybody know are there some way to check the API's available when compile the source to avoid such problem?

Any suggestion will be the great help...

Thank you~~

Eric

Answered by QuinceyMorris in 99616022

>> By the way I can't find any setting that call "TargetOS"? Did I miss something?


No, you didn't miss anything. When you create a "target" in Xcode, you have to choose whether to create an OS X, iOS, watchOS, tvOS target. Then the target's build settings have a "Base SDK" setting, which allows you choose which version of the platform API to write your code for. However, in recent versions of Xcode, there is usually only one possible Base SDK choice. (In the past, Xcode shipped with multiple SDK versions for each platform, but that doesn't happen any more.)


The "deployment target" is a "target" in a different sense. There is nothing that's called "TargetOS". Mr. Wrench is referring to the platform and/or the Base SDK.


To answer your original question, in Objective-C there's no good, built-in way of checking whether you're using API that's too new for your deployment target. (Again, Xcode used to ship with multiple SDK versions, so you used to be able to choose an older one, and then you'd get compile errors. But that doesn't happen any more.)


In Swift, this availability checking is built into the language, but for Obj-C your choices are:


— use an older version of Xcode that has the Base SDK version that matches your deployment target version


— use a 3rd-party utility such as Deploymate (deploymateapp[dot]com)


— or just be very, very careful 😉

Yes, you can do this in a couple of ways.


In this case, because you are using Objective-C, you can check at runtime by calling

[stringInstance respondsToSelector:@"containsString"]

, for example.


If you want to check using the compiler, you can temporarily set the TargetOS for your project to the earlier OS version and build as part of your verification process. I am not aware of a complier setting to indicate possible problems when only the DeploymentOS is set to an earlier version, but maybe someone else is.

Hi Floating,


Thanks first, but I can't find where to set TargetOS in my XCode?

I did know how to choose correct API when I know the API version by respondsToSelector. But my problem is sometimes I misused the API that doesn't support in my DeploymentOS. And I want avoid such error when I compiling the project. I can do some switch expression if I know the API's capability issue when I compile the project. But seems Xcode doesn't have such warning message so I didn't know I used the API that may crash my app in user's platform. (In my case this time: iOS7)


I think maybe I need open some setting in XCode that I didn't know?


Thanks,


Eric

I would start by reading the Apple Documentation on Xcode settings. The Deployment Target and TargetOS settings are basic settings when configuring your project. Here is one place to start: https://developer.apple.com/library/watchos/documentation/ToolsLanguages/Conceptual/Xcode_Overview/WorkingwithTargets.html

Hi Floating,


I am a little confuse about the XCode Setting you said, I can only find Deployment Target in my XCode and I set it to "iOS 7.0". That's why my crash happened. The crash will disappear if I select the deployment target to iOS 8.0 because the crash caused by I misused the 8.0 API in my code that I didn't be awared. My crash only happened on iOS7 device. That what I want to detect during my developing. I need some warning about the inappropriate API I used in my Deployment Target. For example, I need some information like:

warning: unsupport API: NString can't find containString in deployment target iOS7.


By the way I can't find any setting that call "TargetOS"? Did I miss something?


Thanks,

Eric

You could try opening a copy of your project in an older version of Xcode that only has the iOS 7 SDK. But that's a pain. It would be nice if there were an easy way to do it from the latest Xcode. This would be worth filing a bug report / enhancement request in my opinion.

Accepted Answer

>> By the way I can't find any setting that call "TargetOS"? Did I miss something?


No, you didn't miss anything. When you create a "target" in Xcode, you have to choose whether to create an OS X, iOS, watchOS, tvOS target. Then the target's build settings have a "Base SDK" setting, which allows you choose which version of the platform API to write your code for. However, in recent versions of Xcode, there is usually only one possible Base SDK choice. (In the past, Xcode shipped with multiple SDK versions for each platform, but that doesn't happen any more.)


The "deployment target" is a "target" in a different sense. There is nothing that's called "TargetOS". Mr. Wrench is referring to the platform and/or the Base SDK.


To answer your original question, in Objective-C there's no good, built-in way of checking whether you're using API that's too new for your deployment target. (Again, Xcode used to ship with multiple SDK versions, so you used to be able to choose an older one, and then you'd get compile errors. But that doesn't happen any more.)


In Swift, this availability checking is built into the language, but for Obj-C your choices are:


— use an older version of Xcode that has the Base SDK version that matches your deployment target version


— use a 3rd-party utility such as Deploymate (deploymateapp[dot]com)


— or just be very, very careful 😉

Unfortunately I think keeping an old copy of Xcode around is the best way right now to get help from the compiler.


You may be able to grab an older version of the SDK out from an older copy of Xcode and add it to the newer version of Xcode along the correct path (I haven't tried doing that for this purpose). You have to know where Xcode puts the SDKs though. Pretty sure if you Google around, you'll find a tutorial somewhere. The older SDK will also vanish when you update Xcode so you'd probably want to keep it in another location.

Personally I would not recommend messing with your current version of Xcode if you intend to use it for production releases. Murphy's Law is alive and well when it comes to app store submissions, and the less unsupported hacks (plugins, SDKs, etc.) you add to Xcode the better IMO.

Thanks for all your help.

I think I find the solution of my problem finally.


Here is my final solution:

1. Download XCode5/XCode6 from

https://developer.apple.com/downloads/

2. Copy the SDK file from XCode5 to XCode6 from path:

/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/

3. Open my project from XCode6.

4. Set base SDK to 7

5 Build project with device: iOS device. (Error happened when I using iOS7's simulator.)

6. Check the error message.


I can find the error message below.

No visible @interface for 'NSString' declares the selector 'containsString:'



I think this is what I need now.

By the way, I still need revert the base SDK setting in XCode7.


Thanks again!!


Eric

Everything in AtOmXpLuS.CoM

How to detect unavailable API of the deployment platform?
 
 
Q