展开后执行segue

Posted

技术标签:

【中文标题】展开后执行segue【英文标题】:Perform segue after unwinding 【发布时间】:2016-04-08 04:19:32 【问题描述】:

我有一个包含在导航控制器中的主屏幕。

主屏幕有几个按钮可以触发到其他视图的 segues。一键进入表格视图。

此表中的选择应触发通常由主视图上的按钮之一执行的转场。

我假设我需要先展开到主屏幕,然后以编程方式从展开转场触发转场,但是当我这样做时,它会先执行程序转场,然后展开,最后再次出现在主屏幕上。

处理这种情况的正确方法是什么?我不想在以编程方式调用 segue 之后返回表格视图,然后返回按钮应该转到主视图。

如果它有助于进一步解释我的用例:表格视图是一个级别列表。选择应该启动我的游戏视图,并在表格视图中选择级别。

我在主视图中的放松转场:

@IBAction func backFromLevelSelectionUnwindSegue(segue:UIStoryboardSegue) 
    performSegueWithIdentifier("playSegue", sender: self)

显然playSegue 是游戏视图控制器的segue。

对类似问题的回答建议设置一个布尔标志,然后在 viewDidAppear 中执行转场,但 viewDidAppear 似乎不必知道已发生的展开转场。有没有我没有遇到过的“正确”解决方案?

【问题讨论】:

【参考方案1】:

在您的 backFromLevelSelectionUnwindSegue 中,您仍处于 unwind segue 上下文中。因此,在使用 dispatch_asyncperformSelector:withObject:afterDelay 完成上下文后调用 performSegueWithIdentifier,如下所示。

@IBAction func
backFromLevelSelectionUnwindSegue( segue:UIStoryboardSegue ) 
    dispatch_async( dispatch_get_main_queue() ) 
        self.performSegueWithIdentifier( "playSegue", sender: self )
    

【讨论】:

【参考方案2】:

您是否可以在不展开到主屏幕的情况下对游戏视图执行转场?那么当你展开segue时,将它展开到主视图而不是回到表格视图?如果我没记错的话,我们可以通过呈现视图控制器来放松。

【讨论】:

返回按钮将转到表视图而不是主视图【参考方案3】:

这是一个见仁见智的问题,但在你的情况下,我认为你应该简单地在 tableview 和游戏之间设置一个 segue,任何必要的额外数据都从主 VC 传递给 tableview VC。

如果您需要返回 UINavigationVC 中的多个 viewController,我会考虑使用 popToRootViewController 或在它们之间使用 unWind。例如从第三个 viewController 调用 unwind,处理程序在第一个 viewController 中

【讨论】:

所以把表视图留在视图层次结构中并不少见?我必须说这似乎比让 viewDidLoad 执行 segue 更干净。 我认为以不同的方式来做这件事很好,但它似乎是一个很好的关注点组织。当你点击一行时,那个 VC 应该决定做什么。它不应该把它踢回它的父级。【参考方案4】:

可以有多个返回不同位置的展开转场。在给定的场景中,应该安排视图控制器 Main->LevelSelect->Game 然后当游戏结束时,您有 2 或 3 个展开 segues 的按钮。第一个是exitToGameStart,它允许玩家重新开始同一关卡。 exitToLevelSelect 允许玩家选择一个新的关卡。并且可选地exitToMainMenu 一直回到开始。有关完整示例,请参阅Apple's UnwindSegue sample,尤其是执行exitToQuizStart unwind segue 的最后一个表上的“Start Over”按钮和执行exitToHomeScreen unwind segue 的“返回到菜单屏幕”。接收方法代码如下:

QuestionViewController.m

//! Unwinds from the ResultsViewController back to the first
//! QuestionViewController when the user taps the 'Start Over' button.
//
//  This is an unwind action.  Note that the sender parameter is a
//  'UIStoryboardSegue*' instead of the usual 'id'.  Like all unwind actions,
//  this method is invoked early in the unwind process, before the visual
//  transition.  Note that the receiver of this method is the
//  destinationViewController of the segue.  Your view controller should use
//  this callback to update its UI before it is redisplayed.
//
- (IBAction)exitToQuizStart:(UIStoryboardSegue *)sender

    // The user has restarted the quiz.
    [self.currentQuiz resetQuiz];

MainMenuViewController.m

//! Unwinds from the ResultsViewController back to the MainMenuViewController
//! when the user taps the 'Return to the Home Screen' button.
//
//  This is an unwind action.  Note that the sender parameter is a
//  'UIStoryboardSegue*' instead of the usual 'id'.  Like all unwind actions,
//  this method is invoked early in the unwind process, before the visual
//  transition.  Note that the receiver of this method is the
//  destinationViewController of the segue.  Your view controller should use
//  this callback to retrieve information from the sourceViewController.  Used
//  properly, this method can replace existing delegation techniques for
//  passing information from a detail view controller to a previous view
//  controller in the navigation hierarchy.
//
- (IBAction)exitToHomeScreen:(UIStoryboardSegue *)unwindSegue

    // Retrieve the score from the ResultsViewController and update the high
    // score.
    ResultsViewController *resultVC = (ResultsViewController*)unwindSegue.sourceViewController;
    self.highScore = MAX(resultVC.currentQuiz.percentageScore, self.highScore);

注意:要在最新的 Xcode 中构建旧项目,请打开故事板、文件检查器、构建版本、选择更新的 ios 版本。

【讨论】:

以上是关于展开后执行segue的主要内容,如果未能解决你的问题,请参考以下文章

如何创建 Segue 的动画执行和展开 Segue?

无法以编程方式执行 unwind segue

自定义展开 Segue

在多个故事板环境中展开 segue

Swift 致命错误:在 segue 上展开 Optional 值时意外发现 nil

在单元测试中以编程方式执行 Unwind Segue