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

Ken*_*and 6 ipad uipopovercontroller ios automatic-ref-counting

我有一个UIPopoverController存储在我的View Controller中的一个强属性中.当用户在弹出窗口可见时旋转iPad时,我会关闭弹出框并将我的属性设置为nil.

if (self.popover != nil) {
    [self.popover dismissPopoverAnimated:NO];
    self.popover.delegate = nil;
    self.popover = nil;
}
Run Code Online (Sandbox Code Playgroud)

当代码变为self.popover = nil时,ARC会尝试解除对UIPopoverController的拒绝,但它会崩溃,因为它应该仍然可见.

如果不崩溃,我该如何解雇和淘汰弹出窗口?

Sim*_*een 16

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

if ([self.popover isPopoverVisible]) {
    [self.popover dismissPopoverAnimated:NO];
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

- (void)releasePopover {
    self.popover.delegate = nil;
    self.popover = nil;
}
Run Code Online (Sandbox Code Playgroud)

然后,在你的旋转回调中,添加此方法以在主运行循环上触发,我喜欢通过向主运行循环添加调用操作来执行此操作:

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

最后,为了清洁起见,您可能希望-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];
}
Run Code Online (Sandbox Code Playgroud)

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