I'm trying to use iAds in my app but I want to support all versions from 4.0 upwards. However the code for setting the current size identifier has changed in the 4.2 sdk, it used to be:
ad.currentContentSizeIdentifier = ADBannerContentSizeIdentifier480x32;
but in 4.2 the code is:
ad.currentContentSizeIdentifier = ADBannerContentSizeIdentifierLandscape;
and therefore when if I use the old code in the 4.2 sdk it crashes and if I use the correct code for 4.2 any device running a previous version to 4.2 crashes. Does anyone know how I can support both or will I have to use 4.2 as the deployment target?
There is a workaround to support both 4.2 and earliers versions.
You could check if the constant exists at your ios version using something similar to the code bellow:
NSString *sizeIdentifier = &ADBannerContentSizeIdentifierLandscape != nil ? ADBannerContentSizeIdentifierLandscape : ADBannerContentSizeIdentifier480x32;
and then just use the string to initialize you iAd view
[yourAdBannerView setRequiredContentSizeIdentifiers:[NSSet setWithObject:sizeIdentifier]];
[yourAdBannerView setCurrentContentSizeIdentifier:sizeIdentifier];
There's some other problem in your code — use of ADBannerContentSizeIdentifier480x32 under 4.2 does not cause a crash, indeed it doesn't even trigger a compiler warning. It's deprecated but remains available.
Related
Recently I submitted my app on AppStore with a method setting badgecolor of tabbaritem.
[[[AppDelegate globalDelegate].tabBarController viewControllers] objectAtIndex:1].tabBarItem.badgeColor = kTabBarBadgeColor;
This badgeColor came in iOS 10 only and my app supported iOS 8 and above. I had no idea about it and the app got approved. Now, I have to resubmit my app with fixing this issue.
I want to know if there is a way to find out such cases where methods get deprecated or are visible in specific OS versions only.
By changing target of Xcode project you can see errors & warnings while building.
If you need more info,
You can visible all API changes like Added,Modified & Deprecated variants in Apple documentation
it will give you searching options for both Swift & Objective C
Searching UITabBarItem Instance Property badgeColor. it gives API changes are none.Supporting SDK's version
SDKs
iOS 10.0+
tvOS 10.0+
Searching finishedSelectedImage instance method of UITabBarItem.
SDK
iOS 5.0–7.0 Deprecated
Deprecated Use selectedImage with UIImageRenderingModeAlwaysOriginal
instead.
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
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.
I am testing an app on an iPhone 4 with iOS 5.1 and an iPad 4 with iOS 6.0. I looked around and surprisingly did not find similar questions:
1- My app has some methods that have been deprecated in iOS 6.0 so I believe I have to build some if/then conditions to test for system version using: [[UIDevice currentDevice] systemVersion], and then use the version appropriate methods. Is that the most efficient way?
2- My understanding is, with only one target, the "project" Deployment Target and the "Targets" deployment target serve the same purpose. And I need to have one of them or both as iOS 5.1 since that is the minimum iOS supported. What is confusing is that if the target is built based on iOS 5.1, how would it run on the iPad4 with iOS 6.0:
Does the iPad OS checks for target versions before running or just tries to run the code and it happens that the iOS 5.1 target does not have any code that the 6.0 is incompatible with?
Even if that is the case though, how could a 5.1 target support 6.0 methods that I built to conditionally replace deprecated methods?
Many thanks!
Deprecated methods
Deprecated methods can be used if you are targetting iOS versions that were released before those methods were deprecated. But assuming your deployment target is set correctly, you won't get any compiler errors unless those deprecated methods were always deprecated for the versions you are targetting. In other words, if you are seeing deprecation warnings in your code you need to fix them or check that your deployment target setting is correct. Do not ignore them!
Xcode setting levels
You mention the fact that you can define the deployment target setting at both the target and project level. Xcode build settings at the target level will override project settings. So define the deployment target at one of these levels only, then go to the other and hit delete so you don't have duplicate values. If you only have one target then it doesn't really matter if you define it at the target or project level.
Backwards and forwards compatibility
Finally, there are many factors that come into play for backwards and forwards compatibility. Sometimes there will be new iOS 6 methods like supportedInterfaceOrientations which will simply be ignored on older iOS versions. Other times you need to add explicit checks:
If you are calling a method on an object and that method was only introducted with iOS 6, you will need to add a respondsToSelector: check like this:
// only available on iOS 6
if ([locationManager respondsToSelector:#selector(pausesLocationUpdatesAutomatically)]) {
locationManager.pausesLocationUpdatesAutomatically = YES;
}
If you want to check if a particular class exists on the current iOS version, you can check the return value of the +class method like this:
// Only available on iOS 6
if ([UICollectionView class]) {
// ...
} else {
// class doesn't exist in this iOS version
}
If you want to check if a particular function is available, do a simple if statement on it:
// Only available in iOS 6
if (ABAddressBookCreateWithOptions) {
ABAddressBookCreateWithOptions(...);
} else {
ABAddressBookCreate(...);
}
Finally, if you want to check if a constant is available, check it's address:
// Only available in iOS 4
if (&UIApplicationProtectedDataDidBecomeAvailable) {
// subscribe to notification
}
Your Base SDK setting should always be set to "latest".
If you follow all these guidelines you will be able to solve most of your problems without having to add explicit version checks. Checking the iOS version or device ID is very brittle and is likely to cause your app to break in future versions. You really want to avoid it.
You can use [[UIDevice currentDevice] systemVersion] to detect the OS version, that would work. Rather than detecting the OS version, you could use respondsToSelector: to see what methods are present, NSClassFromString() != nil to see if classes are present, and fallback if that method is not available.
iOS is backward compatible, so iOS 6 will run iOS 5 apps just fine. However, if you want to use iOS 6 specific feature but still support iOS 5.1, you have to :
Compile using the 6.0 SDK so that the compilers knows new APIs
Set your target version to the lowest supported, aka. 5.1. Any system higher than that number will run the code. Any lower will not try.
Use one of the method described in 1. to make sure that each device execute codes the OS support.
I hope that's clear, don't hesitate if you have more questions
What you must do is detect functionality, not iOS version, please check out this thread:
Conditional support of iOS 6 features in an iOS 5 app
You shouldn't check against the system version but rather check against the functionality you are trying to use. On that note remember that deprecated does not mean removed so whatever you are trying to do may very well be there for iOS6. To check against a specific functionality you would do something like:
if([TheClassInQuestion class] != nil)
{
//use it
}
iOS is backwards compatible. If you compile your app for iOS 5.1 it will be perfectly run on iOS 6 as well. No need to re-implement deprecated classes.
But if you change your deployment version from 5.0 to 6.0, Xcode will show you warnings if you use deprecated methods
If you want to use methods, which are available only in iOS 6, you can use this check:
if ([self respondsToSelector:#selector(doSomething:)]) {
[self doSomething];
}
I am new to iPhone development. I started developing a project using iOS4.2 SDK. It works properly on both an iOS4.2 device and simulator. Later I realized that my app wasn't working on devices with iOS3.1.3. To solve this I updated the "Deployment Target" in my app's configuration file to "3.1.3".
The problem I am having is that I use UITapGestureRecognizer in some of my classes. On compiling my code using iOS 3.1.3 SDK I get the following errors:
error: 'UITapGestureRecognizer' undeclared (first use in this function)
error: 'tap' undeclared (first use in this function)
From what I have ready, this seems to be because iOS .1.3 does not support UITapGestureRecognizer, so to run this i made the following changes wherever I use UITapGestureRecognizer:
Class mailClass = (NSClassFromString(#"UITapGestureRecognizer"));
if(mailClass != nil)
{
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(findOutTheTagmap:)];
[imageView addGestureRecognizer:tap];
[tap release];
}
I also updated my Target configuration and set the UIKit Framework to "Weak". Additionally I have also made the following changes:
Base SDK: 3.1.3
Compiler Version: GCC4.2 (also tried with GCC4.0)
Mac OS X Deployment Target: Compiler Default (also tried with 10.4 and 10.6)
iOS Deployment Target: 3.1.3
Yet, when I try compiling my code, I am still shown the same errors. What is surprising is that a few days ago someone was helping me and this worked.
I have tried pretty much everything I have found in forums.
Does anyone have an idea on how I can proceed?
Thanks in advance!
Base SDK is the version of the SDK used to compile your application. You need to make sure it's set to a version that has all the features you're using. UIGestureRecognizer requires 3.2 or later, so you should set your Base SDK 3.2 or later. And actually, 3.2 was iPad only; if your app is for iPhone, you'll need to set Base SDK to 4.0 or later. 3.1.3 for the Deployment Target is correct. Check your code to make sure there aren't other classes you're using which aren't available in 3.1.3 (check the docs).
Matt Gallagher has a great article on this which I highly recommend, here. While you're there, read his whole blog, it's great. :)
Setting a different SDK as you've done can be useful for getting hard errors about what you can't use, but as you can see it's difficult to impossible (depending on the class) to work around.
Instead, you should always be building against the latest SDK. (In fact, newer versions of Xcode have a "latest" setting you should use.) Set iOS Deployment Target (IPHONEOS_DEPLOYMENT_TARGET) to your minimum version.