什么是在Swift中对顺序绑定进行可选绑定的优势?

时间:2017-09-19 19:37:24

标签: swift optional

在简短教程here中,在步骤5中分配了一个代理:

if let nav = segue.destination as? UINavigationController,
   let classBVC = nav.topViewController as? ClassBVC {
       // 'self' is ClassAVC which has been delegated.
       classBVC.delegate = self
   }

我发现很难遵循这些陈述,所以写下来是一个很大的缺点:

let nav = segue.destination as? UINavigationController
let classBVC = nav?.topViewController as? ClassBVC
classBVC!.delegate = self

3 个答案:

答案 0 :(得分:3)

没有顺序绑定这样的东西。你在第二个语句中所做的是被称为可选链接和可选的强制转换,如果不是你最后一行中的强制解包,这将是安全的。

此处展开的力量使您的第二个解决方案不安全。如果任何先前的可选操作导致nil值,则将发生运行时异常。

classBVC!.delegate = self

如果需要打开可选值,可选绑定是执行此操作的最佳选项之一。您可以通过减少if let语句的数量来使可选展开的样板代码最小化。在某些情况下,使用guard let代替if let也可以生成更清晰的代码,因为您不必将块嵌套在彼此内部。

使用可选绑定,您将永远不会看到

  

在展开可选值时意外发现nil

运行时异常,如果您强行解包可能实际具有nil值的选项,您可能会经常看到它。

guard let nav = segue.destination as? UINavigationController, let classBVC = nav.topViewController as? ClassBVC else { return }
classBVC.delegate = self

答案 1 :(得分:1)

是的,因为您声明classBVC绝对是ClassBVC个对象。如果你将它包装在if let语句中,如果一个失败,它将不会崩溃展开nil值。

答案 2 :(得分:1)

如果您的应用成功运行需要ClassBVC成为destination导航控制器的顶视图控制器,那么您的第二个模式没有任何问题。事实上,我实际上更喜欢你的第二个模式,因为使用前一个模式(可选的强制转换/解包),如果任何一个强制转换失败,代码会默默地进展,而不会让你知道出现了严重的问题。而你正在努力弄清楚为什么没有调用你的委托方法。

我可能会建议的唯一一个小调整是,如果这确实是要求,我会完全删除可选的投射/链接。如果前两行可选的转换/链接中的任何一行失败,则有两行可选的转换/链接,然后是强制解包,这将无效。我会在代码中明确说明:

let nav = segue.destination as! UINavigationController
let classBVC = nav.topViewController as! ClassBVC
classBVC.delegate = self

这样,在阅读你的代码时,你不必到第三行来确定前两个强制转换不是真正可选的,而是必不可少的。这一修订明确了这一点。

如果您感到被迫guard对抗其中一个演员阵容可能失败的情况,我建议您确认通知开发人员这些必要的(假设他们是真正需要的)演员表失败:

guard let nav = segue.destination as? UINavigationController, let classBVC = nav.topViewController as? ClassBVC else {
    fatalError("destination should be nav controller who's top view controller is a ClassBVC")
}

classBVC.delegate = self

我个人认为这比上面的模式要好得多(当然,错误更明确,但我不认为代码更具可读性和结果,如果转换失败则崩溃,是相同)。但是如果你想要一个更具信息性的错误信息,那就是解决这个问题的一种方法。