UIWebView のインスタンスに delegate を指定している場合は以下のように release する前に delegate に nil をセットする必要があります。

- (void) viewDidLoad {
    webView = [[UIWebView alloc] init];
    webView.delegate = self;
    ....
}

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


アップルのマニュアルにも以下のように書かれています。

Important: Before releasing an instance of UIWebView for which you have set a delegate, you must first set its delegate property to nil. This can be done, for example, in your dealloc method.

理由は UIWebView のロード処理が別スレッドで行われているために、release 後にデリゲートメソッドを呼ぶ可能性があるためだそうです。

以下のコードで実験してみました。UIWebView のインスタンスを生成後、loadRequest で読み込みます。その直後に UIWebView のインスタンスをリリースしてみました。そして、webView.delegate = nil を入れた時と入れないときの挙動を試してみるとわかりやすいです。

- (void)viewDidLoad {
    [super viewDidLoad];

    UIWebView* webView = [[UIWebView alloc] init];
    [self.view addSubview:webView];
    webView.delegate = self;
    NSURL* url = [NSURL URLWithString:@"http://example.com"];
    [webView loadRequest:[NSURLRequest requestWithURL:url]];

    webView.delegate = nil;  // この行を入れた時と入れないときの挙動の違い
    [webView release];
}

- (void)webViewDidFinishLoad:(UIWebView *)_webView {
    NSLog(@"finish load");
}

delegate に nil を設定していないとデリゲートメソッドが呼ばれます。もし、このUIViewController のインスタンスが破棄されていればアプリが落ちてしまいます。

意図しないタイミングでデリゲートメソッドが呼ばれないために UIWebView のインスタンスをリリースする前にはデリゲートに nil をセットしなければいけないということです。

関連する投稿