当Popover仍然可见时,解除了Popover,[UIPopoverController dealloc]

时间:2013-01-27 21:26:12

标签: ios ipad automatic-ref-counting uipopovercontroller

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

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

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

如果不让它崩溃,我该如何解雇并取消弹出?

3 个答案:

答案 0 :(得分:16)

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

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

现在问题是,如果您以编程方式解除弹出窗口,则不会获得委托回调- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController,但是您需要对弹出窗口的强引用,直到它不再可见。

执行此操作的方法是将属性延迟设置为nil直到返回主运行循环,因为当您返回主运行循环时,所有动画都将完成,因此弹出窗口将不再可见。

您需要将设置popover的代码移动到另一个方法:

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

说了这么多,除非有充分的理由,否则你可能只想让popover保持重用,只有当你得到低内存警告和/或你的视图被卸载时才将其设置为nil,如Chris Loonam的回答提到了

答案 1 :(得分:1)

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

答案 2 :(得分:1)

站在西蒙的回答的肩膀上,这是我对坠机事件的解决方法:

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