I have the following properties defined on a UIViewController:
@property (nonatomic, strong) UIButton *strongButton;
@property (nonatomic, weak) UIButton *weakButton;
These properties are not set via Interface Builder (i.e. they will always remain nil as long as I don't set them explicitly in code).
I also added a category on UIButton to know exactly when it is dealloced:
@implementation UIButton (test)
- (void)dealloc { NSLog(@"Dealloc called."); }
@end
I have the following code in the viewDidLoad
of the 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.");
When I run that code, it fails on the second assertion (B). The log shows:
- Setting to nil
- Done setting to nil
- * Assertion failure in -[ViewController viewDidLoad]
- * Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'B: Weak button should be nil.'
However, when I comment out the first assertion:
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.");
The code runs fine with this in the log:
- Setting to nil
- Dealloc called.
- Done setting to nil
Notice how the dealloc is not being called at the proper time in the first scenario.
Why is that first NSAssert causing this weird behavior? Is this a bug or am I doing something wrong?
(I am on iOS 6.1)