开发者

Can you use Objective-C categories to clean up backwards compatibility with older SDKs?

开发者 https://www.devze.com 2023-04-03 14:48 出处:网络
There are 2 main considerations to take into account when thinking about backward compatibility : build target

There are 2 main considerations to take into account when thinking about backward compatibility :

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号