Swift中的动态协议一致性

问题描述 投票:0回答:1

你好,我正在努力解决swift语言中的动态协议一致性问题。请看代码。

协议。

protocol Object {

    init(by object: [String: Any])
}

自定义结构与协议对象一致性。

struct Tree: Object {

    let treeName: String

    init(by object: [String: Any]) {

        self.treeName = object["tree"] as? String ?? "Notree"
    }
}

struct Plant: Object {

    let plantName: String

    init(by object: [String : Any]) {

        self.plantName = object["tree"] as? String ?? ""
    }
}

上面的代码很好,直到对象是 [String: Any]. 我不能像下面那样使用[[String: Any]]。

let coconut = ["tree":"Coconut"] // => This fine
let allTrees = [["tree":"Apple"],["tree":"Orange"],["tree":"Jakfruit"]] //=> Here is the problem

 let aTree = Tree(by: coconut)
 let bTree = Tree(by: ["data":allTrees])
 let cTree = Plant(by: ["data":allTrees])

我不能使用对象的数组。所以,我曾经把对象存储在 "data "键中。现在我使用 extension: Array 确认协议对象。

extension Array: Object where Element == Object{

    init(by object: [String : Any]) {

        if let data = object["data"] as? [[String: Any]]{

            self  = data.map({ (object) -> Object in

//                return Plant.init(by: object) // => Works, But I need dynamic confirmance
//                return Tree.init(by: object) // => Works, But I need dynamic confirmance

                return Object.init(by: object) //=> How can I do?
            })
        }else{

            self = []
        }
    }
}

返回的 Object 显示错误 协议类型'对象'不能被实例化。. 我尝试了很多解决方法,但无法。

谁能提出更好的想法或解决这个问题的方法?先谢谢你...

swift swift3
1个回答
1
投票

首先,你不应该使用限制条件 == Object. 你想说,不仅 [Object] 是一个 Object但也 [Plant][Tree]Object的,对吗?为此,你应该使用 : Object 约束。其次,您可以使用 Element.init 来初始化一个新的 Element 的数组。由于约束条件 Element : Object我们知道,一个 init(by:) 存在初始化器。

extension Array: Object where Element: Object{

    init(by object: [String : Any]) {

        if let data = object["data"] as? [[String: Any]]{

            self  = data.map({ (object) in

                return Element.init(by: object)
            })
        }else{

            self = []
        }
    }
}

Usage:

let trees = [Tree](by: ["data": allTrees])

下面是我认为你的代码的一个更Swifty的版本,使用了 可失效初始化器 - 初始化器,返回 nil 当他们未能初始化对象时。

protocol Object {

    init?(by object: [String: Any])
}


struct Tree: Object {

    let treeName: String

    init?(by object: [String: Any]) {

        if let treeName = object["tree"] as? String {
            self.treeName = treeName
        } else {
            return nil
        }
    }
}

struct Plant: Object {

    let plantName: String

    init?(by object: [String : Any]) {

        if let plantName = object["tree"] as? String {
            self.plantName = plantName
        } else {
            return nil
        }
    }
}

extension Array: Object where Element: Object{

    init?(by object: [String : Any]) {

        if let data = object["data"] as? [[String: Any]]{
            self  = data.compactMap(Element.init)
        }else{
            return nil
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.