如何解雇故事板Popover

Sam*_*cer 73 objective-c uibarbuttonitem uipopovercontroller ios uistoryboard

UIBarButtonItem使用Xcode Storyboards 创建了一个popover (所以没有代码),如下所示:

带有Popover的Xcode 5.0 Connections Inspector

提出popover工作得很好.但是,当我点击它使它出现时,我无法让popover 消失UIBarButtonItem.

按下按钮(第一次)时会出现弹出窗口.当再次按下该按钮(第二次)时,它上面会出现相同的弹出窗口,所以现在我有两个弹出窗口(如果我继续按下按钮,则会有更多弹出窗口).根据iOS人机界面指南,我需要在第一次点击时显示弹出窗口并在第二次点击时消失:

确保一次只能在屏幕上看到一个弹出窗口.您不应同时显示多个弹出窗口(或设计为外观和行为的自定义视图).特别是,您应该避免同时显示级联或层次结构的弹出窗口,其中一个弹出窗口从另一个弹出窗口出现.

当用户UIBarButtonItem再次点击时,如何解除popover ?

ric*_*ter 114

编辑:从iOS 7.1/Xcode 5.1.1开始,这些问题似乎已得到修复.(可能更早,因为我无法测试所有版本.绝对是在iOS 7.0之后,因为我测试了那个.)当你从a创建一个popover segue时UIBarButtonItem,segue确保再次点击popover隐藏了popover而不是而不是显示重复.它适用于UIPresentationControllerXcode 6为iOS 8创建的新的popover segues.

由于我的解决方案可能对仍然支持早期iOS版本的人有历史意义,我将其留在下面.


如果您存储对segue的弹出控制器的引用,在重复调用时将其设置为新值之前将其解除prepareForSegue:sender:,您可以避免重复按下按钮时获得多个堆栈弹出窗口的问题 - 您仍然无法使用按照HIG的建议解除弹出窗口的按钮(如Apple的应用程序中所示)

但是,您可以利用ARC归零弱引用来获得简单的解决方案:

1:从按钮开始

从iOS 5开始,你无法使用来自a的segue UIBarButtonItem,但你可以在iOS 6及更高版本中使用.(在iOS 5上,您必须从视图控制器本身中删除,然后performSegueWithIdentifier:在检查弹出窗口后进行按钮的动作调用.)

2:使用对弹出窗口的引用 -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
Run Code Online (Sandbox Code Playgroud)

3:没有第三步!

在这里使用归零弱引用的好处是,一旦弹出控制器被解除 - 无论是以编程方式进入shouldPerformSegueWithIdentifier:,还是由用户在弹出窗口外的其他位置自动攻击 - ivar nil再次进入,所以我们回到我们的初始状态.

在没有归零弱引用的情况下,我们还必须:

  • myPopover = nil在解雇时设置shouldPerformSegueWithIdentifier:,和
  • 将我们自己设置为popover控制器的委托,以便捕获popoverControllerDidDismissPopover:并设置myPopover = nil那里(所以我们在弹出窗口被自动解除时捕获).

  • 向@wcochran道具寻求帮助解决这个问题. (3认同)
  • 是的,`__ weak` ivar和`weak`属性在这里是等价的.是否使用财产或ivar作为课堂内部的东西仍然是一个备受争议的主题.当我怀疑自定义存取器并且永远不需要KVO时,我倾向于坚持使用ivar,但"一切都属性"策略也有其优点. (2认同)

小智 13

我在这里找到了解决方案/sf/answers/555695941/ 在第一个prepareForSegue:sender:存储在ivar/property中指向UIPopoverController的指针和用户指向在后续调用中解除popover的指针.

...
@property (nonatomic, weak) UIPopoverController* storePopover;
...

- (void)prepareForSegue:(UIStoryboardSegue *)segue 
                 sender:(id)sender {
if ([segue.identifier isEqualToString:@"My segue"]) {
// setup segue here

[self.storePopover dismissPopoverAnimated:YES];
self.storePopover = ((UIStoryboardPopoverSegue*)segue).popoverController;
...
}
Run Code Online (Sandbox Code Playgroud)