我可以使用镜像为Swift对象属性设置值吗?

10

目前我可以使用Mirror类型来检查对象的变量。但是,我能否使用镜像设置我的变量值呢?或者还有其他纯Swift的方法吗?

例如,我想从JSON创建一个对象(一个Swift struct)。这是否可能而无需子类化NSObject并使用Objective-C函数?

2个回答

5

目前这是我所能做到的最好的翻译,但仍缺少将mirrorObject转换回其通用类型的步骤。FYI,这是使用SwiftyJSON。

func convertToObject<T>(json: JSON, genericObject: T) -> T {
    let mirroredObject = Mirror(reflecting: genericObject)

    for (_, var attr) in mirroredObject.children.enumerate() {
        if let propertyName = attr.label as String! {
            attr.value = json[propertyName]
            print(propertyName)
            print(attr.value)
        }
    }
    // Figure out how to convert back to object type...
}

4
“@Randex,难点在于找出如何将数据类型转换回对象类型。除非你想为每个创建的类型制作自定义扩展。在Swift 4中,有Decodable和Encodable。它们可以动态地完成这项工作。” - Sentry.co
这只是一个错误: 类型“Mirror.Children”(又名“AnyCollection <(label:Optional <String>,value:Any)>”)没有成员“enumerate”。 - Dustin
1
如果你将其枚举,它就能工作,但设置attr.value对对象属性值没有影响。 - Dustin

4

这是一个老问题,但答案对我来说不起作用。

我必须将我的Swift对象更改为NSObject才能使事情正常运行,并且具有动态属性。

在我的情况下,我使用了Marshal pod来反序列化数据。

 class MyClass: NSObject, Unmarshaling
  {
       // @objc dynamic make property available for NSObject
       @objc dynamic var myProperty: String?

       required init(object: MarshaledObject) throws {
          super.init()

          initUsingReflection(object: object)
        }

        func initUsingReflection(object: MarshaledObject) {
          let mirror = Mirror(reflecting: self)

          // we go through children
          for child in mirror.children {
            guard let key = child.label else {
              continue
            }

            // This line is here to get the value from json, in my case I already know the type I needed
            let myValue: String = try! object.value(for: key)

            // The trick is here, setValue only exist in NSObject and not in swift object.
            self.setValue(myValue, forKey: key)
          }
       }
  }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接