Swift 良好的编码实践:可选类型 Bool 的 If 语句
Posted
技术标签:
【中文标题】Swift 良好的编码实践:可选类型 Bool 的 If 语句【英文标题】:Swift good coding practice: If statement with optional type Bool 【发布时间】:2014-09-10 15:27:41 【问题描述】:所以我一直在用 Swift 开发一个应用程序,今天我花了将近一个小时来调试一个完全出乎意料的问题。这一切都源于下面的代码。
if (hero.isAI) //isAI is a Bool
问题是这个 if 语句总是返回 true。所以我想也许我在某处将 isAI 设置为 true,但最后我意识到我将 isAI 声明为可选类型,如下所示。
var isAI: Bool!
应该是什么时候
var isAI: Bool
这导致 if 语句不检查 isAI 是否为真,而是检查它是否包含值。
所以现在为了安全起见,我一定要像这样写我的 if 语句
if (hero.isAI == true) //isAI is a Bool
所以我的问题是,我有哪些选择可以在未来避免这个问题?(这个问题似乎非常危险,尤其是在一个大型项目的团队中工作时)。 我是否应该始终明确地编写我的 if 语句,我是否应该完全避免 Bools 的可选类型?
请注意,我在 Xcode Beta 2 中没有这个问题。这个问题是在我升级到 Xcode beta 3 时出现的。我认为是因为在 Beta 2 中,Apple 通过检查其值而不是在 if 语句中处理隐式展开的 Bool检查它是否包含一个值。
最后,下面是一个例子,如果给定一个可选的 Bool 来运行 if 语句,以更好地帮助人们理解问题。
let myBool: Bool! = false
if (myBool)
//Runs
if (myBool!)
//Won't Run
if (!myBool)
//Runs
if (myBool == true)
//Won't Run
【问题讨论】:
你为什么有一个可选的布尔值?会很容易避免吗? 我有一个初始化后运行的设置方法。 对不起,我对可选选项有点困惑,为什么声明时是!
而不是?
?
我选择将 Bool 声明为隐式解包,这样我就不需要每次想使用它时都解包它。也因为我知道我会给它一个价值。通常我根本不需要让它成为可选的,只需在初始化时为其分配一个值,但我有一个单独的设置方法,在初始化之后发生,所以在设置方法运行之前,Bool 在技术上将为零。
包装布尔的问题已在较新的 Swift 版本中得到修复。要检查一个可选项是否为 nil,现在最常将其与 nil 进行比较。所以没有重复的意思了。
【参考方案1】:
这是一个已知问题,正在 SwiftInFlux 存储库上进行跟踪,其中包括来自 Chris Lattner on the Apple developer forums 的引用。
此问题存在于符合以下条件的任何可选内容中 LogicValue 协议(例如,嵌套选项、布尔选项、 等等)。我们认为这是一个严重的问题,需要在 1.0 和 有一些想法,但尚未确定解决方案。
所以,这个问题不仅影响可选的布尔值,还影响任何符合 LogicValue 协议(定义为)的可选类型。
protocol LogicValue
func getLogicValue() -> Bool
无论如何,就如何解决这个问题的建议而言,很难推荐任何一种具体的解决方案,因为 Apple 没有说明他们打算在未来如何解决这个问题,但我想继续明确检查 Bool 的值将是要走的路。
if (hero.isAI == true)
// stuff
其实经过一番进一步的阅读,上面列出的引文继续阅读:
对于这种常见情况,最简单的答案是生成一个 警告“if x”并要求某人明确写“if x!= nil" 或 "if x == true" 来明确他们想要什么。
【讨论】:
谢谢你,正是我想要的。很高兴看到他们承认这是一个问题。【参考方案2】:我的建议是使用这种漂亮的合并 ??
if textfieldDate.text?.isEmpty ?? true
// the text is either nil or empty but its all we want to know
【讨论】:
【参考方案3】:如果 bool 是 Core Data(又名 NSNumber)的一部分,你应该这样做。
if (isHero.isAI?.boolValue != nil)
问候
【讨论】:
以上是关于Swift 良好的编码实践:可选类型 Bool 的 If 语句的主要内容,如果未能解决你的问题,请参考以下文章
使用 Swift 的 Encodable 将可选属性编码为 null 而无需自定义编码