我的视图控制器中存在一个强属性的UIPopoverController。当用户在弹出窗口可见时旋转iPad时,我会关闭弹出框并将我的属性设置为nil。
if (self.popover != nil) {
[self.popover dismissPopoverAnimated:NO];
self.popover.delegate = nil;
self.popover = nil;
}
当代码到达self.popover = nil时,ARC会尝试取消分配UIPopoverController,但它崩溃了,因为它应该仍然可见。
如果不让它崩溃,我该如何解雇并取消弹出?
答案 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;
});