EDIT:从IOS 7.1/Xcode 5.1.1开始,这些问题似乎已得到解决.(可能更早,因为我无法测试所有版本.肯定是在iOS 7.0之后,因为我测试了那个.)当您从UIBarButtonItem
创建弹出窗口段时,段会确保再次点击弹出窗口会隐藏弹出窗口,而不是显示副本.它也适用于Xcode6为iOS8创建的基于UIPresentationController
的新Popover segues.
由于我的解决方案可能对那些仍然支持早期iOS版本的人具有历史意义,所以我将其留在下面.
如果您存储了对Segue的Popover控制器的引用,在重复调用prepareForSegue:sender:
时将其设置为新值之前将其取消,那么您所避免的就是重复按下按钮时会出现多次堆叠弹出的问题--您仍然不能像HIG建议的那样使用该按钮来取消Popover(正如苹果的应用程序等所看到的那样).
不过,对于简单的解决方案,您可以利用ARC将弱引用置零的优势:
1:从按钮开始分段
从iOS5开始,你不能用UIBarButtonItem
的片段来做这件事,但是你可以在iOS6和更高版本上做这件事.(在iOS5上,您必须与视图控制器本身分开,然后在判断弹出窗口后让按钮的操作调用performSegueWithIdentifier:
.)
2: Use a reference to the popover in -shouldPerformSegue...
@interface ViewController
@property (weak) UIPopoverController *myPopover;
@end
@implementation ViewController
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// if you have multiple segues, check segue.identifier
self.myPopover = [(UIStoryboardPopoverSegue *)segue popoverController];
}
- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender {
if (self.myPopover) {
[self.myPopover dismissPopoverAnimated:YES];
return NO;
} else {
return YES;
}
}
@end
3:没有第三步!
这里使用零弱引用的好处是,一旦取消了popover控制器--无论是以编程方式进入shouldPerformSegueWithIdentifier:
,还是通过用户在popover之外的其他地方自动点击--ivar又回到了nil
,所以我们回到了初始状态.
如果不将弱引用归零,我们还必须:
- 在
shouldPerformSegueWithIdentifier:
中取消时设置myPopover = nil
,并且
- 将自己设置为popover控制器的代理,以便捕捉
popoverControllerDidDismissPopover:
,并在那里设置myPopover = nil
(因此,当popover被自动解除时,我们捕捉).