令人沮丧的UIWebView代理崩溃问题 [英] Frustrating UIWebView Delegate Crash issue

查看:94
本文介绍了令人沮丧的UIWebView代理崩溃问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了运行完美的ARC应用程序。它有一个UINavigationController,我用来推动观点,一切顺利。



我将应用程序转换为iPad,我决定显示其中一个意见作为一个popover。 (我不喜欢UIPopoverController,所以我创建了我自己的基本弹出窗口)。它被添加到视图如下..

  MyViewController * hotelinf = [[MyViewController alloc] 
initWithNibName:@ MyViewController_iPadbundle:nil];

[self.view addSubview:hotelinf.view];

视图被添加为子视图。我添加的视图包含一个UIWebView,它具有通常的委托方法,但是当该视图尝试访问其中一个委托时,它只会崩溃。

  ***  -  [MyViewController respondToSelector:]:发送到解除分配的实例的消息0x7917b90 

具体来说,它在这行上崩溃。

  [self.webView loadHTMLString:stringResponse baseURL:nil]; 

我已经将视图(和UINavigationControllers)多次显示为子视图,没有任何问题,尽管没有他们包括一个UIWebView委托。我猜想我必须设置我的UIViewController的承诺,但我不知道如何。值得注意的是,如果我在现有的UINavigationController中推送视图,它调用并加载HTML的罚款,这肯定意味着它与视图本身的代码无关。



任何帮助将不胜感激!这是代码(除了上面显示控制器)..



.h

  @interface MyViewController:UIViewController< UIWebViewDelegate,UIActionSheetDelegate> {

//不相关的IBOutlets

}


@property(nonatomic,strong)UIWebView * webView;

@end

.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 {
//下载一个有效的HTML字符串
[self performSelectorOnMainThread:@ selector(loadHTML)withObject:nil waitUntilDone:NO];
}
}

- (void)viewDidDisappear:(BOOL)动画
{
[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:@Errormessage:@无法连接到XXXXX.com,请验证您连接到工作的3G / WIFI网络。委托:self cancelButtonTitle:@OKotherButtonTitles:nil];
[alert show];

} else {
//它只在加载为子视图时崩溃 - 第一次访问委托
[self.webView loadHTMLString:stringResponse baseURL:nil];
}
}

- (void)connection:(NSURLConnection *)连接didReceiveResponse :( NSURLResponse *)响应{
}


- (void)连接:(NSURLConnection *)连接didReceiveData:(NSData *)data {
}

- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}

- (void)webViewDidFinishLoad :( UIWebView *)webView {

[self stopIndicator];


- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)错误
{

if(error.code = = NSURLErrorCancelled)return; //这是错误-999
[self stopIndicator];

//报告webview中的错误
NSString * errorString = [NSString stringWithFormat:
@< html>< center>< font size = + 10 color ='black'face ='Helvetica'>发生错误:< br>%@< / font>< / center>< / html>,
error.localizedDescription];
[self.webView loadHTMLString:errorString baseURL:nil];

UIAlertView * alert = [[UIAlertView alloc]
initWithTitle:@无法加载URL。
消息:@您连接失败,请确认您已连接到WIFI或3G网络。
delegate:self cancelButtonTitle:@OkotherButtonTitles:nil];
[alert show];



}

@end


解决方案

该问题与 UIWebView 无关,而是与您的控制器类。确实,

  MyViewController * hotelinf = [[MyViewController alloc] 
initWithNibName:@MyViewController_iPadbundle:nil];

[self.view addSubview:hotelinf.view];

您正在分配控制器并将其分配给局部变量;然后将控制器视图作为子视图添加到当前视图中。这样做,该视图被保留,但控制器对象本身会发生什么?你释放了吗?或者它泄漏(因为它被分配到一个局部变量)?



这可能解释了为什么稍后 respondToSelector 方法被调用,控制器已被释放...



一种解决方法是在主控制器类中创建一个新的属性或一个ivar,并存储 MyViewController 在那里。不要忘记在dealloc中释放它。



我还会建议另一件事。在($)

   - (void)viewDidDisappear:(BOOL)动画
{
[super viewDidDisappear:animated ];
self.webView = nil;
}

在发布视图之前,将webView委托设置为nil:

$ (BOOL)动画
{
[super viewDidDisappear:animated]; b
$ b

   - (void)viewDidDisappear 
self.webView.delegate = nil;
self.webView = nil;
}

我也可以查看您在$ $中发布webView的原因c $ c> viewDidDisappear 。另一方面,您可以在 viewDidLoad 中分配。这种不对称是危险的,因为每当主视图消失(由于任何原因),webView将被删除,当视图重新出现时,它不再存在。


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.

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..

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.

*** -[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.

Any help would be greatly appreciated! Here is the code (in addition to above that shows the controller)..

.h

@interface MyViewController : UIViewController <UIWebViewDelegate, UIActionSheetDelegate> {

//Unrelated IBOutlets

}


@property (nonatomic, strong) UIWebView *webView;

@end

.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

解决方案

The issue has nothing to do with the UIWebView, rather with your controller class. Indeed,

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...

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.

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:

- (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.

这篇关于令人沮丧的UIWebView代理崩溃问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