明示的なreleaseは死亡フラグ
「あるUIViewControllerが表示されるたびに、メンバ(例えば何らかのUIViewクラスとか)を作り直したい」ということが度々あり、何となく以下のような実装をしていました。(hogeViewメンバは @retain @synthesize 指定済)
-(void)viewWillAppear:(BOOL)animated { self.hogeView = [[[HogeView alloc] initWithFrame:CGRectMake(100, 100, 200, 200)] autorelease]; [self.view addSubview:hogeView]; } -(void)viewDidDisappear:(BOOL)animated { [self.hogeView release]; }
ところが上記のソースコードだと、これを指定したUIViewControllerを2回目に表示したタイミングでEXC_BAD_ACCESSが発生してしまいます。
冷静に考えてみればこれは当たり前の話で、2回目のviewDidAppearが呼ばれると、hogeViewに代入されていた古いオブジェクトのretainCountがマイナスになり死亡します。
つまり、
- 1回目の画面が消えるタイミングで、viewDidDisapperからreleaseメソッドが呼ばれる。
- しかし、releaseメソッドを呼んだだけでは、self.hogeView には nilオブジェクトは入らないが、retainCountは1減少して0になる。
- 2回目の画面表示のタイミングで、self.hogeView にかつて代入されていたオブジェクトのreleaseメソッドが呼ばれる。
- retainCountがマイナスに→死
つまりはreleaseメソッドを呼んでいたのが不幸の始まり。nilを代入してあげるのが正解です。
-(void)viewDidDisappear:(BOOL)animated { self.hogeView = nil; }