Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
104 views
in Technique[技术] by (71.8m points)

ios - Two (or more) optionals in Swift

While watching an Apple's video about LLDB debugger I found something I can't find an explanation for; he was talking about optional values when he wrote:

var optional: String? = nil; //This is ok, a common optional
var twice_optional: String?? = nil; //What is this and why's this useful??

I opened a playground and started trying it out and realized that you can write as many as ? as you want, and then unwrap them with the same number of !. I understand the concept of wrapping/unwrapping a variable but can't think of a situation where I would like to wrap a value 4, 5 or 6 times.

Question&Answers:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

(Updated for Swift >=3)

"Double optionals" can be useful, and the Swift blog entry "Optionals Case Study: valuesForKeys" describes an application.

Here is a simplified example:

let dict : [String : String?] = ["a" : "foo" , "b" : nil]

is a dictionary with optional strings as values. Therefore

let val = dict[key]

has the type String?? aka Optional<Optional<String>>. It is .none (or nil) if the key is not present in the dictionary, and .some(x) otherwise. In the second case, x is a String? aka Optional<String> and can be .none (or nil) or .some(s) where s is a String.

You can use nested optional binding to check for the various cases:

for key in ["a", "b", "c"] {

    let val = dict[key]
    if let x = val {
        if let s = x {
            print("(key): (s)")
        } else {
            print("(key): nil")
        }
    } else {
        print("(key): not present")
    }

}

Output:

a: foo
b: nil
c: not present

It might be instructive to see how the same can be achieved with pattern matching in a switch-statement:

let val = dict[key]
switch val {
case .some(.some(let s)):
    print("(key): (s)")
case .some(.none):
    print("(key): nil")
case .none:
    print("(key): not present")
}

or, using the x? pattern as a synonym for .some(x):

let val = dict[key]
switch val {
case let (s??):
    print("(key): (s)")
case let (s?):
    print("(key): nil")
case nil:
    print("(key): not present")
}

(I do not know a sensible application for more deeply nested optionals.)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...