5

最近在使用 Cocoa 后转向 iOS,我惊讶地收到一个带有以下错误的 SIGABRT:“-[UIDeviceRGBColor copyWithZone:]: unrecognized selector sent to instance...”我在 UIColor 上调用了“copy”。

我查看了类引用,并且,与 NSColor 相比,UIColor 没有采用任何协议。

现在,这没什么大不了的。我只是试图通过主动拥有颜色实例来提高效率,以便在使用后立即丢弃它。但我认为 Apple 在 iOS 中省略垃圾收集器的目的是鼓励开发人员做我正在做的事情,在内存不足、电池挑战的便携式设备上保持精简的内存配置文件。

关于苹果的理由有什么想法,还是我的假设有一些错误?

4

2 回答 2

5

我不明白您为什么认为实施该NSCopying协议会“鼓励主动内存管理”。

由于UIColor是不可变的(它没有实现任何改变其内部状态的方法),因此没有必要进行复制。retain如果你想保留它,就release让它,当你完成时它。不需要其他任何东西。

如果你真的想要,你可以在一个类别中添加复制:

@implementation UIColor (Copying) <NSCopying>

- (id)copyWithZone:(NSZone *)zone
{
    return [self retain];
}

@end

但显然这实际上并没有给你任何新功能。显然,Apple 认为他们实施该课程不值得花时间。

于 2012-03-18T19:56:18.223 回答
3

我的应用程序需要同时在 iOS5(UIColor>>#copyWithZone不存在)和 iOS6+(UIColor>>#copyWithZone存在)上运行,所以我想出了以下内容:

@implementation UIColor(ios5CopyWithZone)

+ (void)initialize
{
    // iOS5 dosn't include UIColor>>#copyWithZone so add it with class_addMethod.
    // For iOS6+ class_addMethod fails as UIColor>>#copyWithZone already exists. 
    Class klass = [UIColor class];
    Method methodToInstall = class_getInstanceMethod(klass, @selector(ios5CopyWithZone:));
    class_addMethod(klass, @selector(copyWithZone:), method_getImplementation(methodToInstall), method_getTypeEncoding(methodToInstall));
}

// UIImage is immutable so can just return self.
// #retain to ensure we follow mem-management conventions
-(id)ios5CopyWithZone:(NSZone *)__unused zone
{
    return [self retain];
}
@end

代码尝试UIColor>>#copyWithZone使用运行时的class_addMethod. 我不知道这是否比UIColor>>#copyWithZone直接在类别中实现更好,但是阅读 Apple 的避免类别方法名称冲突意味着重新实现现有框架方法(即UIColor>>#copyWithZone在 iOS6 中)是不好的做法。但是我意识到这+initialize可能会践踏框架的+initialize.

于 2013-05-14T20:10:44.973 回答