第2回 @property,@synthesize,retain,assign,copyについて | 渋谷で働くUnity野郎

渋谷で働くUnity野郎

備忘録として有効活用していきます。

続いてはこちら。

(2)@propertyの属性ってなに? ~retain , assign, copy編~
次に、お待ちかね(?)の「retain」、「assign」、「copy」について紐解いていきます。

まず、これら3つ何が違うのか?
ズバッと言いますと、

アクセッサメソッドの実装です。

実際に見てみましょう。
次のようになっています。

--------------------------
@property(assign or retain or copy) NSString *example

@synthesize example;

とした場合、次のような実装がコンパイルによって自動合成される。

//assign属性を指定した場合
- (void)setExample:(NSString*)in {
example = in;
}

// retain属性を指定した場合
- (void)setExample:(NSString*)in {

if (example != in) {
[example release];
example = [in retain];
}
}

// copy属性を指定した場合
- (void)setExample:(NSString*)in {
if (property != newValue) {
[property release];
property = [newValue copy];
}
}

(※属性を指定しなかった場合は自動的にassignになります)
(ARC環境下では自動的にstrong)
--------------------------

まず、assignだが、見た通りreleaseもretainもされていない。引数を単に代入している。
つまり「オブジェクト型でない場合、assignを使用する」という事になる。
主にintやdouble、BOOLと言った変数に使います。
(オブジェクトに対しても使用可能ですが、あまり利用されません)

次にretainとcopyですが、これが少し難しい。

基本的には次の考え方で大丈夫です。
オブジェクトを値として扱っているようなときは、copy
それ以外の場合は、retain
(これに当てはまらない例外も勿論存在します。)

前者のコピーについて、分かりやすかった例はNSString型での宣言です。
@property(retain)NSString *str;
@synthesize str;

NSMutableString *mutableStr = [NSMutableString stringWithFormat@"hello"];
という宣言があったとします。

NSString型は引数として、可変なMutableStringを受ける可能性もあるので、次のような代入も考えられます。
str = mutableStr;

この時、
[mutalbeStr appendString@" World"];
とするとstrもそれに引きずられて中身がHello Worldに変わってしまいます。

このような参照元の値が予期せぬ内に変更されるのを防ぐ目的でcopyの使い方です。

@property(copy)NSString *str;の場合は勿論ですが、
[mutalbeStr appendString@" World"];としても、内容はHelloのままです。
ディープコピーですね。

※注意(どんでん返しなので、結構重要)
ただし、NSStringやNSArrayやNSDictionaryなどのMutableでないオブジェクトはcopyしても、言語仕様のため、
実際にはコピーされず、同じアドレスを指してしまう
のでcopyもretainも同じ意味になります。
ですが、暗黙的な意味でcopyを使うと良いでしょう!
(ちなみにMutable型のオブジェクトはディープコピーされるので、retainとcopyの意味合いは違います)


さてさて、ここまで色々記述してきましたが、copyの使いどころ。
あまりありません。

iphoneアプリ制作では基本的にretainでしょう。
先ほど述べた暗黙的な意味とMutable系のオブジェクトをディープコピーしたい場合にのみcopyを使うイメージで良いと思われます。
それ以外はretainで。

長々と書いてきたので、最後にまとめましょう。

(2)まとめ

assign => intやdouble,BOOLといったオブジェクト型でない変数に使用しよう。

copy => 暗黙的な理由(NSStringやNSValue,NSNumberなどの変数)と
Mutable型の変数をディープコピーしたい場合に使用する。

retain => それ以外!
(ビューやラベルやIBOUtlet)

---------------------------
コラム:
他に属性としreadonlyやreadwrite、そして頻繁に見るnonatomicがあります。
これらの属性は理解が簡単なので、ついでに覚えておきましょう。

readonly => 読み取りのみ(ゲッターのみ使用できる)
readwrite => 読み書きOK (ゲッター、セッター使用可能 デフォルト)

nonatomic => スレッドセーフにする。
(要はスレッドを仕様した際に、多重アクセスを生じても、値が破損しないようにする。)
スレッドを使わないなら、nonatomicに指定しておけばOK.
--------------------------

第1回 @property,@synthesizeについて

第3回 weak,strongについて