首先,我尝试映射[String?]
,以获得[String]
:
$ xcrun swift
Welcome to Apple Swift version 2.2 (swiftlang-703.0.18.8 clang-703.0.30). Type :help for assistance.
1> import Foundation
2> let j: [String?] = ["a", nil]
j: [String?] = 2 values {
[0] = "a"
[1] = nil
}
3> j.map {$0 ?? ""}
$R0: [String] = 2 values {
[0] = "a"
[1] = ""
}
这对我来说非常有意义。我没有合并String?
,我得到String
。但是对于[AnyObject?]
,会发生一些奇怪的事情:
4> let k: [AnyObject?] = ["a", nil]
k: [AnyObject?] = 2 values {
[0] = "a"
[1] = nil
}
5> k.map {$0 ?? ""}
$R1: [AnyObject?] = 2 values {
[0] = "a"
[1] = (instance_type = 0x00007fff7bc2c140 @"")
}
我是零合并选项,但这次我选择了。为什么呢?
Swift Programming Language说a ?? b
是a != nil ? a! : b
的简写,但是当我尝试这样做时,我会得到一系列非选项:
6> k.map {$0 != nil ? $0! : ""}
$R2: [AnyObject] = 2 values {
[0] = "a"
[1] = ""
}
我是否误解了??
应该如何运作?这是怎么回事?
答案 0 :(得分:2)
详细的行为没有详细记录,因此,未来的Swifts会发生变化。
但是你应该知道合并运算符有两个重载:
@warn_unused_result
public func ??<T>(optional: T?, @autoclosure defaultValue: () throws -> T) rethrows -> T
@warn_unused_result
public func ??<T>(optional: T?, @autoclosure defaultValue: () throws -> T?) rethrows -> T?
在您的情况下,Swift已选择后者作为您的代码。
您可以使用简化代码进行测试,例如:
let x: AnyObject? = "a"
x ?? ""
推断类型(在Swift 2.2.1中)变为AnyObject?
。
但是这段代码也是有效的。
let y: AnyObject = x ?? ""
像""
这样的字符串文字可以被视为各种类型。所有这些在Swift中都是有效的。
"" as String
"" as String?
"" as NSString
"" as NSString?
"" as AnyObject
"" as AnyObject?
因此,有一些未说明的原因,Swift选择了AnyObject?
。
并且,如果类型推断可能不明确,您应该使用显式类型注释,如appzYourLife的注释中所建议的那样。
答案 1 :(得分:0)
我注意到Apple认为这是Swift 2中的一个错误。
在Swift 3中,上面的第一个例子仍然有效,而第二个和第三个例子是无效的语法(有或没有基础桥接)。
将AnyObject
声明替换为Any
有效:a ?? b
的行为与a != nil ? a! : b
完全相同,正如文档所述。