Swift 中的动态协议一致性
Dynamic protocol conformance in Swift
您好,我正在努力解决 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 = []
}
}
}
returnObject
显示错误无法实例化协议类型'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 版本的代码,使用 failable initialisers - return 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
}
}
}
您好,我正在努力解决 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 = []
}
}
}
returnObject
显示错误无法实例化协议类型'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 版本的代码,使用 failable initialisers - return 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
}
}
}