I'm creating a wrapper for UIAlertView
(I know about UIAlertController
and about several already existing wrappers, it's also for educational purposes).
Suppose it looks like this (very shortened version):
@interface MYAlertView : NSObject
-(void)show;
@end
@interface MYAlertView()<UIAlertViewDelegate>
@end
@implementation MYAlertView
-(void)show {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Some title"
message:@"Some message"
delegate:self
cancelButtonTitle:@"Cancel"
otherButtonTitles:nil];
[alertView show]
}
#pragma mark UIAlertViewDelegate implementation
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
//Do something.
}
@end
And, for instance, I use it like this:
// USAGE (inside some ViewController)
-(void)showMyAlert {
dispatch_async(dispatch_get_main_queue(), ^{
MYAlertView *myAlertView = [[MYAlertView alloc] init];
[myAlertView show];
});
}
The problem I have is the following:
[myAlertView show]
causes thealertView
to appear.myAlertView
is set as a delegate of thealertView
.- There is the only strong reference to
myAlertView
: inside the block in theshowMyAlert
method. When it's finished,myAlertView
is deallocated. - When the user clicks a button on the
alertView
, thealertView
calls it's delegate method, but the delegate (myAlertView
) is deallocated already, so it causes BAD_ACCESS (the delegate inUIAlertView
is declared asassign
, notweak
).
I want to make MYAlertView
as easy to use as it is with UIAlertView
, so I don't want to make the user store a strong reference to it somewhere (it is inconvenient).
So, I have to keep the myAlertView
alive as long as the alertView
is shown somehow. The problem is I can't think of any way other than creating a strong reference inside MyAlertView
, assigning it to self
, when I show the alertView
, and assigning it to nil
, when I dismiss it.
Like so (only the changed bits):
@interface MYAlertView()<UIAlertViewDelegate>
//ADDED:
@property (nonatomic, strong) id strongSelfReference;
@end
@implementation MYAlertView
-(void)show {
UIAlertView *alertView = [[UIAlertView alloc] init /*shortened*/];
[alertView show]
//ADDED:
self.strongSelfReference = self;
}
#pragma mark UIAlertViewDelegate implementation
//ADDED:
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
self.strongSelfReference = nil;
}
@end
It should work: the moment the alertView
is dismissed, the strongSelfReference
will be set to nil
, there will be no strong references left to the myAlertView
, and it will get deallocated (in theory).
But keeping a strong reference to self
like this looks evil to me. Is there a better way?
UPDATE: The MYAlertView
in reality is an abstraction layer around the now deprecated UIAlertView
and a new UIAlertController
(iOS 8+), so subclassing UIAlertView
is not an option.