Swift 2.0获取镜像超类属性

Exo*_*imp 4 inheritance mirror swift swift2

我需要将我的类的属性作为字典.为简单起见,我创建了一个具有默认实现的协议,如下所示:

protocol ListsProperties{
    func toDictionary() -> [String: AnyObject]
}

extension ListsProperties{
    func toDictionary() -> [String: AnyObject] {
        let mirrored_object = Mirror(reflecting: self)
        var dict = [String: AnyObject]()
        for (_, attr) in mirrored_object.children.enumerate() {
            if let propertyName = attr.label as String! {
                dict[propertyName] = attr.value as? AnyObject
            }
        }     

        return dict
    }
}
Run Code Online (Sandbox Code Playgroud)

我的类可以符合这个协议,并且可以使用toDictionary()方法.但是,如果我在子类上使用该方法,则这不起作用,因为它只会生成在子类上定义的属性并忽略父超类属性.

理想情况下,我可以找到一些方法来调用镜像超类上的toDictionary()方法,因为这会在它自己的超类上调用toDictionary(),并且编译器说超类镜像不符合协议,即使它正在镜像的类确实.

以下工作,但只有当只有一个超类时,这是不够的:

func toDictionary() -> [String: AnyObject] {
    let mirrored_object = Mirror(reflecting: self)
    var dict = [String: AnyObject]()
    for (_, attr) in mirrored_object.children.enumerate() {
        if let propertyName = attr.label as String! {
            dict[propertyName] = attr.value as? AnyObject
        }
    }

    // This is an issue as it limits to one subclass 'deep' 
    if let parent = mirrored_object.superclassMirror(){
        for (_, attr) in parent.children.enumerate() {
            if let propertyName = attr.label as String!{
                if dict[propertyName] == nil{
                    dict[propertyName] = attr.value as? AnyObject
                }
            }
        }
    }

    return dict
}
Run Code Online (Sandbox Code Playgroud)

关于如何修改toDictionary()的默认实现以包含超类属性(以及超类的任何超类的属性等)的任何想法?

Mar*_*n R 12

一种可能的解决方案是将其toDictionary() 作为Mirror自身的方法实现,以便您可以递归遍历到超类镜像:

extension Mirror {

    func toDictionary() -> [String: AnyObject] {
        var dict = [String: AnyObject]()

        // Properties of this instance:
        for attr in self.children {
            if let propertyName = attr.label {
                dict[propertyName] = attr.value as? AnyObject
            }
        } 

        // Add properties of superclass:
        if let parent = self.superclassMirror() {
            for (propertyName, value) in parent.toDictionary() {
                dict[propertyName] = value
            }
        }

        return dict
    }
}
Run Code Online (Sandbox Code Playgroud)

然后使用它来实现协议扩展方法:

extension ListsProperties {
    func toDictionary() -> [String: AnyObject] {
        return Mirror(reflecting: self).toDictionary()
    }
}
Run Code Online (Sandbox Code Playgroud)


sup*_*org 5

您可以简单地循环遍历所有superclassMirrors 来获取属性。有多少层并不重要。

var mirror: Mirror? = Mirror(reflecting: child) repeat { for property in mirror!.children { print("property: \(property)") } mirror = mirror?.superclassMirror() } while mirror != nil