ARC を利用している際に注意すること

ARC を利用していて少し気づきにくい問題に遭遇したのでメモしておく。

例えば、以前は baseViewController に addViewController を addSubView して表示する場合、以下の様なコードを書いていたがコレだと、ARC を利用した場合に BAD_ACCESS が発生する場合がある。

1
2
3
4
5
6
7
8
9
10
11
12
13
// 1. ARC 以前のコード
@implementation baseViewController
 
- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
 
    UIViewController *_tv = [[addViewController alloc] initWithNibName:@"addViewController" bundle:nil];
 
    _tv.view.center = self.view.center;
    [self.view addSubview:_tv.view];
}

retain count を考慮していると上記の様なコードが記述できたが、ARC を利用していると viewDidLoad メソッドを処理を抜けたタイミングで _tv が解放されるため、_tv 上のオブジェクトにアクセするする処理を行うと BAD_ACCESS が発生する。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 2. ARC を利用した際のコード
@interface baseViewController ()
@property(strong, nonatomic) addViewController *tv;
@end
 
@implementation baseViewController
 
- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
 
    _tv = [[addViewController alloc] initWithNibName:@"addViewController" bundle:nil];
 
    _tv.view.center = self.view.center;
    [self.view addSubview:_tv.view];
}

ARC 利用時は _tv が解放されないように包含されるクラスのメンバ変数としておく必要がある。
当たり前といえば当たり前だが、できるだけアクセスしなくてよいメンバ変数は定義しないようにと意識してるとハマります。
この問題最初に遭遇した時、1時間悩みました。(ノД`)

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です