从json初始化子类
我正在寻找一种保存任意子类的好方法 我在保存和加载时都在写对象。结构是具有不同类型的从json初始化子类,json,swift,inheritance,swift-protocols,Json,Swift,Inheritance,Swift Protocols,我正在寻找一种保存任意子类的好方法 我在保存和加载时都在写对象。结构是具有不同类型的单元的组s。组只知道它的单位是实现UnitProtocol的东西 Unit的子类UAetc具有与单元完全相同的数据。因此,在数据方面,asDictionary和init(json)非常适合单元。子类仅在逻辑上有所不同。所以当从文件中恢复它们时,我相信它必须是初始化的确切子类 (糟糕)我想到的解决方案 让每个组都知道它可以拥有不同子类的单元,方法是不将它们仅作为[UnitProtocol]保存,而是作为[UA],
单元的组
s。组
只知道它的单位是实现UnitProtocol
的东西
Unit
的子类UA
etc具有与单元完全相同的数据。因此,在数据方面,asDictionary
和init(json)
非常适合单元
。子类仅在逻辑上有所不同。所以当从文件中恢复它们时,我相信它必须是初始化的确切子类
(糟糕)我想到的解决方案
让每个组都知道它可以拥有不同子类的单元,方法是不将它们仅作为[UnitProtocol]
保存,而是作为[UA]
,[UB]
等保存,它们可以单独保存,由各自的子初始化还原,并在初始化时合并为[UnitProtocol]
使用子单元的类名存储子单元,并创建一个Unit.Init(json)
,它能够根据子类型传递初始化
???我仍在思考,但我相信我可以在这里学到一些东西,以一种可维护的方式做到这一点,而不违反单一责任政策
对于json中的init类,我使用了以下技术:
//For row in json
for row in json {
//namespace it use for init class
let namespace = (Bundle.main.infoDictionary!["CFBundleExecutable"] as! String).replacingOccurrences(of: " ", with: "_")
//create instance of your class
if let myClass = NSClassFromString("\(namespace).\(row.name)") as? NameProtocol.Type{
//init your class
let classInit : NameProtocol = myClass.init(myArgument: "Hey")
//classInit is up for use
}
}
对于json中的init类,我使用了以下技术:
//For row in json
for row in json {
//namespace it use for init class
let namespace = (Bundle.main.infoDictionary!["CFBundleExecutable"] as! String).replacingOccurrences(of: " ", with: "_")
//create instance of your class
if let myClass = NSClassFromString("\(namespace).\(row.name)") as? NameProtocol.Type{
//init your class
let classInit : NameProtocol = myClass.init(myArgument: "Hey")
//classInit is up for use
}
}
用它的类名存储每个单元json
func asDictionary() -> Dictionary<String, Any> {
let className = String(describing: type(of: self))
let d = Dictionary<String, Any>(
dictionaryLiteral:
("className", className),
("someUnitData", someUnitData),
// and so on, for all the data of Unit...
这里的诀窍是,将类unitSubclass
强制转换为UnitProtocol
,然后允许您调用其init(json)
,该协议中声明但在特定子类中实现,或者在其超类Unit
中实现,如果属性都相同。使用其类名存储每个单元json
func asDictionary() -> Dictionary<String, Any> {
let className = String(describing: type(of: self))
let d = Dictionary<String, Any>(
dictionaryLiteral:
("className", className),
("someUnitData", someUnitData),
// and so on, for all the data of Unit...
这里的诀窍是,将类unitSubclass
强制转换为UnitProtocol
,然后允许调用其init(json)
在该协议中声明但在特定子类中实现,或者在其超类Unit
中实现(如果属性都相同)。Ok,因此,使用这种技术,我会将名称空间和类名存储在单元json中?@JOG您只需要存储类名,例如:[{“name”:“MyClassA”,“init”:“Horus”},{“name”:“MyClassB”,“init”:“JOG”}]您能解释一下NameProtocol.键入解决方案的一部分吗?好的,因此,使用这种技术,我将在单元json中存储名称空间和类名?@JOG您只需要存储类名,例如:[{“name”:“MyClassA”,“init”:“Horus”},{“name”:“MyClassB”,“init”:“JOG”}]请您解释一下NameProtocol。键入解决方案的一部分?您是否有理由避免使用透明处理所有这些问题的NSKeyedArchiver
?如果JSON的唯一目标是保存和恢复对象,那么它似乎需要做大量的工作,但没有任何好处。我如何使用它?如果你的意思是“为什么使用json?”是因为当数据离开iOS并变得混浊时,我喜欢json。请注意,Swift 4将有一个更强大的解决方案。你看(但要过几个月左右才会有)我不知道你说的“多云”是什么意思。您真的需要将其发布到需要JSON的服务吗?(iCloud是一个“云”服务,完全不需要JSON即可工作。)您为什么要避免透明地处理所有这些问题的NSKeyedArchiver
?如果JSON的唯一目标是保存和恢复对象,那么它似乎需要做大量的工作,但没有任何好处。我如何使用它?如果你的意思是“为什么使用json?”是因为当数据离开iOS并变得混浊时,我喜欢json。请注意,Swift 4将有一个更强大的解决方案。你看(但要过几个月左右才会有)我不知道你说的“多云”是什么意思。您真的需要将其发布到需要JSON的服务吗?(iCloud是一个“云”服务,完全没有JSON就可以工作。)这非常非常危险。永远不要基于从API收到的数据创建类。这是一个非常典型的漏洞。您应该知道系统处理什么类。创建JSON名称到类型的字典。(如果不清楚,我会写一个例子。)千万不要对通过网络收到的东西调用NSClassFromString
。啊哈,你的意思是检查类名是否是我期望的类名之一?是的。否则,您可能会收到一些对您调用的方法做出响应的任意内容。这是Java世界中一个非常常见的漏洞(在Java世界中,从网络反序列化任意内容非常常见)。所以,我需要这样的东西来列出实现我的UnitProtocol的所有类,对吗?(还有一种使用“寄存器”的常见模式)方法更新字典,以便类可以注册自己。如果它们是NSObject
子类,则可以将其放入+load
中,它将在程序开始时自动运行。但这通常是过分的;同样,如果它非常复杂,您可能有太多的类。)这非常,非常危险。永远不要基于从API收到的数据创建类。这是一个非常典型的漏洞。您应该知道系统处理什么类。创建JSON名称到类型的字典。(如果不清楚,我会写一个例子。)千万不要对通过网络收到的东西调用NSClassFromString
。啊哈,你的意思是检查类名是否是我期望的类名之一?是的。否则,您可能会收到一些对您调用的方法做出响应的任意内容。这是Java世界中一个非常常见的漏洞(在Java世界中,从网络反序列化任意内容非常常见)。所以,我需要这样的东西来列出实现我的UnitProtocol的所有类,对吗