こんにちは。きんくまです。
Backbone.jsのModelとかCollectionをSwiftでも使いたいなと思って、機能限定だけど作ってみました。
JavaScriptのオリジナルのソースを見つつSwiftに書き直してみました。
学習目的で作ったものだと思ってくださいまし。
>> BBModel
作ったのは3つのクラスです。
Events, Model, Collection
サーバーとの通信、Collectionクラスのsortとwhereなどが抜けています。
インストール
3つのswiftクラスのファイルをコピペしてください。
iOS8 からはFrameworkでいれられるかも。
Events
on(イベント名)でコールバックが登録できます。
var event:Events = Events() event.on("myevent") { (events, options) -> Void in println("callback 1") } event.trigger("myevent") // callback 1
off(イベント名)でコールバックが全て削除できます。
またonで登録したときにクロージャのidを発行するので、それをとっておけばそのクロージャーだけを削除することができます。
あとクロージャ内でselfを使うものを登録するときは、メモリリークを防ぐため unowned self を使います。
>> Resolving Strong Reference Cycles for Closures
それと現状だと、あるEventsオブジェクトにonで登録した場合、そのオブジェクトを破棄する際には全てのコールバックを削除する必要があります。(ここはなんとかしたいですね、、)
off() で引数を省略すると全てのコールバックを削除できます。
var event:Events = Events() event.on("myevent") { (events, options) -> Void in println("callback 1") } event.trigger("myevent") // callback 1 let callbackId = event.on("myevent") { [unowned self] (events, options) -> Void in println("self \(self)") println("callback 2'") //optionsの中にこのcallbackのidが入っている let id = options["callbackId"] //それを使って内側からこのコールバックを削除することも可能 //event.off("myevent", callbackId:id) } event.on("myevent") { (events, options) -> Void in println("callback 3") } event.trigger("myevent") //callback 1, 2, 3 //remove callback 2 only event.off("myevent", callbackId: callbackId) event.trigger("myevent") //callback 1, 3 //remove all callbacks event.off("myevent") event.trigger("myevent") //no callback
Model
こんなModelのサブクラスを作ります
class Person: Model{ var name:String?{ get{ return self.get("name") as? String } set{ self.set("name", newValue!) } } var age:Int?{ get{ return self.get("age") as? Int } set{ self.set("age", newValue!) } } override init(attributes: [String : Any]?) { super.init(attributes: attributes) } init(name:String = "", age:Int = 0) { super.init() self.name = name self.age = age } }
実際に使ってみます。
//Modelのinitを使って var sato = Person(attributes: ["name":"Sato", "age":21]) //Personのinitを使って var tanaka = Person(name:"Tanaka", age:18) //Changeイベントに登録 tanaka.on(Model.Event.CHANGE) { (model, options) in let aTanaka = model as Person for (key, attr) in aTanaka.changedAttributes { println("tanaka changed key:\(key), value:\(attr)") println("tanaka previous value:\(aTanaka.previous(key))") } } //まとめて tanaka.set(["name":"Tanaka san", "age":24]) //1つだけ tanaka.set("name", "Tanaka dayo") println("--") //プロパティにアクセスして tanaka.name = "Super Tanaka" tanaka.age = 30 println("--") //イベント発行しないときは silent tanaka.set("name", "Special Tanaka", options:["silent": true])
Collection
Modelをまとめて扱うためのクラスです。
こんな感じのCollectionがあったとして
class PersonCollection: Collection { override init(models: [Model]?, options: [String : Any]?) { super.init(models: models, options: options) //Modelクラス登録 self.model = Person.self } }
実際に使ってみます
var tanaka = Person(name:"Tanaka") var yamada = Person(name:"Yamada") var sato = Person(name:"sato") var personCollection = PersonCollection(models: nil, options: nil) //Addイベント登録 personCollection.on(Collection.Event.ADD) { (model, collection, options) in let p = model as Person println("Person \(p.name) is added") } //Removeイベント登録 personCollection.on(Collection.Event.REMOVE) { (model, collection, options) in let p = model as Person println("Person \(p.name) is removed") } //ひとつ personCollection.add(tanaka) //複数 personCollection.add([yamada, sato]) //ひとつ personCollection.remove(yamada) //複数 personCollection.remove([tanaka, sato]) println("collection length = \(personCollection.length)") // 0 personCollection.add([yamada, sato]) //setは差分で登録 //すでにあれば上書き、なければ登録、引数に入ってなければ削除 personCollection.set([tanaka, sato]) //そのほかのメソッド /* personCollection.pop() personCollection.push() personCollection.shift() personCollection.unshift() personCollection.at() personCollection.has() personCollection.indexOf() */
で、これを使ってTodoアプリを作ってみたので次回はそれを書いてみます。
あと、実際に書いてみた感想。
・swiftの文法的なところにいちいちひっかかっていたけど、書いていくうちに慣れてきた。
・JSのライブラリの中身をちゃんと見る機会がほとんどなかったので、ソースを読み解く勉強になった。
・読み解くことでドキュメントにしっかり書いてない挙動とかがわかった。stackoverflowとかいろんなところで、どうしてこの人はこんなにこのライブラリの使い方を知っているんだろう?と思うことがよくあったのだけど、たぶんソースを見てるってことですね。やっぱソース大事なんだなと思いました。
■ 自作iPhoneアプリ 好評発売中!
・フォルメモ - シンプルなフォルダつきメモ帳
・ジッピー電卓 - 消費税や割引もサクサク計算!
■ LINEスタンプ作りました!
毎日使える。とぼけたウサギ