xcode 令人沮丧的 UIWebView 委托崩溃问题
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8995146/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Frustrating UIWebView Delegate Crash issue
提问by user1168056
I've created an ARC Application that run's perfect. It's got a UINavigationController that I use to push through the views and everything runs fine.
我创建了一个运行完美的 ARC 应用程序。它有一个 UINavigationController,我用它来推送视图,一切都运行良好。
I'm converting the Application to iPad and i've decided to show one of the views as a popover. (I don't like UIPopoverController so i've created my own basic popup). It's added to the view as follows..
我正在将应用程序转换为 iPad,我决定将其中一个视图显示为弹出窗口。(我不喜欢 UIPopoverController 所以我创建了我自己的基本弹出窗口)。它被添加到视图中,如下所示..
MyViewController *hotelinf = [[MyViewController alloc]
initWithNibName:@"MyViewController_iPad" bundle:nil];
[self.view addSubview:hotelinf.view];
The view is added as a subview fine. The view i'm adding contains a UIWebView that has the usual delegate methods in it, but when the view tries to access one of the delegates it simply crashes.
该视图被添加为子视图罚款。我正在添加的视图包含一个 UIWebView,其中包含通常的委托方法,但是当视图尝试访问其中一个委托时,它只会崩溃。
*** -[MyViewController respondsToSelector:]: message sent to deallocated instance 0x7917b90
Specifically, it crashes on this line..
具体来说,它在这条线上崩溃了..
[self.webView loadHTMLString:stringResponse baseURL:nil];
I've displayed views (and UINavigationControllers) as subViews many of times without any issues, although none of them included a UIWebView delegate. I'm guessing I have to set the delegate of my UIViewController istance but i'm not sure how. It's also worth noting that if I push the view in my existing UINavigationController it calls and loads the HTML fine, which surely means it has nothing to do with the code of the view itself.
我已经多次将视图(和 UINavigationControllers)显示为子视图而没有任何问题,尽管它们都没有包含 UIWebView 委托。我猜我必须设置我的 UIViewController 实例的委托,但我不确定如何设置。还值得注意的是,如果我在现有的 UINavigationController 中推送视图,它会调用并加载 HTML,这肯定意味着它与视图本身的代码无关。
Any help would be greatly appreciated! Here is the code (in addition to above that shows the controller)..
任何帮助将不胜感激!这是代码(除了上面显示控制器的代码)。
.h
。H
@interface MyViewController : UIViewController <UIWebViewDelegate, UIActionSheetDelegate> {
//Unrelated IBOutlets
}
@property (nonatomic, strong) UIWebView *webView;
@end
.m
.m
@implementation MyViewController
@synthesize webView;
- (void)viewDidLoad
{
[super viewDidLoad];
self.webView = [[UIWebView alloc]initWithFrame:CGRectMake(317,283,393,354)];
self.webView.delegate = self;
[self.view addSubview:self.webView];
[NSThread detachNewThreadSelector:@selector(getHTMLString) toTarget:self withObject:nil];
}
-(void)getHTMLString {
@autoreleasepool {
//Download a valid HTML String
[self performSelectorOnMainThread:@selector(loadHTML) withObject:nil waitUntilDone:NO];
}
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
self.webView = nil;
}
-(void)loadHTML {
self.webView.opaque = NO;
self.webView.backgroundColor = [UIColor clearColor];
if ([stringResponse isEqualToString:@""]) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error" message:@"Could not connect to XXXXX.com. Please verify you are connected to a working 3G/WIFI Network." delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alert show];
} else {
//it crashes here only when loaded as a subview - the first access to the delegate
[self.webView loadHTMLString:stringResponse baseURL:nil];
}
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}
- (void)webViewDidFinishLoad:(UIWebView *)webView {
[self stopIndicator];
}
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
{
if (error.code == NSURLErrorCancelled) return; // this is Error -999
[self stopIndicator];
// report the error inside the webview
NSString* errorString = [NSString stringWithFormat:
@"<html><center><font size=+10 color='black' face='Helvetica'>An error occurred:<br>%@</font></center></html>",
error.localizedDescription];
[self.webView loadHTMLString:errorString baseURL:nil];
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:@"Cannot load URL."
message:@"You have a connection failure. Please verify you are connected to a WIFI or 3G enabled Network."
delegate:self cancelButtonTitle:@"Ok" otherButtonTitles:nil];
[alert show];
}
@end
回答by sergio
The issue has nothing to do with the UIWebView
, rather with your controller class. Indeed,
该问题与 无关UIWebView
,而与您的控制器类有关。的确,
MyViewController *hotelinf = [[MyViewController alloc]
initWithNibName:@"MyViewController_iPad" bundle:nil];
[self.view addSubview:hotelinf.view];
You are allocating the controller and assigning it to a local variable; then you add the controller's view as subview to your current view. Doing that, that view is retained, but what happens to the controller object itself? Are you releasing it? Or it leaks (since it is assigned to a local variable)?
您正在分配控制器并将其分配给局部变量;然后将控制器的视图作为子视图添加到当前视图中。这样做,该视图被保留,但是控制器对象本身会发生什么?你释放它吗?或者它泄漏(因为它被分配给一个局部变量)?
This possibly explains why when later the respondsToSelector
method is called, the controller has already been deallocated...
这可能解释了为什么稍后respondsToSelector
调用该方法时,控制器已被释放...
A way to fix this is creating a new property or an ivar in your main controller class and store MyViewController
in there. Don't forget to release it in dealloc.
解决此问题的一种方法是在主控制器类中创建一个新属性或一个 ivar 并将其存储MyViewController
在那里。不要忘记在 dealloc 中释放它。
I would also suggest another thing. In:
我还建议另一件事。在:
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
self.webView = nil;
}
set the webView delegate to nil before releasing the view:
在释放视图之前将 webView 委托设置为 nil:
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
self.webView.delegate = nil;
self.webView = nil;
}
And I would also possibly review the reason why you release the webView in viewDidDisappear
. On the other hand you allocate it in viewDidLoad
. This asymmetry is dangerous, since whenever the main view disappears (for any reason) the webView will be removed and when the view reappears, it is not there anymore.
我也可能会检查您在viewDidDisappear
. 另一方面,您将它分配到viewDidLoad
. 这种不对称是危险的,因为每当主视图消失(出于任何原因)webView 将被删除,当视图重新出现时,它不再存在。
回答by Gopalakrishnan Mallappan
Better add all the delegate methods. You havent added the first two. Most probably, your code is crashing when message webViewDidStartLoad
is sent
最好添加所有委托方法。你还没有添加前两个。最可能的是,你的代码崩溃时,消息webViewDidStartLoad
被发送
– webView:shouldStartLoadWithRequest:navigationType:
– webViewDidStartLoad:
– webViewDidFinishLoad:
– webView:didFailLoadWithError: