closurespopup窗口,当弹窗仍然可见时,达到
我有一个UIPopoverController存储在我的视图控制器的一个强大的属性。 当用户在popup窗口显示的同时旋转iPad时,我忽略popup窗口并将我的属性设置为零。
if (self.popover != nil) { [self.popover dismissPopoverAnimated:NO]; self.popover.delegate = nil; self.popover = nil; }
当代码到达self.popover = nil,ARC试图解除分配UIPopoverController,但它崩溃,因为它应该仍然可见。
如果没有崩溃,我该如何解雇和淘汰popover?
首先,检查是否显示popup窗口是明智的,这将方便地检查是否分配:
if ([self.popover isPopoverVisible]) { [self.popover dismissPopoverAnimated:NO]; }
现在,问题是,你没有得到委托callback- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController
如果你像这样以编程方式closures- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController
,但是你需要一个强大的引用,直到它不再可见。
这样做的方法是延迟将属性设置为零,直到您返回到主运行循环,因为当您回到主运行循环时,所有animation将完成,因此popup窗口将不再可见。
你会想将设置popover的代码移动到另一个方法:
- (void)releasePopover { self.popover.delegate = nil; self.popover = nil; }
然后,在你的循环callback中,添加这个方法在主运行循环中触发,我喜欢通过向主运行循环添加一个调用操作来完成这个操作:
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
callback中调用-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]; }
说了这么多,除非有很好的理由,否则你可能只想保持stream行的重用性,只有当你得到低内存的警告和/或你的视图被卸载的时候,才会将其设置为零,正如Chris Loonam的回答
尝试在viewDidUnload中将它清零,如果你真的觉得有必要的话。 由于ARC自动发布对象,我不确定是否真的需要这样做。
站在Simon的答案的肩膀上,这是我的崩溃修复:
// set to nil on main queue to prevent "dealloc'd while still visible" exception dispatch_async(dispatch_get_main_queue(), ^{ self.popover = nil; });