Optional 与 字符串 的交互
你知道这个问题吗? 你想要在 UI 上显示一个 Optional 值,或者是在控制台打印出来,但你不喜欢默认的 Optional 字符串的显示方式: "Optional(...)" 或者是 "nil". 例如: var someValue: Int? = 5 print("这个值是 (someValue)") // "这个值是 Optional(5)" someValue = nil print("这个值是 (someValue)") // "这个值是 nil" 在字符串里插入 Optional 值会有一些不可预料的结果Swift 3.1 会在你往字符串里插入一个 Optional 值的时候发出一个警告,因为这个行为可能会产生意料之外的结果. 这里有 Julio Carrettoni,Harlan Haskins 和 Robert Widmann 在 Swift-Evolution 的讨论:
在最新的 Swift 开发版本(2016-12-01)里已经实现了这个警告:
你有几个方法可以去掉这个警告:
上面的方式我都不是特别喜欢,但这是编译器能提供的最好的方式了. 第三种做法的问题是解包操作符 一个自定义的字符串解包操作符我通过自定义一个字符串解包操作符来解决这个问题. 因为它来源于 infix operator ???: NilCoalescingPrecedence public func ???<T>(optional: T?,defaultValue: @autoclosure () -> String) -> String { switch optional { case let value?: return String(describing: value) case nil: return defaultValue() } } @autoclosure 结构保证了右边的值只会在需要的时候才会被计算出来,例如 Optional 值是 nil 的时候. 这就可以让你传递一个复杂的或者耗时的运算表达式进去,而只会在特定情况下才会影响到性能. 我不认为这种情况(表达式很复杂)会经常发生,但它是参考了 ?? 操作符在标准库里的实现.(尽管我决定去掉标准库实现里的 throws/rethrows) 或者,你可以通过 Optional.map 只用一行代码来实现这个操作符,就像这样: public func ???<T>(optional: T?,defaultValue: @autoclosure () -> String) -> String { return optional.map { String(describing: $0) } ?? defaultValue() } 这跟第一个实现的效果一模一样,用哪一个只看你个人的口味和代码习惯. 我不认为哪一个比另一个更加清晰. 最后一件我想说的是,你必须从 String(describing:) (更偏向于值的描述) 或者是 String(reflecting:) (更偏向于 debug 信息) 中做出一个选择,去转化这个值. 前一个选择更适合 UI 展示,而后一个则更适合运行日志. 甚至你可以再自定义一个操作符 (例如: 实际使用我们使用 var someValue: Int? = 5 print("值是 (someValue ??? "unknown")") // "值是 5" someValue = nil print("值是 (someValue ??? "unknown")") // "值是 unknown" 这是一个很小的改变,但我很喜欢 [1]. 我最开始其实觉得重载 译者注我想特别说明一点是,在我们的项目里,重载 如果是我们自己想写框架的话,声明为 但我不太确定声明为 如果有了解的人,或者已经做过测试的人,可以的话告诉一下我准确的结果 相关阅读emptiness (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |