【问题标题】:Dismissing Popover, [UIPopoverController dealloc] reached while popover is still visible关闭 Popover,在 popover 仍然可见时达到 [UIPopoverController dealloc]
【发布时间】:2013-01-27 21:26:11
【问题描述】:

我有一个 UIPopoverController 存储在我的视图控制器的强属性中。当用户在弹出窗口可见时旋转 iPad 时,我关闭弹出窗口并将我的属性设置为 nil。

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

当代码到达 self.popover = nil 时,ARC 尝试解除 UIPopoverController 的分配,但它崩溃了,因为它应该仍然可见。

我应该如何在不崩溃的情况下关闭并消除弹出框?

【问题讨论】:

  • 很好地解释了这个问题。我遇到了完全相同的情况。

标签: ios ipad automatic-ref-counting uipopovercontroller


【解决方案1】:

首先,建议检查弹出框是否正在显示,这也可以方便地检查它是否已分配:

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];
}

最后,为了清洁起见,您可能需要在 - (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController 回调中调用 -releasePopover

所以,把它们放在一起:

- (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,如 Chris提到Loonam的回答

【讨论】:

    【解决方案2】:

    如果您确实觉得有必要,请尝试在 viewDidUnload 中将其置零。由于 ARC 自动释放对象,我不确定这样做是否真的有必要。

    【讨论】:

    • 视图没有被卸载,我只是在改变方向。
    • 这是因为我希望它在被解散后消失而不是保留在内存中,并且我还检查了该变量以查看是否存储了一个等。
    【解决方案3】:

    站在西蒙回答的肩膀上,这是我对崩溃的修复:

    // set to nil on main queue to prevent "dealloc'd while still visible" exception
    dispatch_async(dispatch_get_main_queue(), ^{
            self.popover = nil;
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-09-24
      • 1970-01-01
      • 2014-10-03
      • 2014-07-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多