2009-07-11 6 views
2

私は、データオブジェクトクラスを持っている:自己でプロパティにアクセスすると、プログラムがクラッシュするのはなぜですか?と合成アクセッサ?

@interface Item: NSObject { 
    NSString *title; 
    NSString *text; 
} 

@property (copy) NSString *title; 
@property (copy) NSString *text; 

@end 

@implementation Item 

@synthesize text; 

- (void)updateText { 
    [email protected]"new text"; 
} 

- (NSString *)title { 
    return title; 
} 

- (void)setTitle:(NSString *)aString { 
    [title release]; 
    title = [aString copy]; 
} 

@end 

非合成された方法を使用しているとき、私はちょうど罰金titleプロパティを設定することができますが、私が合成アクセサでプロパティを設定すると、私はライン上updateText方法でエラーが出ますそれは読む:

[email protected]"new text"; 

エラーは次のとおりです。

*** NSInvocation: warning: object 0x462d2c0 of class '_NSZombie_CFString' does not implement methodSignatureForSelector: -- trouble ahead 
*** NSInvocation: warning: object 0x462d2c0 of class '_NSZombie_CFString' does not implement doesNotRecognizeSelector: -- abort 

がなぜ同一の非合成されませんプロセッサーは動作し、合成されたプロセッサーは動作しませんか?

オブジェクトはメインスレッドで作成され、NSOperationスレッドからアクセスするとエラーが表示されます。

答えて

0

投稿したコードはうまく動作します。このコードと使用している実際のコードの間に何か違いはありますか?

表示されているエラーメッセージは、既にリリースされているオブジェクトへのポインタである「ゾンビ」を参照しています。このコードには、このような動作の危険性が示されていないため、実際のエラーは他の場所にあると思うようになります。

Xcodeのデバッガを使用してNSStringオブジェクトのアドレスを確認し、その情報を使用して最終的にどちらがNSInvocationという警告になるかを判断することができます。

+0

オブジェクトはメインスレッドで作成され、NSOperationスレッドからアクセスするとエラーが表示されます。 – Rod

3

セッターはこのようにコード化する必要があります。

[title autorelease] 
title = [aString copy]; 

そうでない場合は、別のスレッドがその足の下でリリースタイトルオブジェクトを取得することがあります。

か、それをコピーする前に、この解放するコード[self setTitle:[self title]]とのdealloc titleMemory Management Programming Guide for Cocoa

+2

これのために自動解放を行うことを無駄にする必要はありません。 setterの標準コードは、新しいタイトルと古いタイトルのポインタの等価性を防ぎます。 if(title!= aString){[タイトルリリース]; title = [aStringコピー]; } –

+0

注意:これらは文字列であり、理由のためにコピーしています。 title!= aStringは可変文字列で本当に厄介になるかもしれません。 – IlDan

+1

私はautoreleaseアプローチを好んでいます。コードが少なくて済み、パフォーマンスの差が目立たない時間の99.9%です。 –

0

から、他の一貫したアクセサスタイルを選択します。 セッターにtitle == aStringが含まれているかどうかを確認する必要があります。