Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

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

swift - How to unwrap an optional value from Any type?

Given an array of [Any] that has a mix of optional and non optional values, e.g:

let int:Int? = 1
let str:String? = "foo"

let values:[Any] = [int,2,str,"bar"]

How can we extract the value of the Optional in the Any type (if there is one) so we can create a generic print function that only prints out the values.

E.g. this printArray function goes through and prints each element:

func printArray(values:[Any]) {
    for i in 0..<values.count {
        println("value[(i)] = (values[i])")
    }
}

printArray(values)

Which will output:

value[0] = Optional(1)
value[1] = 2
value[2] = Optional("foo")
value[3] = bar

How can we change it so it only prints the underlying value so that it unwraps the value if it's Optional? e.g:

value[0] = 1
value[1] = 2
value[2] = foo
value[3] = bar

Update Progress...

It can work when changing the argument to [Any?], e.g:

let values:[Any?] = [int,2,str,"bar"]

func printArray(values:[Any?]) {
    for i in 0..<values.count {
        println("value[(i)] = (values[i]!)")
    }
}

printArray(values)

Which will print the desired:

value[0] = 1
value[1] = 2
value[2] = foo
value[3] = bar

But would still like to see how we can unwrap an Optional from Any as this is what MirrorType.value returns making it difficult to extract the Optional value, e.g:

class Person {
    var id:Int = 1
    var name:String?
}

var person = Person()
person.name = "foo"

var mt:MirrorType = reflect(person)
for i in 0 ..< mt.count {
    let (name, pt) = mt[i]
    println("(name) = (pt.value)")
}

Prints out:

id = 1
name = Optional("foo")

When I need:

id = 1
name = foo
Question&Answers:os

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

1 Reply

0 votes
by (71.8m points)

For Xcode 7 and Swift 2:

func unwrap(any:Any) -> Any {

    let mi = Mirror(reflecting: any)
    if mi.displayStyle != .Optional {
        return any
    }

    if mi.children.count == 0 { return NSNull() }
    let (_, some) = mi.children.first!
    return some

}


let int:Int? = 1
let str:String? = "foo"
let null:Any? = nil
let values:[Any] = [unwrap(int),2,unwrap(str),"bar", unwrap(null)]

This will give you [1, 2, "foo", "bar", {NSObject}]

Change NSNull() to nil and the return value of unwrap func to Any? will always unwrap any type.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...