UIBarButtonItem + popover segue 会创建多个弹出窗口

8

我目前有一个iPad应用程序,其中包含一个UIToolbar,它包含两个UIBarButtonItems,每个都连接到一个弹出视图。

当用户触摸UIBarButtonItems之一时,将创建弹出窗口而不是切换。这会创建多个重叠的弹出窗口。我已经能够使用以下代码关闭先前创建的弹出窗口:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // First close the preferences popover if it's open per Apple guidelines
    if ([self.popoverA.popoverController isPopoverVisible]) {
        [self.popoverA.popoverController dismissPopoverAnimated:YES];
    }

    if ([self.popoverB.popoverController isPopoverVisible]) {
        [self.popoverB.popoverController dismissPopoverAnimated:YES];
    }
    ... code to manage segues ...
}

我还有一些UIButtons,它们创建的弹出窗口segue表现正常。由于与UIBarButtonItems相关联的弹出窗口的这种行为,我的应用程序被拒绝了。有人有什么建议或任何代码示例可以正确地使用具有多个UIBarButtonItems的UIToolbar吗?当用户触摸窗口外部时,弹出窗口确实会消失。


只是想澄清我的问题。期望的行为是每次点击按钮(UIBarButtonItem)时,弹出窗口应该切换打开或关闭,而不是总是打开。然而,转场似乎总是创建另一个弹出窗口,而不是关闭现有可见的窗口。当链接到UIButton时,弹出窗口会适当地切换。 - Timothy Newton
3个回答

16

这是做你需要做的正确方式:

- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender {
    if ([identifier isEqualToString:@"SurveyListPopover"]) {
        if (self.surveyListPopover == nil) {
            return YES;
        }
        return NO;
    }
    return YES;
}

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if ([segue.identifier isEqualToString:@"SurveyListPopover"]) {
        // Assign popover instance so we can dismiss it later
        self.surveyListPopover = [(UIStoryboardPopoverSegue *)segue popoverController];
    }
}

如果已经显示了弹出框的实例,这将确保转场将被取消。您只需要确保您的弹出框对象在故事板中具有标识符。


如果你的目标是6.0及以上版本,这是迄今为止最好的方法。 - Mark Adams
只有我一个人还是在iOS 5中shouldPerformSegueWithIdentifier根本没有被调用? - Radu Simionescu
https://developer.apple.com/library/ios/documentation/uikit/reference/UIViewController_Class/Reference/Reference.html#//apple_ref/occ/instm/UIViewController/shouldPerformSegueWithIdentifier:sender:这个方法似乎是在iOS 6.0及以上版本中引入的。 - Brenden

8

当你在-prepareForSegue:sender:中收到消息时,取消segue已经太晚了。

为了有效地实现这一点,您应该从视图控制器本身创建弹出窗口的segue而不是从栏按钮创建,以便它们仍然可以通过编程方式执行。现在将 UIBarButtonItem 连接到一些方法,这些方法将有条件地呈现或解除弹出窗口。

- (IBAction)showPopoverA
{
    if (self.popoverA.popoverController.popoverVisible)
        [self.popoverA.popoverController dismissPopoverAnimated:YES];

    [self performSegueWithIdentifier:@"ShowPopoverA"];
}

1
尝试了那个建议后,我得到了如下错误:终止应用程序,原因是未捕获的异常'NSInternalInconsistencyException',原因是'UIStoryboardPopoverSegue必须从栏按钮项或视图中呈现。' - Timothy Newton
- (IBAction)showPopoverA:(id)sender { if ([self.popoverA.popoverController isPopoverVisible]) { [self.popoverA.popoverController dismissPopoverAnimated:YES]; } [self performSegueWithIdentifier:@"showPopoverASegue" sender:sender]; } - Timothy Newton
`- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { if ([[segue identifier] isEqualToString:@"showPopoverASegue"]) { UINavigationController *navController = [(UIStoryboardPopoverSegue *)segue destinationViewController]; PreferencesVC *dvc = [[navController viewControllers] objectAtIndex:0]; [dvc setUserPrefs:self.userPrefs]; [dvc setDelegate:self]; // used to close popover [self setPrefsPopover:(UIStoryboardPopoverSegue *)segue]; [self.prefsPopover.popoverController setDelegate:self]; }` - Timothy Newton
抱歉没有换行。似乎无法格式化我的注释以使其更易读。 - Timothy Newton
搞定了。你必须将segue的锚点设置回适当的UIBarButtonItem。此外,发现要切换,[self performSegueWithIdentifier:sender] 应该在else子句中(否则问题会再次出现)。再次感谢提示,它让我走上了正确的轨道。 - Timothy Newton

1

组合起来对我很有帮助

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([segue.identifier isEqualToString:@"showPopover"]) {
        self.tableOfContentsPopoverController = [(UIStoryboardPopoverSegue*)segue popoverController];
    }
}

- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender {
    if ([identifier isEqualToString:@"showPopover"]) {
        if (!self.tableOfContentsPopoverController.popoverVisible) {
            return YES;
        }
        return NO;
    }
    return YES;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接