UIViewController で次のプロパティを定義しています。
@property (nonatomic, strong) UIButton *strongButton;
@property (nonatomic, weak) UIButton *weakButton;
これらのプロパティは、Interface Builder では設定されません (つまり、コードで明示的に設定しない限り、常に nil のままです)。
また、UIButton にカテゴリを追加して、いつ割り当てが解除されたかを正確に把握できるようにしました。
@implementation UIButton (test)
- (void)dealloc { NSLog(@"Dealloc called."); }
@end
viewDidLoad
UIViewControllerに次のコードがあります。
self.strongButton = [[UIButton alloc] init];
self.weakButton = self.strongButton;
NSAssert(self.weakButton != nil, @"A: Weak button should not be nil.");
NSLog(@"Setting to nil");
self.strongButton = nil;
NSLog(@"Done setting to nil");
NSAssert(self.weakButton == nil, @"B: Weak button should be nil.");
そのコードを実行すると、2 番目のアサーション (B) で失敗します。ログには次のように表示されます。
- ゼロに設定
- nil に設定完了
- * -[ViewController viewDidLoad] でのアサーションの失敗
- *キャッチされない例外「NSInternalInconsistencyException」が原因でアプリを終了します。理由:「B: 弱いボタンは nil にする必要があります。」
ただし、最初のアサーションをコメントアウトすると、次のようになります。
self.strongButton = [[UIButton alloc] init];
self.weakButton = self.strongButton;
//NSAssert(self.weakButton != nil, @"A: Weak button should not be nil.");
NSLog(@"Setting to nil");
self.strongButton = nil;
NSLog(@"Done setting to nil");
NSAssert(self.weakButton == nil, @"B: Weak button should be nil.");
ログでこれを使用すると、コードは正常に実行されます。
- ゼロに設定
- 割り当て解除が呼び出されました。
- nil に設定完了
最初のシナリオで、dealloc が適切なタイミングで呼び出されていないことに注意してください。
最初の NSAssert がこの奇妙な動作を引き起こしているのはなぜですか? これはバグですか、それとも何か間違っていますか?
(私はiOS 6.1を使用しています)