如何解除使用 contextForSegue 呈现的 WKInterfaceController?

Posted

技术标签:

【中文标题】如何解除使用 contextForSegue 呈现的 WKInterfaceController?【英文标题】:How do I dismiss a WKInterfaceController that was presented with contextForSegue? 【发布时间】:2018-08-19 21:50:55 【问题描述】:

我有一个WKInterfaceController 和一个WKInterfaceTable,其中列出了用户在我的应用中记录的一些事件。

用户可以点按表格的一行来查看有关该事件的更多详细信息。为了实现这一点,我在包含表格的WKInterfaceController 上覆盖了contextForSegue(withIdentifier:in:rowIndex:),因此点击一行以模态方式在名为EventDetailController 的新WKInterfaceController 中显示该行的详细视图。

modal 演示文稿在情节提要上定义。我不能使用push 演示文稿,因为WKInterfaceControllerWKInterfaceTable 是我应用程序顶层WKInterfaceController 多个实例中的一个页面。

这是主要问题:

EventDetailController内,有一个Delete按钮,用于销毁表格行所代表的记录。

当用户点击删除按钮时,我会显示一个提醒,允许用户确认或取消删除操作。

一旦用户确认删除记录,我想关闭 EventDetailController,因为它不再相关,因为它代表已删除的记录。

这是在EventDetailController 上定义的IBAction,当点击删除按钮时会调用它:

@IBAction func deleteButtonTapped(_ sender: WKInterfaceButton) 

    let deleteAction = WKAlertAction(title: "Delete", style: .destructive) 

        // delete the record

        // as long as the delete was successful, dismiss the detail view
        self.dismiss()
    

    let cancelAction = WKAlertAction(title: "Cancel", style: .cancel) 
        // do nothing
    

    presentAlert(withTitle: "Delete Event",
                 message: "Are you sure you want to delete this event?",
                 preferredStyle: .alert,
                 actions: [deleteAction, cancelAction])

问题在于 watchOS 似乎不允许这样做。测试此代码时,EventDetailController 不会关闭。相反,控制台中会记录一条错误消息:

[WKInterfaceController dismissController]:434: calling dismissController from a WKAlertAction's handler is not valid. Called on <Watch_Extension.EventDetailController: 0x7d1cdb90>. Ignoring

我尝试了一些奇怪的变通方法来试图诱使EventDetailController 解除,例如在事件被删除时触发通知并从通知观察者调用的函数中解除EventDetailController,但是也不行。

在这一点上,我认为有一些正确的方法可以让我解除WKInterfaceController,或者换句话说,反转contextForSegue(withIdentifier:in:rowIndex:) 调用,但我不知道它是什么。

当我直接在IBAction 中而不是在WKAlertAction 处理程序中调用dismiss() 时,它工作正常,但我不喜欢这种实现,因为它不允许用户先确认操作.

【问题讨论】:

【参考方案1】:

我觉得自己像个白痴,但我想出了解决办法。

答案一直在 Apple 的 WKInterfaceController.dismiss() 文档中(重点已添加):

当您想关闭您以模态方式呈现的界面控制器时调用此方法。 始终从 WatchKit 扩展的主线程调用此方法。

我所要做的就是在主线程上调用self.dismiss()

这是我更新后的删除操作代码,现在可以按预期工作:

let deleteAction = WKAlertAction(title: "Delete", style: .destructive) 

    // delete the record

    // as long as the delete was successful, dismiss the detail view
    DispatchQueue.main.async 
        self.dismiss()
    

希望这可以为其他人节省一些故障排除时间!

【讨论】:

我们有一些类似的代码在 watchOS4 上运行良好,但在 watchOS5 上被破坏了。添加这个为我们解决了它:DispatchQueue.main.async self.dismiss() 谢谢,节省了我一些时间。此外,当 .dismiss() 代码未在主线程上调用时,Apple 至少可能会崩溃(就像在许多其他情况下一样)。

以上是关于如何解除使用 contextForSegue 呈现的 WKInterfaceController?的主要内容,如果未能解决你的问题,请参考以下文章

UIViewController 在解除先前呈现的模态视图控制器后被释放

禁用呈现的视图控制器的交互式解除

需要协助解除模态呈现的 ViewController 并从 UINavigationController 弹出 ViewController

如何从 UIAlertView 按钮中解除 segues

视图控制器解除动画参数

如何以模态方式呈现标准 UIViewController