Сбой приложения в [UIWebView webView: didReceiveTitle: forFrame:] - PullRequest
3 голосов
/ 25 мая 2011

Я реализую простой браузер в приложении.В моем домашнем представлении (UITableViewController) у меня есть что-то вроде:

    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

        WebViewController *webViewController = [[WebViewController alloc] init];
        switch (indexPath.row) {
            case 0:
                webViewController.stringURL = @"http://www.google.com";
                break;
            case 1:
                webViewController.stringURL = @"http://www.bing.com";
                break;
            default:
                webViewController.stringURL = @"http://stackoverflow.com"; 
                break;
        }

        [self.navigationController pushViewController:webViewController animated:YES];
        [webViewController release];
    }

Приложение зависло после того, как я несколько раз перемещался назад и вперед между моим домашним видом и webViewController несколькимираз.

В классе WebViewController у меня нет ничего, кроме [UIWebView *webView] и [UIActivityIndicatorView *activityIndicator].Оба с атрибутами nonatomic, retain.Вот реализация.

        #import "WebViewController.h"
        @implementation WebViewController
        @synthesize webView, activityIndicator, stringURL;

        - (void)dealloc
        {
            [self.webView release];
            self.webView.delegate = nil;
            [self.activityIndicator release]; 
            [super dealloc];
        }

        -(void)loadView {
            UIView *contentView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
            self.view = contentView;    

            CGRect webFrame = [[UIScreen mainScreen] applicationFrame];
            webFrame.origin.y = 0.0f;
            self.webView = [[UIWebView alloc] initWithFrame:webFrame];
            self.webView.backgroundColor = [UIColor blueColor];
            self.webView.scalesPageToFit = YES;
            self.webView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
            self.webView.delegate = self;
            [self.view addSubview: self.webView];
            [self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:self.stringURL]]];

            self.activityIndicator = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
            self.activityIndicator.frame = CGRectMake(0.0, 0.0, 30.0, 30.0);
            self.activityIndicator.center = self.view.center;
            [self.view addSubview: self.activityIndicator];
        }

        - (void)viewDidLoad
        {   
            [super viewDidLoad];
            [self loadView];
        }

        - (void)webViewDidStartLoad:(UIWebView *)webView
        {
            // starting the load, show the activity indicator in the status bar
            [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
            [activityIndicator startAnimating];
        }

        - (void)webViewDidFinishLoad:(UIWebView *)webView
        {
            // finished loading, hide the activity indicator in the status bar
            [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
            [activityIndicator stopAnimating];
        }

        @end

Я только что запустил свое приложение в Инструментах, используя шаблон Zombies , который показывает, что -[UIWebView webView:didReceiveTitle:forFrame:] - это вызов Zombie.Но я все еще не могу понять, в чем на самом деле проблема.

(Пожалуйста, скачайте след при необходимости)

Любая помощь очень ценится!

[Update]:

  1. Как отметили @ 7KV7 и @David, в моей функции dealloc есть очевидная ошибка.Я должен позвонить self.webView.delegate=nil; сначала, прежде чем отпустить self.webView.Извини за это.К сожалению, после того, как я это исправлю, приложение все равно вылетает так же.
  2. Если я удаляю [webViewController release]; из первого блока кода, сбой фактически исчезает.Но очевидно, что будет утечка памяти.

Ответы [ 5 ]

3 голосов
/ 25 мая 2011

Прежде всего удалите этот вызов на loadView в viewDidLoad. Фреймворк будет вызывать метод, когда он не найдет представление, представленное в файле XIB. Во-вторых, ваш loadView заполнен утечками памяти. Вы выделяете, инициализируете и сохраняете объект каждый раз, когда вызывается метод. Таким образом, вы получаете право собственности дважды и освобождаете его только один раз в сделке.

Объекты не освобождаются должным образом. Вы должны сделать что-то вроде alloc-init-autorelease, чтобы решить эту проблему. Следующим шагом является то, что каждый раз, когда загружается контроллер, из-за вашего вызова loadView вы в конечном итоге создаете два объекта веб-представления и два запроса. Вы теряете ссылку на один из них при переназначении. В этом и заключается проблема, упомянутая в названии. Вы не можете сбросить делегат объекта веб-представления, в котором ваш контроллер является делегатом. Представьте, что запрос завершается вскоре после вашего отъезда. Здесь сообщение перейдет к объекту зомби. Это довольно хороший пример того, почему вам нужно nil выдвинуть своих делегатов.

2 голосов
/ 25 мая 2011
- (void)dealloc
{
self.webView.delegate = nil;
[self.webView release];
[self.activityIndicator release]; 
[super dealloc];
}

Попробуйте это dealloc.Вы отпускаете webview, а затем устанавливаете delegate как nil.Сначала вы должны установить delegate как nil, а затем release.Надеюсь, что это решит проблему.

1 голос
/ 25 мая 2011

Я думаю, что происходит то, что вы возвращаетесь, пока страница еще загружается, поэтому контроллер освобождается, а затем веб-просмотр завершает загрузку.Попробуйте вызвать [webView stopLoading] в вашем методе viewDidUnload, чтобы убедиться, что этого не происходит.

0 голосов
/ 25 мая 2011

Вместо нажатия кнопки webViewController добавьте его представление в self.view. Не вызывайте [self loadView]; в viewDidLoad.

0 голосов
/ 25 мая 2011

Не знаю, является ли это причиной вашей проблемы, но это определенно неправильно:

[self.webView release];
self.webView.delegate = nil;

Вы не можете (безопасно) ссылаться на self.webView после того, как отпустите его!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...