[英]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.