Check iOS version as Apple suggested - ios

Apple in the iOS7 transition guide wrote a snippet to check the iOS version
if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_6_1) {
// Load resources for iOS 6.1 or earlier
} else {
// Load resources for iOS 7 or later
}
But what if Apple come out with another iOS6 version such as 6.2? automatically the iOS7 version will be loaded.
Would be better something like that:
if (floor(NSFoundationVersionNumber) >= NSFoundationVersionNumber_iOS_7_0) {
// Load resources for iOS 7 or later
} else {
// Load resources for iOS 6.1 or earlier
}
Unfortunately this foundation number is not available. Do you think that Apple suggested method is safe?

NSFoundationVersionNumber_iOS_6_1 == 993.00, there is no problem.
But NSFoundationVersionNumber_iOS_7_0 == 1047.22 , so floor() function maybe not right~

iOS 6.2 should have all of the API features of 6.1, so that will work fine. These tests are mainly for knowing how to do something (i.e. which API features exist).

Related

How to check latest version of iOS in Swift without using #available?

How can we check if the OS running on iPhone is the latest one. Is there any API for that?
For example, user is using iOS 14.6, so I want to know if its the latest version that he is using
I know this code is for checking, what OS user is having. This is not the answer at all. Please read the question before closing
if (#available(iOS 14.6, *)) {
// Use iOS 11 APIs.
} else {
// Alternative code for earlier versions of iOS.
}
No there is no way except available only if you created a personal Api to provide this info for your app automatically when opened

Can I use "uppercaseString" in an app targeting 8.0? Is it safe pre iOS 8.3?

I'm using the built in string method uppercaseString, like this:
let capitalLetters = myString.uppercaseString
The documentation tells this for availability:
iOS (8.3 and later)
However, Xcode is not giving a compiler error, with the if #available recommendation, i.e:
if #available(iOS 8.3, *) {
} else {
}
My question is simple. Can I use this method in an app targeting 8.0? I cannot test it on a device with this version because I don't have one. And the simulator I have is 8.4.
From Apple's documentation:
var uppercaseString: String { get }
Available in iOS 2.0 and later.
https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/index.html#//apple_ref/occ/instm/NSString/uppercaseString
Sometimes xcode shows you wrong availability versions (since swift came out). If sometimes you aren't sure about the availability - check it online.
PS: You can download simulators for which version you want

How to define code for different iOS versions

