Swift数据模型中的动态属性(getter/setter)
我正在尝试使用Swift数据模型中的动态属性(getter/setter),swift,swift2,Swift,Swift2,我正在尝试使用Swift(这是我的新手)为我的数据模型创建一个干净的界面。这些模型得到了Firebase的支持(尽管这最终与实际问题无关)。我想要避免的是一遍又一遍地编写大量setter/accessor锅炉板代码 例如: class MyData { let connection: Firebase! private var _name: String? // internal storage, like an iVar in ObjC init(connection: Fir
Swift
(这是我的新手)为我的数据模型创建一个干净的界面。这些模型得到了Firebase的支持(尽管这最终与实际问题无关)。我想要避免的是一遍又一遍地编写大量setter/accessor锅炉板代码
例如:
class MyData {
let connection: Firebase!
private var _name: String? // internal storage, like an iVar in ObjC
init(connection: Firebase!) {
self.connection = connection
self.connection.observeEventType(.Value, withBlock: { snapshot in
_name = snapshot["name"]
}
}
var name: {
get {
return _name
}
set(name) {
// When the client sets the name, write it to Firebase
_name = name
self.connection.childByAppendingPath("name").setValue(name)
}
}
}
我肯定我在这方面犯了很多错误。其思想是在实例化实例时首先从服务器加载数据。随后,我们可以调用my\u data\u instance.name
来获取该名称,或者my\u data\u instance.name=“foo”
并将该名称自动写入服务器
对于单个属性(其中将有许多属性),这需要大约10行代码。坚果一定有更好的办法
编辑:为了清楚起见,我想避免编写尽可能多的锅炉铭牌代码。考虑一个库,例如“代码> Test< <代码>,这里只定义一个<代码>属性就足以满足您的需要。在我看来,任何超过一行代码的内容都过于冗长。
我有一个名为“name”的属性,通过Firebase处理它。Swift提供了名为property observer的功能
在更改值之前,还有第二个观察者将设置,称为
注(来自文件):
为存储的属性指定默认值或设置其
初始值在初始值设定项中,设置该属性的值
直接,无需致电任何财产观察员
您可以使用监视属性中的更改。更多信息请访问
<代码>导入基础
私有变量KVOContext=0
//您的类必须从NSObject继承
类MyData:NSObject{
私有出租房地产观察=[“名称”,“位置”]
动态变量名:String
动态变量位置:字符串
init(名称:String,位置:String){
self.name=名称
self.location=位置
super.init()
//添加要观察的属性
对于self.propertiesToObserve中的属性{
addObserver(self,forKeyPath:属性,选项:[.New,.Old],上下文:&KVOContext)
}
}
//只要观察到的属性发生更改,就会调用此方法
重写func observeValueForKeyPath(键路径:String?,对象对象的类型:AnyObject?,更改:[String:AnyObject]?,上下文:UnsafeMutablePointer){
如果let property=keyPath,
newValue=更改![NSKeyValueChangeNewKey],
oldValue=更改![NSKeyValueChangeOldKey]{
打印(“\(属性)从\(旧值)更改为\(新值)”)
//如果oldValue!=newValue,则写回Firebase
}
}
//移除自我作为自我的观察者
脱硝{
对于self.propertiesToObserve中的属性{
self.removeObserver(self,forKeyPath:property)
}
}
}
let data=MyData(名称:“John”,位置:“Chicago”)
data.name=“David”//print:姓名从John改为David
data.location=“纽约”//print:地点从芝加哥改为纽约
当然可以,但每个属性的代码量仍然很大。我们只减少了几行。很抱歉,这是Swift中最短的解决方案。在我的示例中,我使用了iVar,因为我不希望setter回写到firebase。也就是说,当load
完成时,您的代码是否会调用didSet
,从而为每次读取创建写操作?didSet
不是在init
方法中调用的,我用文档中的一段引用更新了答案,我可能需要在任何时间点从服务器加载数据,不仅仅是在init
中,为了同步,您可以使用Objective-C运行时的元编程功能来动态批量添加属性。
var name: String {
didSet {
self.connection.childByAppendingPath("name").setValue(name)
}
}
import Foundation
private var KVOContext = 0
// Your class must inherit from NSObject
class MyData : NSObject {
private let propertiesToObserve = ["name", "location"]
dynamic var name: String
dynamic var location: String
init(name: String, location: String) {
self.name = name
self.location = location
super.init()
// Add the properties that you want to observe
for property in self.propertiesToObserve {
self.addObserver(self, forKeyPath: property, options: [.New, .Old], context: &KVOContext)
}
}
// This method is called whenever an observed property is changed
override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
if let property = keyPath,
newValue = change![NSKeyValueChangeNewKey],
oldValue = change![NSKeyValueChangeOldKey] {
print("\(property) changed from \(oldValue) to \(newValue)")
// If oldValue != newValue, write back to Firebase
}
}
// Remove self as observer of self
deinit {
for property in self.propertiesToObserve {
self.removeObserver(self, forKeyPath: property)
}
}
}
let data = MyData(name: "John", location: "Chicago")
data.name = "David" // print: name changed from John to David
data.location = "New York" // print: location changed from Chicago to New York