Can you use Objective-C categories to clean up backwards compatibility with older SDKs?
There are 2 main considerations to take into account when thinking about backward compatibility :
- build target
- current SDK for开发者_C百科 compilation
If I compile with iOS SDK 3.1.3, [UIScreen mainScreen].scale
will raise an error.
To deal with this, I can write :
CGLoat scale = 1.0;
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 40000
scale = [UIScreen mainScreen].scale;
#endif
But... if my minimum version target is let's say 3.1.3, this call will crash a 3.1.3 device, even if it compiles fine.
So I must write :
CGFloat scale = 1.0;
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 40000
if ([UIScreen instancesRespondToSelector:@selector(scale)])
scale = [UIScreen mainScreen].scale;
#endif
Saying that, I wonder if there is a way to implement
- (CGFloat)scale;
into a UIScreen category, inside which I could manage this kind of problem, and then the caller would just have to write :
CGFloat scale = [UIScreen mainScreen].scale;
without having to think about its used SDK nor its min target.
If possible, how would you write such a category so that it compiles fine with a 3.1.3 SDK, a 4.3 SDK, and runs fine on a 3.1.3 device as on a 4.3 device?
You could do this with some method-swizzling, but I really wouldn't recommend it (gets confusing really fast).
I'd prefix your category method instead, something like foo_scale
. This way you won't run into name conflicts and you still only have one method to call.
You don't need the pre-processor macro (nor should you use them for this sort of task — try to forget about precise iOS versions, and think more in terms of available features. This will be more flexible for you in the long run).
You could write a category method like so:
- (CGFloat)my_scale { // or whatever prefix you choose. you shouldn't try to mash with Apple's method names
CGFloat scale = 1.0f;
if ([UIScreen instancesRespondToSelector:@selector(scale)])
scale = [UIScreen mainScreen].scale;
return scale;
}
Do this, and make sure your Base SDK
is set to Latest iOS
(which will always choose the latest iOS version for whichever SDK version you have installed), and set your Deployment Target
to iOS 3.1.3
or the lowest version to which you want to deploy.
This combination will alleviate the need for a pre-processor macro, and it will compile and run just fine, too. This gives you more flexibility.
精彩评论