ここ半年くらい、コードでサブビューをインスタンス変数として持つUIViewControllerを作成するときに、readonlyのプロパティでゲッタを定義してnilのときのみ作成するということをやっていました。
コードはこんな感じです
// interface
@property (nonatomic, readonly) UIView *subview;
// implementation
@synthesize subview = _subview;
- (void)viewDidLoad
{
[super viewDidLoad];
[self.view addSubview:self.subview];
}
- (UIView *)subview {
if (_subview == nil) { // <- (2)
CGRect frame = self.view.bounds; // <- (1)
_subview = [[UIView alloc] initWithFrame:frame];
}
return _subview;
}
この書き方のメリットは、subviewが必要なときに作成されるのでnilが返ることを心配しなくてよいというところです。
しかし、-subviewがviewDidLoadの前(self.view == nilのとき)に呼び出されるとどうなるのか…?
(い) まず(1)の部分でself.viewを呼び出しているのでself.viewが作成されviewDidLoadが呼ばれます。
(ろ) 次に、viewDidLoadが呼ばれますが、このときはまだ _subview == nil なので(2)の条件式を通り_subviewにビュー(A)が代入され、viewDidLoadに戻ってビュー(A)がself.viewにaddされます。
(は) ここで(い)のとき呼び出されていた-subviewに戻ってきて、ビュー(A)が入っている_subviewにビュー(B)が代入されます。
この条件だとself.viewにaddされているビューインスタンスとself.subviewに入っているのが別人になります。