使字典符合值类型协议

时间:2016-08-13 21:41:03

标签: swift

这是不编译的简化代码。反正有没有在Swift中完成这项工作?感谢。

protocol Person {

    var name:String { get }

    var age:Int { get }

}

extension Dictionary : Person {

    var name: String {

        return self["name"] as String

    }

    var age: Int {

        return self["Int"] as Int

    }

}

让我说一下我为什么要这样做的背景。

让我们说我有一些人的数据作为json进入线路。当我通过JSONSerialization传递它时,我得到了一个[String:AnyObject]字典。

所以我想在协议中声明JSON数据接口,使字典对象符合协议,然后通过类型属性从字典中提取值,而不是通过魔术字符串和强制转换。这样,客户端代码只会知道协议类型,即使它们被实现为幕后的字典。

不确定它是可行的还是一个好主意,只是想尝试一下。但编译器给我带来了各种各样的麻烦。

1 个答案:

答案 0 :(得分:0)

我知道你想要封装逻辑以将json链接到它的模型表示。

建议的解决方案

首先,我建议另一种方法来实现你想要的东西

看看这个结构。

struct Person {
    let name: String
    let age: Int

    init?(json: [String:Any]) {
        guard let name = json["name"] as? String, age = json["age"] as? Int else { return nil }
        self.name = name
        self.age = age
    }
}

从json中提取数据的逻辑被封装到其初始化器中。如果提供的json无效,则初始化失败。这是安全的,因为它永远不会崩溃,而且易于使用。

直接回答(不要在家里这样做!)

protocol Person {
    var name: String? { get }
    var age: Int? { get }
}

extension Dictionary : Person {
    private var dictWithStringKeys: [String:Any] {
        return reduce([String:Any]()) { (dict, elm) -> [String:Any] in
            var dict = dict
            if let key = elm.0 as? String {
                dict[key] = elm.1
            }
            return dict
        }
    }

    var name: String? {
        return dictWithStringKeys["name"] as? String
    }

    var age: Int? {
        return dictWithStringKeys["age"] as? Int
    }

}