Programing Note

千里の道も一歩から

Programing Tips > Objective-C > @propertyの属性 strong と weak

Tweet

Advertisement



Event

・サイトを引っ越ししました。2016/10/15

新しいサイトはこちらです。

・サイトをリニューアルしました。2015/12/29

Related Articles:

@propertyの属性 strong と weak

Update on March 18, 2016

よくよく考えると?だった、@propertyの属性の「strong」と「weak」について

あっちこっちの資料を調べた結果、一応、こういうことなんじゃないかということを整理してみました。

間違っていたら、ごめんなさい。


確認環境:Xcode 7.2


まずは、動かして確認しましょう。


strong属性の「strongProperty」weak属性の「weakProperty」という2つのプロパティを持つ

「TESTClass001」クラスのクラスインターフェースを定義します。

なお、@propertyの属性は特に何も指定しなければ、「strong」になります。


TESTClass001.h


「viewDidLoad」で以下のような処理を行います。


ViewController.m


実行結果は、以下の通りです。

2回目のNSLogの結果で、「weakProperty」の値が Null になってます。

行ごとに説明していきます。


12行目: TESTClass001 *testClass = [[TESTClass001 alloc]init];

「testClass」という「TESTClass001」クラスのインスタンスを生成します。


14行目: NSString *string = [[NSString alloc]initWithFormat:@"変更前"];

NSString型「string」オブジェクトを「alloc」して「init」します。

「alloc」すると、オブジェクトは、メモリ領域に割り当てられます。

ついでですが、割り当てたメモリ領域は、たまたまその領域に残っていた「ゴミ」の影響がないように0が埋めらます。

そして「init」で初期値 ”変更前” を設定します。


おそらくですが、イメージとして、メモリ領域にこんな感じで「string」オブジェクトが割り当てられます。

(アドレスは適当です。)

ここで注目する点は、ARC(Automatic Reference Counting、自動参照カウント)では、

オブジェクトは「参照カウンタ」を持っているということです。

オブジェクトを生成すると、「参照カウンタ」は1になります。

なので、「string」オブジェクトの参照先 ”変更前”の「参照カウンタ」は、この時点で1になります。


16行目: testClass.strongProperty = string;

「testClass.strongProperty」に「string」オブジェクトの参照先 ”変更前” のアドレスがセットされます。

「testClass.strongProperty」は「strong」属性のプロパティです。

「strong」属性のプロパティからの参照は参照カウンタを+1します。

なので、「string」オブジェクトの参照先 ”変更前” の「参照カウンタ」は、この時点で2になります。


このことを「testClass.strongProperty」が ”変更前” を所有している、とか

「testClass.strongProperty」から ”変更前” への強い参照がある、と言います。


17行目: testClass.weakProperty = testClass.strongProperty;

「testClass.weakProperty」に「testClass.strongProperty」の参照先 ”変更前” のアドレスがセットされます。

「testClass.weakProperty」は「weak」属性のプロパティです。

「weak」属性のプロパティからの参照は参照カウンタを変化させません。

なので、testClass.strongProperty」の参照先 ”変更前” の「参照カウンタ」は、この時点で2のままです。


このことを「testClass.weakProperty」は ”変更前” を所有していない、とか

「testClass.weakProperty」から ”変更前” への弱い参照がある、と言います。


19行目: NSLog(@"strongProperty = %@ weakProperty = %@", testClass.strongProperty, testClass.weakProperty);

「testClass.strongProperty」と「「testClass.weakProperty」」の値を確認します。

strongProperty = 変更前 weakProperty = 変更前

となっています。


22行目: string = [[NSString alloc]initWithFormat:@"変更後"];

再度、NSString型「string」オブジェクトを「alloc」して「init」します。

14行目で、「alloc」したのと別のメモリ領域にオブジェクトを生成します。

22行目で、「string」オブジェクトを新たに生成したので「string」オブジェクトの参照先 ”変更後”の「参照カウンタ」は、1になります。

一方、14行目で生成した「string」オブジェクトの参照先 ”変更前”の「参照カウンタ」は、

14行目で、生成した「string」オブジェクトの参照がなくなるので、−1され1になります。



23行目: testClass.strongProperty = string;

「testClass.strongProperty」に「string」オブジェクトの参照先 ”変更後” のアドレスがセットされます。

「testClass.strongProperty」は「strong」属性のプロパティです。

「strong」属性のプロパティからの参照は参照カウンタを+1します。

なので、「string」オブジェクトの参照先 ”変更後” の「参照カウンタ」は、この時点で2になります。

一方、14行目で生成した「string」オブジェクトの参照先 ”変更前” の「参照カウンタ」は、

「testClass.strongProperty」からの参照がなくなるので、−1され0になります。


25行目: NSLog(@"strongProperty = %@ weakProperty = %@", testClass.strongProperty, testClass.weakProperty);

「testClass.strongProperty」と「「testClass.weakProperty」」の値を確認します。

strongProperty = 変更後 weakProperty = (null)

となっています。


ここまでの処理で、14行目で、生成した「string」オブジェクトの参照先 ”変更前”の「参照カウンタ」は、0になりました。

ARCでは、オブジェクトは「参照カウンタ」が0になると、割り当てが解放されます。

「testClass.weakProperty」からの参照が残っていますが、

「testClass.weakProperty」はweak属性のプロパティなので、

弱い参照があるだけでは、オブジェクトの寿命を保つことはできません。

なので、14行目で、生成した「string」オブジェクトの参照先 ”変更前” は解放され、その結果、「testClass.weakProperty」はnilになります。


補足:

このように、プログラムが動的に確保したメモリ領域のうち、不要になった領域を自動的に解放する機能のことを  ガベージコレクション(garbage collection; GC)といいます。

Objective-Cでは、ガベージコレクションとして、参照カウント方式を採用しています。

参照カウント方式には、

・MRR(Manual Retain-Release、明示的に記述したコードによる獲得と解放)

・ARC(Automatic Reference Counting、自動参照カウント)

の2つの手段があります。

「strong」と「weak」プロパティの属性は、ARCで使用する属性です。


inserted by FC2 system