2012-03-18 7 views
5

最近、Cocoaを使っていて、iOSに目を向けると、「 - [UIDeviceRGBColor copyWithZone:]:インスタンスに送られたセレクタが認識されませんでした...」というSIGABRTを取得するのに驚いていました。iOSクラスでは、アクティブなメモリを奨励するためにcopyWithZoneプロトコルを採用していないのはなぜですか?

NSColorとは対照的に、UIColorはクラス参照を参照していましたが、UIColorはプロトコルを採用していません。

今、これは大きな問題ではありません。私は、カラーインスタンスのアクティブな所有権を取って、使用直後に破棄するようにして、より効率的にしようとしていました。しかし、AppleがiOSのガベージコレクタを省略した理由は、メモリが枯渇し、バッテリチャレンジされたポータブルデバイスにリーンなメモリプロファイルを維持するために、開発者が自分が行っていたことを正確に行うよう促すことだと思った。

アップルの根拠に関するアイデア、または私の前提に何らかの誤りがありますか?

+1

おそらく、これは役に立ちます:http://robnapier.net/blog/implementing-nscopying-439 – CodaFi

+1

頭がおかしくなりました。あなたのブログエントリはこの特定の質問に答えませんが、コピープロトコルを実装しているクラスのディープコピーオーバーライドを書くことに決めたなら、はるかに深刻な疑問を抱くでしょう。優れた説明。 – Wienke

+0

あなたの質問は素晴らしいです。 +1 – CodaFi

答えて

5

NSCopyingプロトコルの実装が「アクティブなメモリ管理を促進する」と思われる理由がわかりません。

UIColorは不変(内部状態を変更するメソッドは実装されていません)であるため、コピーを作成する点はありません。完了したらそれを維持したい場合はretain、それが完了したらreleaseにしてください。他に何も必要ありません。

あなたが本当に望んでいた場合は、カテゴリにコピーを追加することができますが:

@implementation UIColor (Copying) <NSCopying> 

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

@end 

しかし、明らかにそれは実際にあなたに新しい機能を与えるものではありません。どうやら、Appleはそのクラスを実装したときにはそれが価値があるとは思わなかった。

+0

提案していただきありがとうございます。この特定の例では、「保持」と「解放」のバランスをとって同じことを実現できます。しかし、なぜ* NSColor *は 'copyingWithZone:'を実装していますか? NSColorも不変です。おそらく私の質問を提起するためのより良いクラスはUIImageです。 UIImageは日曜日に6つの方法で変更可能ですが、NSCopyingには準拠していません。その一方で、Cocoaの対応版であるNSImageはそうしています。あなたの思考を刺激する反応は新しい質問を追加し、元のものを改訂します。 – Wienke

+0

AppKitとUIKit、そしてNSColorとUIColorは、少なくとも10年は別のチームによって作成されました。これらは完全に一貫しているわけではありません。ほとんどの場合、UIKitのバージョンは小さく、よりクリーンです。 (特にNSImageは完全な災害でした)また、UIImageをもう一度チェックしてください - 私は突然変異の方法を見ません。 –

+0

一般的に、UIKitの設計目標は「AppKitですが、すべての迷惑メールがないため、非常に少ないメモリを搭載した超小型の携帯電話に適合させることができます。今、私たちは永遠にそれをサポートしなければなりません "。 UIColorとUIImageのサポートに「」を付けることに意味がなかったので、彼らはそれをやめました。 –

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 

ランタイムのclass_addMethodを使用してUIColor>>#copyWithZoneを追加するコードの試みを。私はこれがUIColor>>#copyWithZoneをカテゴリに直接実装するよりも優れているかどうかはわかりませんが、AppleのAvoid Category Method Name Clashesを読むことは、既存のフレームワークメソッド(iOS6ではUIColor>>#copyWithZone)を再実装することが悪いことを意味します。しかし、私は+initializeがフレームワークの+initializeに潜んでいる可能性があることに気付きました。

+0

私を 'class_addMethod'に紹介してくれてありがとうございます。私は '+ initialize'をオーバーライドすることについて慎重にすべきだと思います。特にUIColorはクラスクラスターです。個人的には、非専門家として、私は面倒ですが安全です。そして、initメソッドに組み込むのではなく、この作業を行う別のカテゴリメソッドを呼び出します。 – Wienke

関連する問題