渋谷で引きこもってる社長です

株式会社Chotchy代表取締役 / エンジニア

ObserverPattern + RealmでモバイルMVCを試した

Swiftを始めて8か月ぐらいたちました。Swiftは割と現代のプログラミング言語のいいとこ取りをしてる感じがあり好きです。 そんな感じでそろそろSwift初心者から中級者に入っていけたらと思い、CocoaPodsでライブラリも公開しました。

github.com

是非使ってください!Starお願いします。

Observer PatternでModelを作る

最近、流行りのObserver PatternですがRXSwiftなどを使えば簡単にできます。が、僕なんかはそこまでやるほどでもないなというくらいの規模の時はこのやり方でいいと思います。 流れとしては、

  • シングルトンでModelを作成。Modelクラスのクラス変数にデータをもたせておく

  • ViewController(VC)がモデルからそのデータをゲッタによって取得

  • Modelクラスのデータに変更をVCから要求。変更が終わり次第変数の変更の通知を送る

  • VC側で変更を受け取りデータをModelから取得。UIに反映となります。

Model

import Foundation
import SwiftyJSON
import Alamofire

class KVOChannelFeedModel : NSObject {
    
    //外部クラスからの変更を許さないためprivateで宣言
    //監視の対象はdynamicで宣言。またその対象がNSObjectを継承している必要がある。
    private dynamic var channelList: [ChannelList] = []

    //singletonパターン
    class var sharedInstance: KVOChannelFeedModel {
        struct Singleton {
            static let instance: KVOChannelFeedModel = KVOChannelFeedModel()
        }
        return Singleton.instance
    }
    
    //privateであるためゲッタを設置。
    func getChannelData() -> [ChannelList]{
        return self.channelList
    }
    
    
    //変更。Post部分
    func channelUpdate(){
        let data = realm.objects(Channel)
        var list: [ChannelList] = []
        for r in data {
            let d = ChannelList()
            d.setFromRealmResult(r)
            list.append(d)
        }
        self.channelList = list
    }
    
}

Data構造

import Foundation
import RealmSwift

class ChannelList: NSObject{
    
    var channelId: Int!
    var name: String!
    var modified = NSDate()
    
    func setFromRealm(r: Channel){
        
        self.channelId = r.id
        self.name = r.name
        self.modified = r.modified
        
    }
    
}

ViewController側での処理

override func viewWillDisappear(animated: Bool) {
        super.viewWillDisappear(true)
        //忘れず回収
        KVOChannelFeedModel.sharedInstance.removeObserver(self, forKeyPath: "channelList")
    }
    
    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(true)
        UIApplication.sharedApplication().applicationIconBadgeNumber = 0
        
        //監視追加
        KVOChannelFeedModel.sharedInstance.addObserver(self, forKeyPath: "channelList", options: [.New], context: nil)
     }

override func viewDidLoad() {
        super.viewDidLoad()
        
        //Updateさせる部分。Modelで更新が始まる
        KVOChannelFeedModel.sharedInstance.channelUpdate()
}

//通知を受け取る場所
override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
        if keyPath == "feedChannelData"{

             //ゲッタを使って変更を取得
            self.channelData = KVOChannelFeedModel.sharedInstance.getChannelList()

            //tableViewなどはここでリロード
            self.tableView.reloadData()
        }
    }

といった感じです。

さっきから出てくるChannelという変数ですが、ここのアプリで使ったソースコードを使っています。まだまだβ版ですが読んだからにはダウンロードしてください。

また、Swiftで一緒に開発したいよ!って人、勉強したいよって人はここへ!

www.wantedly.com