I am working on an iOS app. I want it to support iOS 7 and 8. It is going pretty nicely, however there are lots of different parts of the app which use Apple APIs. Some of these APIs work in both iOS 8 and 7. However, some of them are deprecated in iOS 8. So I therefore went to the Apple developer site to see what to replace them with (new methods/etc....).
However, I now have the problem that the app will work on iOS 8 fine, but certain parts of it don't work properly on iOS 7 as I'm trying to use an iOS 8 API...... (lol).
So I just wanted to know, what is the best way to implement code which works on iOS 8 and 7. I had a few ideas (below), but I'm not sure which is best:
IDEA 1
Whenever I have code which doesn't work on both OS's, I use an if function (which calls a macro) like so:
if (SYSTEM_VERSION_LESS_THAN(#"8.0")) {
// iOS 7 device. Use iOS 7 apis.
}
else {
// iOS 8 (or higher) - use iOS 8 apis.
}
IDEA 2
I was thinking about using ifdef definitions all around the app like so:
#ifdef __IPHONE_8_0
// iOS 8 code here....
#else
// iOS 7 code here....
#endif
Which way is better? I would have thought that the second idea is much faster and uses less resources right?
Or are both my ideas rubbish? Is there a much better way about solving this problem?
Thanks for your time, Dan.
I don't suggest checking the Version and writing code based on that. Instead you need to check whether that API is available or not.
For checking a class available or not:
Class checkClass = NSClassFromString(#"CheckingClass");
if (checkClass)
{
// Available
}
else
{
// Not Available
}
If you need to check a feature/function available;
if ([checkClass respondsToSelector:#selector(yourMethod:)])
{
// Feature/ Method Available
}
else
{
// Feature/ Method Not Available
}
NOTE:
Deprecated API's doesn't mean that you shouldn't use that in current version. It means, it won't work from next version onwards, and only work till current version.
The ifdef-way won't work, because preprocessor statements are evaluated at compile-time; but only at runtime we know which ios-version we have to deal with.
You would use macros for example if you wanted to support Mac OS X and iOS with the same code, because you know at compile-time if the binary will be for Mac OS or iOS.
So you need in this case approach 1 - or, even better, you should use respondsToSelector: to check for availability instead of testing the iOS version if possible.
However, because you are only dealing with deprecation warnings, you don't have to do anything and should simply continue using the deprecated APIs until the app no longer needs to support ios7.

Check ios versions then call functions of uiviewcontroller accordingly

I was stuck with an orientation issue in iPad for all versions. My app is designed in such a way that it supports from ios 6 till ios 8.
According to apple since willAnimateRotationToInterfaceOrientation: is DEPRECATED from ios8, i used viewWillTransitionToSize: for ios8.
When hit with issue, my first solution was providing macros to decide the version as either ios 8 or below and perform the functions accordingly.
#ifdef __IPHONE_8_0
// Works on >= version 8.0
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
{
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
// my code go here for ios 8
}
#else
// Works on < version 8.0
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration
{
// my code go here when version is below 8.0
}
#endif
I also checked and run it.. I received the output as expected.
But it was said that the code was wrong.. as i am trying to turn version checking into a compile-time decision. The version checking must be a RUNTIME decision. both the ios7 and ios8 code must BOTH be compiled into the executable.
So changed the function as below without any version check:
-(void)viewWillLayoutSubviews
{
[super viewWillLayoutSubviews];
// my code go here without any version check
}
I'm hardly unable to understand the line "both the ios7 and ios8 code must BOTH be compiled into the executable." - what this really mean.
Wish to know why i shouldn't provide compile-time decision?
Also if i want to do it... without using notification.. is there any way through which i can able to handle by calling these functions at runtime with version check?
Kindly let me have the comments on this.

Was I supposed to get a warning [duplicate]

This question already has an answer here:
Why is the Xcode compiler not warning me about invalid methods for my Deployment Target?
(1 answer)
Closed 9 years ago.
In my code I use
[[self presentingViewController] dismissViewControllerAnimated:YES
completion:dismissBlock];
The thing is my deployment target is set to: 5.0.
While base SDK is 6.1.
Was I not supposed to get a warning by XCode? (because I think the above method got introduced in iOS6).
Unfortunately no, Xcode doesn't check if you use symbols that are not available in your deployment SDK.
It only checks your code against the base SDK.
But you can use some third-party software for this, like DeployMate.
That being said, as others pointed it out, dismissViewControllerAnimated:completion: is available since iOS 5, so your code is safe.
But it's always a good idea to check for unavailable or deprecated APIs in your app, using something like DeployMate.
EDIT
Here's an answer to your comment:
If you deployment target is 5.0 and your base SDK 6.0, using a symbol available in the 6.0 SDK on an iOS 5 device will crash the application.
But Xcode won't warn about this when compiling, hence the need of some third-party software.
Once you identified the problematic symbol, using respondsToSelector: is the way to go, as it's better than simple version checking.
This way, you can have conditional code that will run with both SDK versions:
if( [ someObject respondsToSelector: #selector( someIOS6Method ) ] )
{ /* iOS 6 code */ }
else
{ /* iOS 5 code */ }
Only do this if you have detected SDK issues. Don't do this for everything.
According to UIVIewController class reference, this method is available from iOS 5.0 and higher.
Availability
Available in iOS 5.0 and later.
It is not ok to warn you. It doesn't have this warnining included in the default bundle of the SDK.

Resources