【问题标题】:Support newer features in older versions of OS X SDK支持旧版本 OS X SDK 中的新功能
【发布时间】:2014-06-06 20:29:51
【问题描述】:

我通过参与一个开源项目 (IPMenulet) 了解了更多关于 Cocoa、Objective-C 和 Xcode 的知识;该项目最初支持 OS X 10.5。

我匆忙中似乎添加了使用旧版 SDK 不支持的 SDK 元素(NSJSONSerialization@autoreleasepool 编译器指令)的功能。现在,我正在尝试确定是否可以采取任何措施来恢复对 10.5 的支持

选项:

  • NSJSONSerialization - 我想我可以切换到JSONKit
  • @autoreleasepool {} - ?
  • @properties - 添加 @synthesize 和 IVARs

问题:

  • 如果操作系统支持的话,有没有办法(编译器指令?)使用较新的 SDK 元素,必要时切换到较旧的元素?如果是这样,在特定于版本的方法中重构功能是否更好(例如getJSONlegacygetJSON)?
  • 将原始项目标记为单独的分支会更好(以便对其进行增强)吗?

【问题讨论】:

  • 新功能的重点是抛弃旧操作系统。反向移植时,您需要采用最低公分母。回滚一切并重新开始。您也不一定需要依赖项来替换所有内容。 JSON解析器写起来很简单,你应该知道MRC,属性合成是clang的一个特性,而不是OS。

标签: objective-c xcode xcode5 osx-mavericks osx-leopard


【解决方案1】:

不同的功能涉及不同的 OS 组件,这些组件定义了如何在多个 OS X 版本中使用一个功能。这是我粗略的分类:

  • 功能完全由某些框架提供。例如,NSJSONSerialization 在 Mac OS X 10.7+ 中可用。您可以对所有操作系统版本使用相同的解决方案,或者在运行时检查某些功能是否可用。例如,

    if ([view respondsToSelector:@selector(setAcceptsTouchEvents:)])
        [view setAcceptsTouchEvents:YES];
    

    有关多个 SDK 支持的更多详细信息,请参见 SDK Compatibility Guide. Using SDK-Based Development

  • 功能完全由编译器提供。例如,@autoreleasepool,文字。

  • 功能由编译器和运行时提供。比如默认@property综合。更多详情请见Objective-C Feature Availability Index

  • 依赖于链接应用程序的 SDK 的功能。它更多的是关于行为变化,这种机制在AppKit Release Notes 的向后兼容性部分中进行了描述。

现在回到你的问题。如果某个功能可用,有一种机制可以在运行时检查,通常respondsToSelector: 可以完成这项工作。我建议公开一种适用于所有操作系统版本的单一方法。并且仅在此方法中存在操作系统版本之间的差异。例如,

- (NSString *)base64EncodingForData:(NSData *)data {
    NSParameterAssert(data);
    if ([data respondsToSelector:@selector(base64EncodedStringWithOptions:)]) {
        return [data base64EncodedStringWithOptions:NSDataBase64Encoding76CharacterLineLength];
    }
    else {
        // Manual encoding using <Security/SecEncodeTransform.h> and kSecBase64Encoding.
    }
}

您可以创建一些 1.1 维护分支,在 master 中执行所有工作,并仅合并到维护分支中的错误修复。因此,您将从维护分支发布 1.1.1 和 master 1.2。这是一种可行的方法。但是您不能无限期地支持 Mac OS X 10.5,因此您需要决定在哪个 IPMenulet 版本中您将放弃 10.5 支持。

【讨论】:

    【解决方案2】:

    在它完全有帮助的范围内,经典版本:

    @autoreleasepool { ... code ... }
    

    曾经:

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    
    ... code ...
    
    [pool drain];
    

    drain 比普通的release 更受欢迎,因为它可以正常工作(现在也已弃用)OS X 垃圾收集。但它算作释放,因此没有内存泄漏,您也不应该释放。

    【讨论】:

    • initdrain之间的代码(... code ...)是否标记为autorelease而无需做任何额外的工作?
    • 不是没有 ARC;你需要明确autorelease。对象将进入pool,然后在耗尽时完全释放。所以你所做的只是试图避免内存占用瓶颈——就像@autorelease一样。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-20
    • 2012-12-21
    • 2011-08-14
    • 2013-10-29
    相关资源
    最近更新 更多