您是否可以使用Objective-C类别来清除与旧SDK的向后兼容性?

时间:2011-09-06 18:11:40

标签: iphone objective-c ios categories backwards-compatibility

在考虑向后兼容性时,需要考虑两个主要注意事项:

  • 构建目标
  • 当前用于编译的SDK

如果我使用iOS SDK 3.1.3编译,[UIScreen mainScreen].scale将引发错误。

为了解决这个问题,我可以写一下:

CGLoat scale = 1.0;
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 40000
scale = [UIScreen mainScreen].scale;
#endif 

但是......如果我的最低版本目标是3.1.3,这个调用会使3.1.3设备崩溃,即使它编译得很好。

所以我必须写:

CGFloat scale = 1.0;
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 40000
    if ([UIScreen instancesRespondToSelector:@selector(scale)])
        scale = [UIScreen mainScreen].scale;
#endif

说,我想知道是否有办法实施

- (CGFloat)scale;

进入一个UIScreen类别,我可以在其中管理这类问题,然后调用者只需要写:

CGFloat scale = [UIScreen mainScreen].scale;

无需考虑其使用的SDK及其最小目标。

如果可能的话,你会如何编写这样一个类别,以便用3.1.3 SDK,4.3 SDK编译好,并在3.1.3设备上运行,如同在4.3设备上一样?

2 个答案:

答案 0 :(得分:1)

可以通过一些方法调整来实现这一点,但我真的不会推荐它(真的很快就会让人感到困惑)。

我会为您的类别方法添加前缀,例如foo_scale。这样您就不会遇到名称冲突,并且您仍然只有一种方法可以调用。

答案 1 :(得分:0)

您不需要预处理器宏(也不应该将它们用于此类任务 - 尝试忘记精确的iOS版本,并在可用功能方面考虑更多。这对您来说更灵活从长远来看。

您可以编写类似的类别方法:

- (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;
}

执行此操作,并确保Base SDK设置为Latest iOS(将始终为您安装的任何SDK版本选择最新的iOS版本),并将Deployment Target设置为iOS 3.1.3或您要部署的最低版本。

这种组合将减轻对预处理器宏的需求,并且它也可以编译和运行。这为您提供了更大的灵活性。