Pregunta

Or alternatively: how could this UILabel usage possibly generate an NSMutableDictionary NSInvalidArgumentException?

This is a non-ARC iOS app. When showLabel (below) runs, I will occasionally, but very rarely, see [__NSDictionaryM setObject:forKey:] throw an error: NSInvalidArgumentException * setObjectForKey: key cannot be nil.

@property (nonatomic, retain) UILabel *myLabel;
@synthesize myLabel = _myLabel;

- (void)showLabel{

if (self.myLabel) {
    return;
}

self.myLabel                        = [[[UILabel alloc] initWithFrame:self.tableView.frame] autorelease];
self.myLabel.textColor              = [UIColor whiteColor];
self.myLabel.shadowColor            = [UIColor blackColor];
self.myLabel.shadowOffset           = CGSizeMake(0, 1);
self.myLabel.textAlignment          = UITextAlignmentCenter;
self.myLabel.text                   = @"blah";
self.myLabel.userInteractionEnabled = YES;
[self.myLabel addGestureRecognizer:[[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(labelTapped:)] autorelease]];
[self.view addSubview:self.myLabel];
[self.view bringSubviewToFront:self.myLabel];

}

- (void)hideLabel {
if (!self.myLabel) {
    return;
}

[self.myLabel removeFromSuperview];
self.myLabel = nil;

}

If I break on [__NSDictionaryM setObject:forKey:], it is getting called within UILabel's setTextColor, setShadow, setShadowOffset, and setTextAlignment methods. None of the values I'm sending should ever be nil, but this dictionary usage is internal to the label, so I'm wondering if perhaps I'm losing reference to the label after sending autorelease due to some other event causing the autorelease pool to drain while I'm still in my method (there are multiple external libraries involved in the app), and the internal dictionary usage occasionally runs into the error because of that.

Could that possibly explain NSMutableDictionary's NSInvalidArgumentException errors in this case?

Here's the full stack trace:

NSInvalidArgumentException *** setObjectForKey: key cannot be nil

1 libobjc.A.dylib 0x3678c963 objc_exception_throw + 31
2 CoreFoundation 0x378625ef -[__NSDictionaryM setObject:forKey:] + 143
3 MyApp 0x000effab -[TableViewController showLabel] (MainTableViewController.m:222)
4 CoreFoundation 0x37851349 _CFXNotificationPost + 1421
5 Foundation 0x37b2d38f -[NSNotificationCenter postNotificationName:object:userInfo:] + 71
6 MyApp 0x000d9141 -[Event setDictionary:] (Event.m:123)
¿Fue útil?

Solución

I can safely say that it has nothing to do with the autorelease. Your property has a retain, and you are correctly using the property when storing the variable, so your retain counter goes +1 (alloc) +1 (property setter retain) and eventually -1 (autorelease)

Your problem is probably elsewhere, but I can't figure it out without more code, sorry!

Edit: If you want to play super safe (and I would actually recommend this), you can do like this:

self.myLabel = [[UILabel alloc] initWithFrame:self.tableView.frame];
// configure
[self.myLabel release];

same goes for your gesture recognizer

Try it and see if you still get the crash

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top