web-dev-qa-db-ja.com

Objective-Cで@propertyを保持、割り当て、コピー、非アトミック

Objective-Cに不慣れな人として、誰かが私に@propertyディレクティブに従う、保持、割り当て、コピー、および私が見逃している他の人の概要を教えてもらえますか?彼らは何をしているのですか?

205
Mark Reid

MrMageからリンクされた記事は機能しなくなりました。したがって、Objective-Cでの(非常に)短時間のコーディングで学んだことは次のとおりです。

非アトミックとアトミック-「アトミック」がデフォルトです。常に「非原子」を使用します。理由はわかりませんが、読んだ本では、「アトミック」を使用する「まれな理由」があると述べています。 (ところで:私が読んだ本はBNR「iOSプログラミング」本です。)

readwrite vs. readonly-「readwrite」がデフォルトです。 @synthesizeを実行すると、ゲッターとセッターの両方が作成されます。 「読み取り専用」を使用すると、セッターは作成されません。オブジェクトのインスタンス化後に変更したくない値に使用します。

保持vs.コピーvs.割り当て

  • 「assign」がデフォルトです。 @synthesizeによって作成されるセッターでは、値は単純に属性に割り当てられます。私の理解では、「assign」は非ポインター属性に使用されるべきです。
  • 属性がオブジェクトへのポインターである場合、「保持」が必要です。 @synthesizeによって生成されたセッターは、オブジェクトを保持します(別名保持カウントを追加します)。作業が終了したら、オブジェクトを解放する必要があります。
  • オブジェクトが変更可能な場合、「コピー」が必要です。この時点でオブジェクトの値が必要であり、その値がオブジェクトの他の所有者による変更を反映したくない場合に使用します。コピーを保持しているため、作業が終了したらオブジェクトを解放する必要があります。
266
Blamdarot

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

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

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

  • アクセサーメソッドは、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の属性のリスト

    atomic、nonatomic、retain、copy、readonly、readwrite、assign、strong、getter = method、setter = method、unsafe_unretained

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

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

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

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

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

Setterメソッドは、オブジェクトの保持カウントを増やし、自動解放プールのメモリを占有します。

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

可変文字列が設定され、その後に変更された場合でも、インスタンスは設定時にその値をキャプチャします。 setterおよびgetterメソッドは合成されません。

@property (copy) NSString *name;

今、

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

nameは影響を受けません。

  • readonly setterメソッドを介してプロパティの変更を許可しない場合は、プロパティを読み取り専用として宣言できます。

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

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

これは読み取り専用の反対です。

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

ガベージコレクションが有効な場合、retainとassignは基本的に交換可能であることに注意してください。

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

ARCが付属しています。

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

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

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

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

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

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

@property (unsafe_unretained) NSObject *unsafeProperty;

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

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

多くの記事を読んだ後、すべての属性情報をまとめることにしました:

  1. アトミック//デフォルト
  2. 非原子
  3. strong = retain // default
  4. weak = unsafe_unretained
  5. 保持する
  6. //デフォルトを割り当てる
  7. unsafe_unretained
  8. コピー
  9. 読み取り専用
  10. readwrite //デフォルト

以下は、これらの属性を見つけることができる詳細な記事へのリンクです。

ここで最高の回答をしてくれたすべての人に感謝します!!

iOSの可変プロパティ属性または修飾子

これが記事のサンプルの説明です

  1. atomic-Atomicは、1つのスレッドのみが変数(静的型)にアクセスすることを意味します。 -Atomicはスレッドセーフです。 -しかし、パフォーマンスは遅いです-atomicはデフォルトの動作です-ガベージコレクトされていない環境(つまり、retain/release/autoreleaseを使用する場合)のAtomicアクセサーはロックを使用して、別のスレッドが正しい設定/取得を妨げないようにします値の。 -実際にはキーワードではありません。

例:

@property (retain) NSString *name;

@synthesize name;
  1. nonatomic-Nonatomicは、複数のスレッドが変数にアクセスすることを意味します(動的型)。 -Nonatomicはスレッドセーフではありません。 -しかし、パフォーマンスは高速です-Nonatomicはデフォルトの動作ではありません。プロパティ属性にnonatomicキーワードを追加する必要があります。 -2つの異なるプロセス(スレッド)が同じ変数に同時にアクセスすると、予期しない動作が発生する可能性があります。

例:

@property (nonatomic, retain) NSString *name;

@synthesize name;

説明する:

「name」というアトミックストリングプロパティがあり、スレッドAから[self setName:@ "A"]を呼び出し、スレッドBから[self setName:@ "B"]を呼び出し、[self name]から呼び出したとします。スレッドCの場合、異なるスレッドでのすべての操作はシリアルで実行されます。つまり、1つのスレッドがセッターまたはゲッターを実行している場合、他のスレッドは待機します。これにより、プロパティ "name"の読み取り/書き込みが安全になりますが、別のスレッドDが同時に[name release]を呼び出すと、セッター/ゲッター呼び出しがないため、この操作でクラッシュが発生する可能性があります。つまり、オブジェクトは読み取り/書き込みセーフ(ATOMIC)であるが、別のスレッドが任意のタイプのメッセージを同時にオブジェクトに送信できるため、スレッドセーフではありません。開発者は、そのようなオブジェクトのスレッドセーフを確保する必要があります。

