Mar*_*eIV 3 optional swift optional-binding
好的,所以我知道在Swift中使用选项的正常方法是通过可选的绑定来解开它们,就像这样......
let stringA:String? = nil // (or "ABC")
if let unwrappedStringA = stringA
{
let x:String = unwrappedStringA
}
Run Code Online (Sandbox Code Playgroud)
但是我也看到了使用隐式解包的选项的以下方式,我个人认为它看起来更干净,因为它不仅不需要额外的变量,而且它"读取"更好,更像英语(即'如果这是不是,然后......')可读性是Swift的核心原则之一(特别是在即将推出的Swift 3.0中).
let stringA:String! = nil // (or "ABC")
if stringA != nil
{
let x:String = stringA
}
Run Code Online (Sandbox Code Playgroud)
然而,就后者而言,斯威夫特的"纯粹主义者"将此称为"代码嗅觉"并坚持认为它是"坏,坏,坏!!"......但他们从未解释过为什么!那么......为什么这么糟糕?
注意:是的,我知道可选链接和其他这些功能,你不能使用隐式解包的选项,它们都是非常酷的功能,但我特别询问测试隐式解包的选项对nil的技术缺点vs可选绑定.
我希望的是可量化的技术原因,为什么一个比另一个好(即编译器优化,更好的安全检查,性能等)换句话说,不仅仅是'嘿,因为那不是'Swifty'的方式去做吧!' 希望有道理.
我实际上刚刚找到了一种方法来解决我的一个问题(至少是表面的方式),它必须创建一个新变量来保存未包装的变量.这里的技巧是因为展开的变量实际上与可选的本身不同,你可以使用完全相同的名称.
此外,括号内部还有另一个范围,它也可以有一个名为stringA的变量.这意味着你现在可以拥有三个'stringA'变量(但并不意味着你应该!)......
这是这个疯狂的代码显示这个......
let stringA:String? = nil // (or "ABC") // First stringA variable
if let stringA = stringA
{
let x:String = stringA // <- This stringA is the unwrapped optional (the second stringA)
// Now we're just getting crazy (and smelly!)
let stringA = stringA + stringA // <- This is yet another stringA (third one!)
let y:String = stringA
}
Run Code Online (Sandbox Code Playgroud)
再一次,我不是在纵容这个!! 我只是从一个有启发性的角度展示其他人可能会感兴趣的代码.我确定做到了!
确实有一个简单的原因,这是你列出的一个:"更好的安全检查".可选绑定保持编译器已知的解包范围,而程序员有责任跟踪您何时检查或未检查隐式解包的可选项nil.
使用可选绑定:
let stringA:String? = nil // (or "ABC")
if let unwrappedStringA = stringA
{
let x:String = unwrappedStringA
}
accidentallyAttemptingToUse(stringA) // Compiler error! I see my mistake.
Run Code Online (Sandbox Code Playgroud)
隐式展开:
let stringA:String! = nil // (or "ABC")
if(stringA != nil)
{
let x:String = stringA
}
accidentallyAttemptingToUse(stringA) // Runtime crash I might find in testing. Yuck.
Run Code Online (Sandbox Code Playgroud)
什么是 IUO有益?
为什么要隐含地打开选项呢?它们的存在基本上只有一个目的:肯定会有值的属性,但直到稍后init才有,所以它们必须是可选的.通常@IBOutlet属于这一类:你可以相信他们有一个价值,你不想一直打开它们,但是它们没有被分配init,所以你必须让它们成为可选的.这就是隐含的解包方案.
展开到同名变量
您的更新暂时建议将选项包装到具有相同名称的变量中,实际上是优秀的 Swift风格,并且早期和经常被Apple使用.当您打开同名变量时,代码更容易阅读,因为您可以跟踪更少(和更好)的名称.绝对拥抱这个!
let stringA:String? = nil // (or "ABC")
if let stringA = stringA
{
let x:String = stringA // Of *course* this is still named `stringA`;
// it's representing the same concept, after all.
}
Run Code Online (Sandbox Code Playgroud)
由于Swift 3中隐式解包选项的更改,如果您正确解包常规选项而不是使用隐式解包的选项,您会更高兴.
在Swift 3中,如果String!为新变量赋值,则该变量将具有该类型String?.这意味着你的隐式展开成为可选分配上经常可选的,你现在要处理的展开新的变量.
此代码适用于Swift 2.x:
let stringA: String! = "Hello"
if stringA != nil
{
let y = stringA
let z = y + " world!"
}
Run Code Online (Sandbox Code Playgroud)
在Swift 3中:
let stringA: String! = "Hello"
if stringA != nil
{
let y = stringA
let z = y + " world!" // ERROR: value of optional type 'String?' not unwrapped; did you mean to use '!' or '?'?
}
Run Code Online (Sandbox Code Playgroud)
如果您使用String?并打开它,那么代码在Swift 2.x和Swift 3中按预期工作:
let stringA: String? = "Hello"
if let stringA = stringA
{
let y = stringA
let z = y + " world!"
}
Run Code Online (Sandbox Code Playgroud)
请参阅此处有关此更改的官方讨论:SE-0054:废除隐式解包的可选类型
本文件的" 动机"部分指出[强调添加我的]:
ImplicitlyUnwrappedOptional("IUO")类型是用于导入Objective-C API的有用工具,其中未指定参数或返回类型的可为空性.它还代表了一种在初始化器中处理明确初始化问题的便捷机制. 但是,IUO是一种过渡技术; 它们代表了一种简单的 方法来解决未标注的API或缺乏语言功能 ,可以更优雅的处理代码的某些模式.因此,我们 希望限制其使用前进,并引入更 具体的语言功能来取代它们.除了一些 特定情况,选项总是更安全的赌注,我们希望 鼓励人们使用它们而不是IUO.
该提案旨在将IUO的采用限制在 实际需要 它们的地方,并且当 其他技术不必要时,将Swift语言放在完全从系统中删除隐式未包装选项的路径上.它还完全废除了IUO的任何概念,低于编译器的类型检查器级别,这将大大简化编译器实现.
这清楚地表明语言设计者认为你应该尽可能少地使用Implicitly Unwrapped Optionals.
| 归档时间: |
|
| 查看次数: |
453 次 |
| 最近记录: |