2015-11-21 32 views
0

我正在尝试使用Swift(我很新),为我的数据模型创建一个干净的界面。这些模型支持Firebase(尽管这与实际问题最终无关)。我想要避免的是反复写入大量的setter/accessor锅炉板代码。Swift在数据模型中的动态属性(获取器/设置器)

例如:

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_data_instance.name来获取该名称,或者my_data_instance.name = "foo",并且名称将自动写入服务器。

这需要约10行代码的单个属性(其中会有很多)。赶快行动吧!一定会有更好的办法!


编辑:要清楚,我想避免需要编写大量样板代码越好。考虑像Mantle这样的库,其中仅定义@property就足以做你想做的一切。在我看来,任何超过一行的代码说I have an attribute called "name", handle it via Firebase是过分冗长。

+0

您可以使用Objective-C运行时的元编程功能在运行中大量添加属性。 –

回答

2

您可以使用Key-Value Observing来监视属性的更改。更多信息在Adopting Cocoa Design Patterns in Swift

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 
0

夫特提供称为属性观察者

var name: String { 
    didSet { 
    self.connection.childByAppendingPath("name").setValue(name) 
    } 
} 

该功能有被称为之前的值被改变的第二观察者willSet

注(从文件):

当你指定一个默认值到存储的属性,或初始化中设置该 初始值,该属性的值设置 直接,而不调用任何财产观察员。

+0

当然,但对于每个属性来说,这仍然是一个巨大的代码量。我们只是减少了几行。 –

+0

对不起,这是Swift中最短的解决方案。 – vadian

+0

在我的例子中,我使用了iVar,因为我不想让setter写回firebase。也就是说,当'load'完成时,你的代码是不是最终会调用'didSet'并因此为每次读取创建一个写入? –