簡體   English   中英

Swift 中的動態協議一致性

[英]Dynamic protocol conformance in Swift

嗨,我正在努力解決 swift 語言中的動態協議一致性問題。 請看代碼。

協議:

protocol Object {

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

具有協議 object 一致性的自定義結構:

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 ?? ""
    }
}

上面的代碼很好,直到 object 是[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])

我不能使用對象數組。 所以,我曾經將對象存儲到關鍵的“數據”中。 現在我使用了extension: Array Confirm protocol object。

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顯示錯誤協議類型“對象”無法實例化 我嘗試了很多解決但無法解決的問題。

有人可以為這個問題提出更好的想法或解決方案嗎? 先感謝您...

首先,您不應該使用約束== 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 = []
        }
    }
}

用法:

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

這是我認為您的代碼的更 Swifty 版本,它使用了可失敗的初始化程序- 當初始化 object 失敗時返回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
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM