今回は、ARCを用いた場合のプロパティ利用に関するTipsです。
ARCって何?と言う方は、まずはこちらからどうぞ。
一般的なOutletにはweakプロパティを使う
Interface Builderなどを用いて作成したOutletは、一般的に別のview(例えばUIViewControllerのviewなど)のsubviewであることがほとんどです。したがって、これらのOutletのオーナーとなるのはsuperviewのみで十分だと言えます。
ViewControllerは、自身がOutletのオーナーになる必要がないので、この場合、weakプロパティの利用が適しています。
もちろん、UIViewControllerのviewや、UIWindowのwindowなど、トップレベルのviewに関してはstrongプロパティを使う必要がありますが、自分でこれらのOutletを設定することはまれでしょう。
weakプロパティを使うことで、不要な循環参照 (Strong reference cycle) を避けることができます。
viewDidUnloadの簡略化
Outletにweakプロパティを利用することには、もう一つ大きなメリットがあります。
メモリ不足が検知されたとき、viewが表示されていないUIViewControllerはすべてのview(自身のviewだけではなくsubviewもすべて)をunloadします。そのためviewDidUnloadが呼ばれるのですね。
したがって、もしstrongプロパティを使っていた場合、このタイミングで必ずオブジェクトを解放する(参照をやめる)必要があります。つまり、
@property (nonatomic, strong) IBOutlet UILabel *label;
に対しては、viewDidUnload内で必ず、
- (void)viewDidUnload {
self.label = nil; // nilをセットして参照をやめる(オーナーシップ権を破棄)
[super viewDidUnload];
}
としてあげる必要があるということです。
ここでもし、self.label = nil の処理を忘れてしまうと、UIViewControllerがlabelオブジェクトをいつまでも参照してしまい、結果としてlabelオブジェクトは破棄されません。せっかくシステムがunloadしてくれて、誰からも利用されていない状態なのに、そのオブジェクトを保持し続けてしまうのです。画面数が多いアプリでこれをやってしまったら、memory warningが上がっても不要なviewが解放されずにいつまでもメモリに空きが出ないでしょう。
しかし、weakプロパティを使っている場合、この処理は不要です。
@property (nonatomic, weak) IBOutlet UILabel *label;
この場合、システムがlabelオブジェクトをunloadした時点で、このオブジェクトはもう誰からも強参照されなくなります。したがって、ARCのルールに則りlabelオブジェクトはここで破棄されます。もちろん、破棄された時点でlabel変数にはnilが代入されます(__weak変数は、参照際のオブジェクトが破棄されたら自動的にnilが代入されるため)。
- (void)viewDidUnload {
// この時点ですでに、labelにはnilがセットされている
[super viewDidUnload];
}
これであれば、不要にオブジェクトを保持し続けてしまうことを避けられます。
viewDidUnloadでの処理がOutletの解放のみだった場合、結果的にviewDidUnloadのオーバーライド自体不要になるわけです。
このように、weakプロパティを使うことで、viewDidUnloadの実装を簡略化することができ、ミスによるトラブルを避けることが可能です。
strongプロパティを使うべきとき
上でも少し触れましたが、例外としてstrongプロパティを使わなくてはいけないこともあります。これは主に、Interface Builder(または、Storyboardの各scene)における、トップレベルのviewやwindowをOutletとして設定するときです。
このような場合は、strongプロパティにしておかないと、誰からも強参照されることなくload後に破棄されてしまので注意が必要です。
まとめ
もちろん、Outletのプロパティとしては、weakでもstrongでも動作可能です。しかしながら、weakプロパティを利用することでケアレスミスによるバグをさらに減らすことが可能です。このように、strong, weakは、状況に応じて使い分けることが重要だということです。
次回は、循環参照(Strong reference cycle)についてです。こちらも、strong, weakの使い分けに関する内容です。
質問、間違いの指摘などはツイッターでお願いします。@natsun_happy
参考資料
- Resource Programming Guide : Nib Files : Managing the Lifetimes of Objects from Nib Files | iOS Developer Library
- Beginning ARC in iOS 5 Part2 | Ray Wenderlich
関連記事


