LoginSignup
3
3

More than 5 years have passed since last update.

ゲッタでnil判定してインスタンス変数を作成する際のはまりどころ

Posted at

ここ半年くらい、コードでサブビューをインスタンス変数として持つ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に入っているのが別人になります。

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3