我正在使用UIWebView,它会在单击按钮时弹出警报(来自javascript)。还有另一个按钮(在本机端),它关闭控制器,因此deallocs也是UIWebView。
问题是,如果我触摸UIWebView中的按钮,并在填充警报之前触摸关闭按钮,我的控制器和UIWebView将被取消分配,但警报仍保留在屏幕上。然后,如果我单击警报上的任何按钮,应用程序崩溃并发出以下错误:
[UIWebView modalView:didDismissWithButtonIndex:]: message sent to deallocated instance
这个方法是从私有方法调用的
[UIModalView(Private) _popoutAnimationDidStop:finished:]
我正在使用ARC,而我的dealloc是这样的:
- (void)dealloc {
[_myWebView stopLoading];
_myWebView.delegate = nil;
_myWebView = nil;
}
但是这并没有解决我的问题,因为我认为UIModalView有一个我的webview作为委托的引用,我无法将其设置为nil,因为它是私有的。
我该如何解决?
此致
答案 0 :(得分:1)
在解除分配UIWebView之前,找到一种将UIAlertView上的委托设置为nil的方法。
答案 1 :(得分:1)
这是处理警报视图时的Apple错误。 Open a bug report.
与此同时,这里有一些解决方法:
在UIAlertView上创建一个类别:
@interface UIAlertView (QuickDismiss) @end
@implementation UIAlertView (QuickDismiss)
- (void)__quickDismiss
{
[self dismissWithClickedButtonIndex:self.cancelButtonIndex animated:NO];
}
@end
现在,在视图控制器的dealloc方法中,调用:
[[UIApplication sharedApplication] sendAction:@selector(__quickDismiss) to:nil from:nil forEvent:nil];
这将关闭当前打开的所有警报视图,包括您的Web视图显示的视图。
如果这不起作用,您可以始终迭代所有UIApplication.sharedApplication.windows
个对象的所有子视图,检查[view.class.description hasPrefix:@"UIAlertView"]
是否为真,并将其解除。这是一种比前一种方法更不优雅的方法,应该是最后的选择。
答案 2 :(得分:0)
最后,我找到了一个很有效的解决方案。我使用方法swizzle来挂钩UIAlertView Delegate函数 - (void)didPresentAlertView:(UIAlertView *)alertView
- (void)didPresentAlertView:(UIAlertView *)alertView
{
if ([self.delegate respondsToSelector:@selector(didPresentAlertView:)]) {
[self.delegate didPresentAlertView:alertView];
}
if ([self.delegate isKindOfClass: [UIWebView class]]) {
uiWebView = self.delegate;
}
}
我只是在此函数中保留UIWebView实例,以便在UIAlertView实例发布之前不会释放作为UIAlertView代理的UIWebView实例。