如何从Swift中的可选类型获取解包类型?

时间:2015-12-06 08:54:32

标签: swift swift2

我试图在运行时从可选类型中获取一个解包类型。 以下代码将a的类型打印为Optional<String>

class MySubClass: MyClass {

    var a: String? = nil
}

var a = MySubClass()

let mirror = Mirror(reflecting: a)
for child in mirror.children {
    print(child.value.dynamicType)
}

现在我想打开类型并获取String,我该怎么做才能在运行时实现?

4 个答案:

答案 0 :(得分:2)

我玩了一点你的想法,但我认为没有真正的方法可以做到这一点,因为你无法获得枚举的相关值的类型。因此,Optionals基本上是Enumerations,我们在这里有一个问题。

我的想法是测试模型对象中可能存在或保持的所有可能的值类型。像:

let myModelObject:Any? = someWayToGetTheData()
if let aString = myModelObject as? String {
    // do everything you need to store a string
} 
else if let anInteger = myModelObject as? Int {
    // do everything you need to store an integer
} 

// and so on ...

由于您的json和您的模型必须具有预定义数量的受支持转换,这是可能的方式,并且就我理解您的原始问题而言,它基本上与测试可选枚举的动态关联值类型一样有用,这也将引入一系列if-else语句。

答案 1 :(得分:2)

假设您有一个可选

let someVar: String?

然后print(type(of: someVar))将打印

Optional<String>

但是如果您将以下扩展名添加到Optional

protocol OptionalProtocol {
 func wrappedType() -> Any.Type
}

extension Optional: OptionalProtocol {
 func wrappedType() -> Any.Type {
   return Wrapped.self
 }
}

然后print(someVar.wrappedType())将打印

String

完全没有反射


TL; DR

只要AnyAnyObject未引用该代码,代码就可以正常工作。

对于Any,您必须先将其强制转换为OptionalProtocol。正在运行

let someVar: String?
let anyVar = someVar as Any

if let op = anyVar as? OptionalProtocol {
    print(op.wrappedType())
}

将打印

String


至于AnyObject,奇怪的是(至少对我来说),它没有转换为OptionalProtocol


可以找到原始的StackOverflow答案here

答案 2 :(得分:0)

您可以使用爆炸(!)或if let明确展开可选项。

例如:

var foo: String? = nil
if foo == nil {
    print("foo is nil")
    foo = "bar"
}

let fooBang = foo!
print("fooBang: \(fooBang)")

if let ifLetFoo = foo {
    print("ifLetFoo: \(ifLetFoo)")
}

这将打印:

foo is nil
fooBang: bar
ifLetFoo: bar

在您的上下文中,我认为print(child.value.dynamicType!)可能是您正在寻找的内容。

答案 3 :(得分:0)

如果将值强制转换为非可选String,它将打印出未展开的类型。

let mirror = Mirror(reflecting: a)
for child in mirror.children {
    print(String(child.value).dynamicType) //String
}

或者您可以使用String并从Optional类型中获取类型。

class MySubClass: MyClass {

var a: Int? = nil
}

var a = MySubClass()

let mirror = Mirror(reflecting: a)
for child in mirror.children {
     let typeArr = String(child.value.dynamicType).characters.split{$0 == "<"}.map(String.init)
     let typeArr2 = typeArr[1].characters.split{$0 == ">"}.map(String.init)

      print(typeArr2[0]) // print: Int
 }

对不起,这很蹩脚,但你可以这样做。