let a:Int? = nil // block not executed - unwapping done,type is inferred if let unwrapped_a = a { println(unwrapped_a) } // block not executed - unwrapping done,type is specified if let unwrapped_a:Int = a { println(unwrapped_a) } // block gets executed - unwrapping not done,new local constant + assignment is done instead? if let not_unwrapped_a:Int? = a { println(not_unwrapped_a) }
那么我应该假设Swift在第一种情况下进行了解包,而在第二种情况下进行了分配吗?@H_404_5@
这种语法是不是太接近造成混乱?我的意思是,是的,编译器警告您在使用not_unwrapped_a时使用的是可选类型,但仍然如此.@H_404_5@
更新:@H_404_5@
所以在Airspeed Velocity的回答之后,我发现另一个(但实际上是相同的)奇怪的情况:@H_404_5@
if let not_unwrapped_a:Int???? = a { println(not_unwrapped_a) }
a将默默地包裹在Int ????中.所以这将是一种Int ????? (五) – 因为a已经是可选的.然后它将被解开一次.@H_404_5@ @H_403_16@
解决方法
案例3非常有趣.@H_404_5@
每当你有一个值时,Swift总是愿意默默地将它升级为一个可选的包装值,如果它有助于使类型匹配和代码编译.类型的Swift自动升级是相当罕见的(例如,它不会隐式地将Int16升级为Int32),但是对optionals的值是一个例外.@H_404_5@
这意味着您可以在需要可选项的地方传递值,而无需费心去包装它:@H_404_5@
func f(maybe: Int?) { ... } let i = 1 // you can just pass a straight value: f(i) // Swift will turn this into this: f(Optional(i))
所以在你的最后一个例子中,你告诉Swift你想要not_unwrapped_a成为一个Int?.但它是let的一部分,需要在分配给它之前将其解包.@H_404_5@
有了这个,Swift可以使其工作的唯一方法是隐式地包装另一个可选项,这就是它的作用.现在它是一个可选项,包含一个包含nil的可选项.这不是一个零值可选 – 这是一个包含值的可选项(包含nil的可选值).展开会给你一个包含nil的可选项.好像什么也没发生.但它确实 – 它被包裹了第二次,然后解开了一次.@H_404_5@
如果使用swiftc -dump-ast source.swift编译示例代码,则可以看到这一点.你会看到短语inject_into_optional implicit type =’Int ??’. Int ?? ??是一个包含可选项的可选项.@H_404_5@
包含选项的选项不是模糊的边缘情况 – 它们很容易发生.例如,如果你曾经…在包含选项的数组中,或者使用下标从包含选项的字典中获取值,则选项的选项已经参与该过程.@H_404_5@
考虑这个问题的另一种方法是,如果你考虑让x = y {}作为*类似函数if_let,定义如下:@H_404_5@
func if_let<T>(optVal: T?,block: T->()) { if optVal != nil { block(optVal!) } }
现在假设您提供了一个采用Int的块? – 也就是说,T将是一个Int?.那么T?将是一个Int ??.当你通过常规的Int?进入if_let和那个块,然后Swift会隐式地将它升级为Int ??使它编译.那基本上是if let not_unwrapped_a:Int?正在发生什么.@H_404_5@
我同意,隐式可选升级有时会令人惊讶(更令人惊讶的是Swift将升级返回选项的函数,即如果函数采用(Int) – > Int ?,它将升级(Int) – > Int返回一个可选的替代).但据推测,感觉是潜在的混乱是值得的,因为在这种情况下方便.@H_404_5@
*只有一种@H_404_5@ @H_403_16@ @H_403_16@ 原文链接:https://www.f2er.com/iOS/327773.html