iOS7 compatible version:
I made a category interface that stores all instance in init method.
I know it's a very inefficient way.
#import <objc/runtime.h>
#import <objc/message.h>
@interface UIAlertView(EnumView)
+ (void)startInstanceMonitor;
+ (void)stopInstanceMonitor;
+ (void)dismissAll;
@end
@implementation UIAlertView(EnumView)
static BOOL _isInstanceMonitorStarted = NO;
+ (NSMutableArray *)instances
{
static NSMutableArray *array = nil;
if (array == nil)
array = [NSMutableArray array];
return array;
}
- (void)_newInit
{
[[UIAlertView instances] addObject:[NSValue valueWithNonretainedObject:self]];
[self _oldInit];
}
- (void)_oldInit
{
// dummy method for storing original init IMP.
}
- (void)_newDealloc
{
[[UIAlertView instances] removeObject:[NSValue valueWithNonretainedObject:self]];
[self _oldDealloc];
}
- (void)_oldDealloc
{
// dummy method for storing original dealloc IMP.
}
static void replaceMethod(Class c, SEL old, SEL new)
{
Method newMethod = class_getInstanceMethod(c, new);
class_replaceMethod(c, old, method_getImplementation(newMethod), method_getTypeEncoding(newMethod));
}
+ (void)startInstanceMonitor
{
if (!_isInstanceMonitorStarted) {
_isInstanceMonitorStarted = YES;
replaceMethod(UIAlertView.class, @selector(_oldInit), @selector(init));
replaceMethod(UIAlertView.class, @selector(init), @selector(_newInit));
replaceMethod(UIAlertView.class, @selector(_oldDealloc), NSSelectorFromString(@"dealloc"));
replaceMethod(UIAlertView.class, NSSelectorFromString(@"dealloc"), @selector(_newDealloc));
}
}
+ (void)stopInstanceMonitor
{
if (_isInstanceMonitorStarted) {
_isInstanceMonitorStarted = NO;
replaceMethod(UIAlertView.class, @selector(init), @selector(_oldInit));
replaceMethod(UIAlertView.class, NSSelectorFromString(@"dealloc"), @selector(_oldDealloc));
}
}
+ (void)dismissAll
{
for (NSValue *value in [UIAlertView instances]) {
UIAlertView *view = [value nonretainedObjectValue];
if ([view isVisible]) {
[view dismissWithClickedButtonIndex:view.cancelButtonIndex animated:NO];
}
}
}
@end
Start instance monitoring before using UIAlertView.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//...
//...
[UIAlertView startInstanceMonitor];
return YES;
}
Call dismissAll before showing another.
[UIAlertView dismissAll];
It's better using a singleton pattern if you can control all UIAlertViews.
But in my case, I need this code for closing javascript alert dialog in a UIWebView.