プロパティ「名前」が非アトミックである場合、上記の例のすべてのスレッド-A、B、C、およびDが同時に実行され、予測できない結果が生成されます。アトミックの場合、A、B、Cのいずれかが最初に実行されますが、Dは引き続き並列に実行できます。

  1. strong(iOS4 = retain)-「これをポイントしなくなるまでヒープ内に保持する」-つまり「私」所有者であるため、retainと同じように狙いを定める前にこれの割り当てを解除することはできません。」-オブジェクトを保持する必要がある場合にのみstrongを使用します。 -デフォルトでは、すべてのインスタンス変数とローカル変数は強力なポインターです。 -通常はUIViewControllers(UIアイテムの親)に対してstrongを使用します-strongはARCと共に使用され、オブジェクトの保持カウントを心配する必要がないため、基本的に役立ちます。 ARCは、作業が完了すると自動的に解放します。strongキーワードを使用することは、オブジェクトを所有していることを意味します。

例:

@property (strong, nonatomic) ViewController *viewController;

@synthesize viewController;
  1. weak(iOS4 = unsafe_unretained)-「誰かが強く指示している限りこれを保持する」と言う-assign、retainまたはno release-「弱い」参照は、保持しない参照です。 -IBOutlets(UIViewControllerのChilds)には通常、weakを使用します。これは、親オブジェクトが存在する場合にのみ子オブジェクトが存在する必要があるため機能します。 -弱参照は、参照オブジェクトをガベージコレクターによるコレクションから保護しない参照です。 -Weakは基本的にassignであり、保持されないプロパティです。オブジェクトの割り当てが解除された場合を除き、ウィークポインターは自動的にnilに設定されます

例:

@property (weak, nonatomic) IBOutlet UIButton *myButton;

@synthesize myButton;

強くて弱い説明、 BJ Homerに感謝

私たちのオブジェクトが犬であり、犬が逃げる(割り当て解除される)ことを想像してください。強いポインターは犬の綱のようなものです。リーシュを犬に取り付けている限り、犬は逃げません。 5人が1匹の犬に綱を付けた場合(1つのオブジェクトへの5つの強いポインター)、5匹の綱すべてが切り離されるまで犬は逃げません。一方、弱いポ​​インターは、小さな子供が犬を指差して、「見て!犬!」と言っているようなものです。犬がひもにつながれている限り、小さな子供たちは犬を見ることができ、犬はそれを指し示します。しかし、すべてのひもが外されるとすぐに、犬はそれを何人の小さな子供が指していても逃げます。最後の強力なポインター(リーシュ)がオブジェクトをポイントしなくなるとすぐに、オブジェクトの割り当てが解除され、すべての弱いポインターがゼロになります。弱いときは?ウィークを使用したいのは、保持サイクルを回避したい場合だけです(たとえば、親が子を保持し、子が親を保持するため、どちらも解放されません)。

  1. retain= strong-保持され、古い値が解放されて割り当てられます-retainは新しい値を送信することを指定します-割り当てと古い送信された値-release -retainはstrongと同じです。 -Appleは、retainを記述すると、自動変換/強力な動作のみを行うと言います。 -「alloc」などのメソッドには、暗黙の「保持」が含まれます。

例:

@property (nonatomic, retain) NSString *name;

@synthesize name;
  1. assign-assignはデフォルトで、単に変数の割り当てを実行します-assignは、プロパティのセッター実装を合成する方法をコンパイラに指示するプロパティ属性です-I Cプリミティブプロパティにはassignを使用し、Objective-Cオブジェクトへの弱い参照にはweakを使用します。

例:

@property (nonatomic, assign) NSString *address;

@synthesize address;
  1. unsafe_unretained

    -unsafe_unretainedは所有権修飾子であり、ARCに保持/解放呼び出しを挿入する方法を指示します。-unsafe_unretainedは、ARCバージョンのassignです。

例:

@property (nonatomic, unsafe_unretained) NSString *nickName;

@synthesize nickName;
  1. copy-オブジェクトが可変の場合、コピーが必要です。 -copyは、新しい値を送信することを指定します-割り当て時にコピーし、古い値を送信します-release。 -copyはretainのようなもので、ガベージコレクトされていない環境で明示的に解放する必要がある(たとえば、deallocで)オブジェクトを返します。 -copyを使用する場合、deallocでそれを解放する必要があります。 -この時点でオブジェクトの値が必要であり、その値がオブジェクトの他の所有者によって行われた変更を反映したくない場合に使用します。コピーを保持しているため、作業が終了したらオブジェクトを解放する必要があります。

例:

@property (nonatomic, copy) NSArray *myArray;

@synthesize myArray;
146
swiftBoy

アトミックプロパティには、一度に1つのスレッドのみがアクセスできます。 スレッドセーフです。デフォルトはアトミックです。キーワードがないことに注意してくださいatomic

Nonatomicは、複数のスレッドがアイテムにアクセスできることを意味します。thread unsafe

そのため、アトミックを使用する際は非常に注意する必要があります。コードのパフォーマンスに影響を与えるため

8
Kannan Prasad