Objective-C での @property の保持、割り当て、コピー、非アトミック 質問する

Objective-C での @property の保持、割り当て、コピー、非アトミック 質問する

Objective-C 初心者なので、@property ディレクティブに続く、retain、assign、copy など、私が知らないものの概要を教えていただけますか? これらは何をするもので、なぜ他のものよりもこれらを使用する必要があるのでしょうか?

ベストアンサー1

@property の属性について知る前に、@property の用途を知っておく必要があります。

  • @property は、クラスがカプセル化しようとしている情報を定義する方法を提供します。@propertyを使用してオブジェクト/変数を宣言すると、そのオブジェクト/変数は、そのクラスをインポートする他のクラスからアクセスできるようになります。

  • ヘッダー ファイルで@propertyを使用してオブジェクトを宣言する場合は、実装ファイルで@synthesizeを使用して合成する必要があります。これにより、オブジェクトはKVC に準拠します。デフォルトでは、コンパイラはこのオブジェクトのアクセサー メソッドを合成します。

  • アクセサ メソッドは、setter と getter です。

例: .h

@interface XYZClass : NSObject
@property (nonatomic, retain) NSString *name;
@end

.m

@implementation XYZClass
@synthesize name;
@end

これで、コンパイラはnameのアクセサー メソッドを合成します。

XYZClass *obj=[[XYZClass alloc]init];
NSString *name1=[obj name]; // get 'name'
[obj setName:@"liza"]; // first letter of 'name' becomes capital in setter method
  • @propertyの属性のリスト

    アトミック、非アトミック、保持、コピー、読み取り専用、読み取り書き込み、割り当て、強力、ゲッター=メソッド、セッター=メソッド、unsafe_unretained

  • アトミックはデフォルトの動作です。オブジェクトがアトミックとして宣言されると、スレッドセーフになります。スレッドセーフとは、一度にそのクラスの特定のインスタンスの 1 つのスレッドだけがそのオブジェクトを制御できることを意味します。

スレッドが getter メソッドを実行している場合、他のスレッドはそのオブジェクトに対して setter メソッドを実行できません。これは遅いです。

@property NSString *name; //by default atomic`
@property (atomic)NSString *name; // explicitly declared atomic`
  • nonatomicはスレッドセーフではありません。 nonatomic プロパティ属性を使用すると、合成アクセサーが単に値を直接設定または返すことを指定できますが、同じ値が別のスレッドから同時にアクセスされた場合に何が起こるかについては保証されません。

このため、アトミック プロパティよりも非アトミック プロパティにアクセスする方が高速になります。

@property (nonatomic)NSString *name;   
  • 属性がオブジェクトへのポインターである場合は、retain が必要です。

setter メソッドはオブジェクトの保持カウントを増やすため、自動解放プールのメモリを占有することになります。

@property (retain)NSString *name;
  • copy copy を使用する場合、retain は使用できません。copy を使用すると、クラスのインスタンスに独自のコピーが含まれます。

可変文字列が設定され、その後変更された場合でも、インスタンスは設定された時点での値をキャプチャします。セッター メソッドとゲッター メソッドは合成されません。

@property (copy) NSString *name;

今、

NSMutableString *nameString = [NSMutableString stringWithString:@"Liza"];    
xyzObj.name = nameString;    
[nameString appendString:@"Pizza"]; 

名前は影響を受けません。

  • readonlyプロパティを setter メソッド経由で変更できないようにする場合は、プロパティを readonly として宣言できます。

コンパイラはゲッターを生成しますが、セッターは生成しません。

@property (readonly) NSString *name;
  • readwrite はデフォルトの動作です。readwrite 属性を明示的に指定する必要はありません。

これは readonly の反対です。

@property (readwrite) NSString *name;
  • assignment は、値をコピーしたり保持したりするのではなく、インスタンス変数に直接値を割り当てるセッターを生成します。これは、NSInteger や CGFloat などのプリミティブ型、またはデリゲートなどの直接所有していないオブジェクトに最適です。

ガベージ コレクションが有効になっている場合、retain と assignment は基本的に互換性があることに留意してください。

@property (assign) NSInteger year;
  • strong は、retain の代わりです。

ARCが付属しています。

@property (nonatomic, strong) AVPlayer *player; 
  • getter=methodゲッター メソッドに別の名前を使用する場合は、プロパティに属性を追加してカスタム名を指定できます。

ブール型プロパティ(YESまたはNOの値を持つプロパティ)の場合、ゲッターメソッドは「is」という単語で始まるのが通例です。

@property (getter=isFinished) BOOL finished;
  • setter=method setter メソッドに別の名前を使用する場合は、プロパティに属性を追加してカスタム名を指定できます。

メソッドはコロンで終わる必要があります。

@property(setter = boolBool:) BOOL finished;
  • unsafe_unretained Cocoa と Cocoa Touch には、まだ弱参照をサポートしていないクラスがいくつかあります。つまり、それらを追跡するために弱プロパティまたは弱ローカル変数を宣言することはできません。これらのクラスには、NSTextView、NSFont、NSColorSpace などが含まれます。これらのクラスのいずれかに弱参照を使用する必要がある場合は、安全でない参照を使用する必要があります。

安全でない参照は、関連するオブジェクトを存続させないという点で弱い参照に似ていますが、宛先オブジェクトが割り当て解除されてもnilに設定されません。

@property (unsafe_unretained) NSObject *unsafeProperty;

複数の属性を指定する必要がある場合は、次のように、それらをコンマ区切りのリストとして含めるだけです。

@property (readonly, getter=isFinished) BOOL finished;

おすすめ記事