Why Do iOS 9 Methods Still Work on iOS 8.4? - ios

I wanted to use the #warn_unused_result #rethrows func filter(#noescape includeElement: (Self.Generator.Element) throws -> Bool) rethrows -> [Self.Generator.Element] method in one of my projects. The App should run on iOS 8 and later. If I look the method up in the documentation it says "Availability: iOS (9.2 and later)"
However, if I call the method on iOS 8.4 it works w/o any issues.
Any ideas why the documentation says iOS 9.2 but it still works on iOS 8.4? So can I call it w/o any availability check and be sure it won't crash in the future?
Thanks in advance!

This is the part of Swift standard library, it doesn't depend on iOS SDK at all. Swift runtime is bundled with application, so for the system it doesn't matter which version of Swift application was written in. I assume that this availibility mark might have something in common with the change which was made to filter function in Swift 2. Look at those two docs:
Swift 2.1
Swift 1.2
As you can see, declarations of those two methods are different.

Related

iOS: Concurrency is only available in iOS 15.0.0 or newer in protocol

I have an app which deployment target is iOS 12.1, with many protocols defining functions with completion handlers, i.e.
protocol P {
func f(_ completion: #escaping: (String) -> Void)
}
I would like to replace all these with the new async/await iOS 15 syntax, for a better code readability:
protocol P {
func f() async -> String
}
But when doing so, I get the error:
Concurrency is only available in iOS 15.0.0 or newer
What is a good solution for this, considering that I just cannot switch the deployment target from 12.1 to 15.0?
Thank you for your help
For other people who are looking facing this issue on 15.0 target.
This is likely related to your XCode version, you need to be have minimum XCode 13.2 or later to compile code which uses Swift Concurrency on versions older than iOS 15.
The short answer is "there is currently no solution." If you want your apps to run on iOS 12 and earlier, you can't use the async/await calls, unless you want to write 2 versions of all your async code, one that runs on iOS < 15, and the other that runs on iOS ≥ 15.
As George mentions in his comment, Apple is trying to figure out how to "back-depoloy" async/await support. If they are able to do that, you will be able to use the modern approach with older versions, but I would bet Apple will not go back as far as iOS 12.
Edit:
See Bradley's comment below. The best you will get is async/await support in iOS 13, if Apple is able to pull that off. From the link Bradley posted, iOS 12 definitely won't be supported.

iOS 13 - FileManager url(forPublishingUbiquitousItemAt:expiration:) not working anymore

I've developed an iOS app that uses the url(forPublishingUbiquitousItemAt:expiration:) method of Apple's FileManager class. Starting with the first Beta of iOS 13 this function stopped working and now it throws an error, stating "This code has been removed. You should switch off of this SPI". But I can't find anything related to this function neither in the release notes of iOS nor in the documentation for this function, and it even states there that it would be supported on Mac Catalyst 13.0+.
This also has nothing to do with Xcode 10 and 11, as it occurs when the app is built using either one of those versions.
Does anyone of you know more about that? It would be great to get new information on that.
Thanks,
Fabian.
This is fixed in iOS 13 beta 6. Updated today and this error magically disappeared!
Had my mind blown when I saw this error message.

fontWithSize(fontSize: CGFloat) is available from which ios Version

I was using this function to change the font size of a label in UIButton.
Like this(SWIFT) :-
Button!.titleLabel?.font = Button!.titleLabel?.font.fontWithSize(12)
I want to see the availability of this funtion for ios 7. So i see the quick help documentation of Xcode. There it was mentioned as iOS (8.0 and later)
Then i went on to search for the appropiate funtion on apple website but there it is wriiten that its available from Available in iOS 2.0 and later. See Here for ref.
Please do let me know which one to trust.
I saw answer but i am not that satisfied as i check the other class
Like NSMutableAttributedString for swift
here it is written as available from iOS (3.2 and later)
My strong guess is that since Swift came out together with iOS 8 Apple's documentation won't show anything being available before that. If you check the same method on Objective-C side, you'll see the same as on the web:
I also have a project targeting iOS 7 with calls to fontWithSize in Objective C and they work fine. So there should be no reason for it to not be available on Swift side of things.
Also found information from Apple's Radar system:
Engineering has the following feedback for you:
This is expected - Swift was not available until WWDC 2014 and the introduction of iOS 8, therefore the availability of these methods and contstants in Swift is correctly documented as iOS 8+.
Thank you for your feedback. Engineering has determined that this issue behaves as intended.
So clearly this is the Apple way of doing things, as usual.
in Objective C
it is still 2.0

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.

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