Срыв проблемы с делегированием UIWebView - PullRequest
4 голосов
/ 25 января 2012

Я создал приложение ARC, которое отлично работает.У него есть UINavigationController, который я использую для просмотра представлений, и все работает нормально.

Я конвертирую приложение в iPad и решил показать одно из представлений как всплывающее окно.(Мне не нравится UIPopoverController, поэтому я создал собственное всплывающее окно).Он добавляется в представление следующим образом.

MyViewController *hotelinf = [[MyViewController alloc]
initWithNibName:@"MyViewController_iPad" bundle:nil];

[self.view addSubview:hotelinf.view];

Представление добавляется как штраф в качестве подпредставления.Представление, которое я добавляю, содержит UIWebView, в котором есть обычные методы делегата, но когда представление пытается получить доступ к одному из делегатов, оно просто падает.

*** -[MyViewController respondsToSelector:]: message sent to deallocated instance 0x7917b90

В частности, в этой строке происходит сбой..

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

Я отображал представления (и UINavigationControllers) как подвиды много раз без каких-либо проблем, хотя ни один из них не включал делегат UIWebView.Я предполагаю, что должен установить делегат моего экземпляра UIViewController, но я не уверен, как.Также стоит отметить, что если я помещаю представление в существующий UINavigationController, он вызывает и прекрасно загружает HTML, что, безусловно, означает, что он не имеет ничего общего с кодом самого представления.

Любая помощь будет принята с благодарностью.!Вот код (в дополнение к выше, который показывает контроллер) ..

.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

Ответы [ 2 ]

15 голосов
/ 25 января 2012

Проблема не имеет ничего общего с UIWebView, а скорее с вашим классом контроллера.Действительно,

MyViewController *hotelinf = [[MyViewController alloc]
   initWithNibName:@"MyViewController_iPad" bundle:nil];

[self.view addSubview:hotelinf.view];

Вы выделяете контроллер и назначаете его локальной переменной;затем вы добавляете представление контроллера в качестве текущего представления.При этом это представление сохраняется, но что происходит с самим объектом контроллера?Вы выпускаете это?Или это утечка (так как он назначен локальной переменной)?

Это, возможно, объясняет, почему, когда позже вызывается метод respondsToSelector, контроллер уже освобожден ...

AЧтобы исправить это, создайте новое свойство или ivar в вашем главном классе контроллера и сохраните там MyViewController.Не забудьте выпустить его в dealloc.

Я бы также предложил другую вещь.В:

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

установите делегат webView равным nil перед освобождением представления:

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

И я также мог бы рассмотреть причину, по которой вы выпускаете webView в viewDidDisappear.С другой стороны, вы выделяете его в viewDidLoad.Эта асимметрия опасна, так как всякий раз, когда основной вид исчезает (по любой причине), веб-вид будет удален, а когда вид снова появится, его там больше не будет.

0 голосов
/ 25 января 2012

Лучше добавить все методы делегата.Вы не добавили первые два.Скорее всего, ваш код падает при отправке сообщения webViewDidStartLoad

– webView:shouldStartLoadWithRequest:navigationType:
– webViewDidStartLoad:
– webViewDidFinishLoad:
– webView:didFailLoadWithError:
...