6

View Controller の強力なプロパティに格納されている UIPopoverController があります。ポップオーバーが表示されているときにユーザーが iPad を回転させると、ポップオーバーを閉じてプロパティを nil に設定します。

if (self.popover != nil) {
    [self.popover dismissPopoverAnimated:NO];
    self.popover.delegate = nil;
    self.popover = nil;
}

コードが self.popover = nil になると、ARC は UIPopoverController の割り当てを解除しようとしますが、まだ表示されているはずなのでクラッシュします。

クラッシュせずにポップオーバーを閉じて無効にするにはどうすればよいですか?

4

3 に答える 3

16

まず、ポップオーバーが表示されているかどうかを確認することをお勧めします。これにより、ポップオーバーが割り当てられているかどうかも簡単に確認できます。

if ([self.popover isPopoverVisible]) {
    [self.popover dismissPopoverAnimated:NO];
}

さて、問題は、このようにプログラムでポップオーバーを閉じると、デリゲート コールバックを取得できないことですが- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController、ポップオーバーが表示されなくなるまで、ポップオーバーへの強い参照が必要です。

これを行う方法は、メインの実行ループに戻るまでプロパティを nil に設定するのを遅らせることです。メインの実行ループに戻ると、すべてのアニメーションが終了し、ポップオーバーが表示されなくなります。

ポップオーバーを nil に設定するコードを別のメソッドに移動する必要があります。

- (void)releasePopover {
    self.popover.delegate = nil;
    self.popover = nil;
}

次に、ローテーション コールバックで、このメソッドを追加してメインの実行ループで起動します。私は呼び出し操作をメインの実行ループに追加することでこれを行うのが好きです。

if ([self.popover isPopoverVisible]){
    [self.popover dismissPopoverAnimated:NO];
    NSInvocationOperation *invocationOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(releasePopover) object:nil];
    [[NSOperationQueue mainQueue] addOperation:invocationOperation];
}

最後に、きれいにするために、おそらくコールバック-releasePopover内から呼び出すことをお勧めし- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverControllerます。

したがって、すべてをまとめると、次のようになります。

- (void)releasePopover
{
    self.popover.delegate = nil;
    self.popover = nil;
}

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
    if ([self.popover isPopoverVisible]){
        [self.popover dismissPopoverAnimated:NO];
        NSInvocationOperation *invocationOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(releasePopover) object:nil];
        [[NSOperationQueue mainQueue] addOperation:invocationOperation];
    }
}

- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController
{
    [self releasePopover];
}

そうは言っても、正当な理由がない限り、ポップオーバーを再利用するために維持し、メモリ不足の警告が表示された場合やビューがアンロードされた場合にのみ nil に設定することをお勧めします。

于 2013-01-29T01:37:21.143 に答える
1

サイモンの答えの肩に立って、これがクラッシュの私の修正です:

// set to nil on main queue to prevent "dealloc'd while still visible" exception
dispatch_async(dispatch_get_main_queue(), ^{
        self.popover = nil;
});
于 2013-02-26T18:24:49.280 に答える
1

本当にそうする必要があると感じたら、viewDidUnload でそれを nil アウトしてみてください。ARC は自動的にオブジェクトを解放するので、これが本当に必要かどうかはわかりません。

于 2013-01-27T21:31:39.350 に答える