【问题标题】:testing "presentingViewController is UIViewController" works fine in one case, fails in other测试“presentingViewController is UIViewController”在一种情况下工作正常,在其他情况下失败
【发布时间】:2017-06-28 07:42:59
【问题描述】:

按照 Apple 的文档添加和编辑信息Apple guide here 我有一个带有 tableview 的 Viewcontroller。表格视图包含一个带有“添加新”按钮的标题。如果选择了表格行,则将 detailViewController 推入堆栈。 detailViewController 也嵌入在 UINavigationController 中,就像在 Apple 的文档中一样。如果按下“Add new”,则会执行另一个 segue,以模态方式呈现 UINavigationController,进而显示 detailViewController。这工作正常,动画清楚地显示了一个模态呈现的 ViewController。

detailViewController 在 NavigationBar 中包含一个取消按钮。如果按下,则运行以下代码:

@IBAction func cancel(_ sender: UIBarButtonItem) {
    // Depending on style of presentation (modal or push presentation), this view controller needs to be dismissed in two different ways.
    var isPresentingInAddActionMode = false
    if let presentingVC = self.presentingViewController{
     isPresentingInAddActionMode = presentingVC is UINavigationController

    }
    streekgidsModel.undoManager.endUndoGrouping()
    print("undo grouping ended and undone")
    streekgidsModel.undoManager.undo()
    if isPresentingInAddActionMode {
        dismiss(animated: true, completion: nil)
    }
    else if let owningNavigationController = navigationController{
        owningNavigationController.popViewController(animated: true)
    }
    else {
        fatalError("The MealViewController is not inside a navigation controller.")
    }
}

第一个 if 语句检查属性 presentingViewController 是否存在,如果存在,是否为 UINavigationController 类型。如果是这样,viewController 会以模态方式呈现,并且应该被关闭。如果不是,它会被压入堆栈,并且 owningNavigationController 应该弹出 detailViewController。 运行此代码无法按照 Apple 的描述运行。 presentingViewController 上的检查显示它存在,但类型检查返回“无效”。这被视为错误。 owningNavigationController 上的测试成功(我认为它应该失败)并且 popViewController 被执行。由于没有推送,视图控制器不会弹出或关闭,并且仍然可见。第二次按下 Cancel 会再次执行 func cancel,这会导致错误,因为在 undo manager 中不再启动一个组。

令人费解的是,我在另一个视图控制器中有相同的代码,具有相似的 UIViewTable 和导航,并且工作正常。

所以要提出这个问题:为什么这不像 Apple 描述的那样工作,为什么我的其他视图控制器按预期工作?任何意见表示赞赏。

顺便说一句,致命错误文本直接来自文档,因此命名不相关且永远不会执行。

【问题讨论】:

    标签: ios swift uiviewcontroller


    【解决方案1】:

    我会先检查谁是演示者。

    根据 Apple 文档:

    当您使用 present(_:animated:completion:) 方法以模态方式(显式或隐式)呈现视图控制器时,呈现的视图控制器将此属性设置为呈现它的视图控制器。如果视图控制器没有以模态方式呈现,但它的祖先之一是,则此属性包含呈现祖先的视图控制器。如果当前视图控制器或其任何祖先均未以模态方式呈现,则此属性中的值为 nil。

    如果文档是正确的,那么您的演示者应该是您的“带有 tableview 的 Viewcontroller”,我猜它不是 UINavigationController。如果是这种情况,那么您应该了解代码失败的原因。

    这当然取决于您的上下文,但我会以这种方式简化检查:

    var isPresentingInAddActionMode = self.presentingViewController != nil 
    ... // your other code
    if isPresentingInAddActionMode {
        dismiss(animated: true, completion: nil)
    }
    else if let owningNavigationController = navigationController{
        owningNavigationController.popViewController(animated: true)
    }
    

    如果我正确理解了您的问题和意图,那么谁(哪个班级)展示了您的 detailVC 并不重要,您只关心您的 detailVC 是如何呈现的——无论是在导航视图控制器中推送还是以模态方式呈现。我认为只需检查presentingViewController 属性即可获得该信息。

    【讨论】:

    • 我确实检查了哪个是演示者;它是一个视图控制器,但不是 UINavigationController 类型,也不是我的带有 tableview 的视图控制器的类型或实例。模态呈现的一个祖先是嵌入的 UINavigationController。所以那里没有运气。此外,布尔检查报告为无效而不是错误。你说得对,我唯一关心的是如何呈现 VC,以便以正确的方式将其从堆栈中解散或弹出。
    • @KvdLingen 无效的布尔检查是什么意思?您能否详细说明(或者发布日志或屏幕截图)?
    • 最终将我自己的变量放入 viewController。并将其设置在呈现视图控制器的 prepareForSegue 方法中。这工作正常。感谢您的建议。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-25
    • 1970-01-01
    • 1970-01-01
    • 2018-09-15
    • 2013-07-05
    相关资源
    最近更新 更多