Swift で Model を書いてみた (observer編)

  • 82
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

こちらのスライドでなるほどなるほどと思いつつ、なんとなく Swift で書いてみました

iOS/Androidアプリエンジニアが理解すべき「Model」の振る舞い(http://www.slideshare.net/mokemokechicken/iosandroidmodel)

Xcode6-Beta3 を使ってます

コード抜粋

ModelLocator.swift
class ModelLocator : NSObject {

    class var sharedInstance : ModelLocator {
        struct Singleton {
            static var instance = ModelLocator()
        }
        return Singleton.instance
    }

    var events = EventModel()

    init() {
        println("ModelLocator init!")
    }

    func getEvent() -> EventModel {
        return events
    }

    func setEvent(array:EventModel) -> EventModel {
        events = array
        return events
    }

}
EventModel.swift
class EventModel : NSObject {

    var resources = [EventData]()
    let atnd_url  = "http://api.atnd.org/events/?keyword=swift&format=json"

    func getResources() -> [EventData] {
        return resources
    }

    func requestAtndApi(){
        let manager = AFHTTPRequestOperationManager()
        manager.GET(
            self.atnd_url,
            parameters: nil,
            success: {
                (operation: AFHTTPRequestOperation!, responseObject: AnyObject!) in
                if let dict = responseObject as? NSDictionary{
                    if let events: NSArray = dict["events"] as? NSArray{
                        var tmp_objects = [EventData]()
                        for event in events{
                            tmp_objects += EventData(event: event as NSDictionary)
                        }
                        self.resources = tmp_objects
                    }
                }
            },
            failure: {
                (operation: AFHTTPRequestOperation!, error: NSError!) in
                println(error.localizedDescription)
            })
    }
}
EventData.swift
class EventData : NSObject {

    var title:String = ""
    var url:String   = ""

    init(event:NSDictionary) {
        super.init()
        self.setModel(event)
    }

    func setModel(event:NSDictionary){
        let title: AnyObject! = event["title"]
        let url: AnyObject!   = event["owner_twitter_img"]
        self.title = title.description
        self.url   = url.description
    }

}
HogeViewController.swift
ModelLocator.sharedInstance.getEvent().addObserver(self, forKeyPath: "resources", options: NSKeyValueObservingOptions(), context: nil)
ModelLocator.sharedInstance.getEvent().requestAtndApi()
HogeViewController.swift
...
override func observeValueForKeyPath(keyPath: String!, ofObject object: AnyObject!, change: [NSObject : AnyObject]!, context: UnsafePointer<()>) {
    events = ModelLocator.sharedInstance.getEvent().getResources() as NSArray
    self.tableView.reloadData()
}
...
override func viewDidDisappear(animated: Bool){
    ModelLocator.sharedInstance.getEvent().removeObserver(self, forKeyPath: "resources")
}
...

ぺたぺた

気をつける事

最初、EventModel で以下のような初期化をして、通知を手動で行っていたのですが、

...
var resources = NSMutableArray()
...
self.willChangeValueForKey("resources")
resouces.addObject(model)
self.didChangeValueForKey("resources")
...

Swift っぽい以下の書き方に変更したら resources に += model する度に通知が行われてしまっていたので、一旦 tmp_objects に格納するように変更しました

var resources = [EventData]()

へー

参考

Swift でシングルトン(http://qiita.com/1024jp/items/3a7bc437af3e79f74505)

デザインパターンもっと読みたい読みたい

マイナビニュース デザインパターンをObjective-Cで(http://news.mynavi.jp/column/objc/)