The object is deallocated in ARC mode and causes crash. My code below;
BlockAlertView* alert = [BlockAlertView alertWithTitle:title message:message];
[alert setCancelButtonWithTitle:NSLocalizedString(@"No", @"No Button") block:nil];
[alert addButtonWithTitle:NSLocalizedString(@"Yes", @"Yes Button") block:^{
//Do Something
}];
[alert show];
It appears the correct alert view(which is custom UIView) but when I click one of the button it crashes.
The crash log;
2015-04-07 22:28:17.065 Test[3213:781570] <BlockAlertView: 0x16bb4160>
2015-04-07 22:33:01.746 Test[3213:781570] *** -[BlockAlertView performSelector:withObject:withObject:]: message sent to deallocated instance 0x16bb4160
Here is the source code of BlockAlertView;
BlockAlertView on Github
For now I can't estimate any of the clues for this and makes me old.
Any input will be much appreciated!
Presumably, that code worked correctly before it was converted to ARC.
To fix it, you'll need to create a strong reference to self
in the -show
method, and release this reference in -dismissWithClickedButtonIndex:animated:
(where you see [self autorelease]
commented out).
You can do this with a simple instance variable:
id _selfReference;
Assign self
to _selfReference
in -show
:
- (void)show
{
_selfReference = self;
...
and then set _selfReference
to nil in -dismissWithClickedButtonIndex:animated:
in the two places where you see [self autorelease]
commented out.
Assign your alert
object to live somewhere beyond your current function. One simple possibility is to just make it an instance variable. If that's not practical, create an instance NSMutableArray *retainedItems;
which you allocate/init, and stuff this into.
Looks like a design flaw in that project. The class is poorly named BlockAlertView
as it's not actually a subclass of UIView
. If it were a view and it was added to the view hierarchy then the view hierarchy would ensure it stayed alive whilst being viewed. As it is the view is kept alive but the object that created the view BlockAlertView
is not held onto by anything and by the time the actions are called BlockAlertView
is long gone.
This will require you to keep a strong
ivar around to reference this "controller" object and it would be sensible to nil
out that ivar in the completion blocks.
BlockAlertView *alertController = [BlockAlertView alertWithTitle:title message:message]; {
[alertController setCancelButtonWithTitle:NSLocalizedString(@"No", @"No Button") block:nil];
__weak __typeof(self) weakSelf = self;
[alertController addButtonWithTitle:NSLocalizedString(@"Yes", @"Yes Button") block:^{
//Do Something
weakSelf.alertController = nil;
}];
[alertController show];
}
self.alertController = alertController;