let nickName: String? = nil
let fullName: String = "John Appleseed"
let informalGreeting = "Hi \(nickName ?? fullName)"
嗨约翰
let informalGreeting2 = "Hi \(fullName ?? nickName)"
你好可选(" John Appleseed")
我以为我理解第一个案例
let informalGreeting = "Hi \(nickName ?? fullName)"
nickName为nil,因此输出必须为" Hi \(fullName)" => "嗨John Appleseed"
在第二种情况下
let informalGreeting2 = "Hi \(fullName ?? nickName)"
第一个值fullName不是nil,因此输出应为" Hi \(fullName)" => "嗨John Appleseed"在我看来。
但是为什么输出是一个可选的包装输出,就像这里
一样你好可选(" John Appleseed")
答案 0 :(得分:4)
有两个??
运算符:
public func ??<T>(optional: T?, defaultValue: @autoclosure () throws -> T) rethrows -> T
public func ??<T>(optional: T?, defaultValue: @autoclosure () throws -> T?) rethrows -> T?
如果我们通过忽略第二个参数来简化声明 一个可能抛出autoclosure,我们得到
public func ??<T>(optional: T?, defaultValue: T) -> T // (1)
public func ??<T>(optional: T?, defaultValue: T?) -> T? // (2)
在nickName ?? fullName
中,第一个参数是可选的
第二个是非可选的,这意味着第一个变体是
使用,结果是非可选的:
nickName ?? fullName // (String? ?? String) -> String
如果nickName != nil
,那么结果就是解包(!)nickName
,
否则fullName
。
在fullName ?? nickName
中,第一个参数是非可选的
第二个是可选的。这与任何人都不匹配
功能声明。
编译器的作用是将第一个参数“包装”成一个 可选,以便进行编译(使用第二个变体)。 结果是可选的:
fullName ?? nickName // (String? ?? String?) -> String?
结果将始终为Optional(fullName)
。
在已编译的项目中,您还会收到警告
warning: left side of nil coalescing operator '??' has non-optional type 'String', so the right side is never used
第二个变体通常在链接nil-coalescing运算符时使用:
let result = optA ?? optB ?? optC ?? nonOptD
(2) (2) (1)
答案 1 :(得分:1)
问题是昵称是可选的,所以在第二种情况下,你告诉你如果fullname是nil print nickname,但昵称可以是nil,那么它将打印Hi Optional(“John Appleseed”),
使用时? 总是把它放在它之前是一个可选变量,但在它之后是一个非可选的字符串,它会正常工作。 希望这会有所帮助。