SwiftBondでつなげてプログラミング
山本たかし
自己紹介
もともとPHP/Javaエンジニア
↓
3ヶ月前から急遽iOSエンジニアに転向
facebook:
https://www.facebook.com/p.t.yamamoto
linkedIn: http://www.linkedin.com/pub/%E8%B2%B4%E5%A3%AB-%E5%B1%B1%E6%9C%AC/57/266/7ba
ソースについて
SwiftBondとは
https://github.com/SwiftBond/Bond
インストールはcocoapods が簡単
pod 'Bond', '~> 3.0'
‘->>’だけでつながる
self.textfield ->> self.label
‘<->> ‘と ‘->|’ もある
class ViewController: UIViewController,
UITextFieldDelegate {
@IBOutlet var textfield : UITextField
@IBOutlet var label : UILabel
override func viewDidLoad() {� super.viewDidLoad()�� self.textfield.addTarget(self
action:@selector(textFieldDidChange:)
forControlEvents:UIControlEventEditingChanged)� }
func textFieldDidChange(id:sender) {
self.label.text = self.textfield.text
}
}
class ViewController: UIViewController {
@IBOutlet var textfield : UITextField
@IBOutlet var label : UILabel
override func viewDidLoad() {� super.viewDidLoad()�� self.textfield ->> self.label� }
}
普通に実現する場合は、
textfieldの状態を監視する処理を入れる必要がある
つなぐ時に処理をはさむ
self.textField.dynText.map { "フィールドの値は " + $0 }
->> self.label
mapは何を返しても良い
let nameValid = name.dynText.map{countelements($0) > 6}
let passValid = pass.dynText.map{countelements($0) > 6}
loginButton.dynEnabled
= reduce(nameValid, passValid){$0 && $1}
reduce(name.dynText, pass.dynText) {� return countElements($0) > 6 && countElements($1) > 6�} ->> loginButton.dynEnabled
Dynamic型の処理は繋げて実行できる
number.filter { $0 > 10 }.map { "\($0)" } ->> label
肝は Dynamic<T>型
var myString:Dynamic<String>
myString ->> self.label
Dynamic型で使える関数型言語機能
func map<T, U>(dynamic: Dynamic<T>, f: T -> U) -> Dynamic<U>
Dynamic(配列)型を関数を使い他のDynamicに変換する
func filter<T>(dynamic: Dynamic<T>, f: T -> Bool) -> Dynamic<T>
Dynamic(配列)型を関数を使い条件に一致するものだけ取り出す
func reduce<A, B, T>(dA: Dynamic<A>, dB: Dynamic<B>, f: (A, B) -> T) -> Dynamic<T>
Dynamic(配列)型を関数を使い一つのDynamic型に集約する
配列の操作も便利
lazy var loginButtonTapListener = Bond<UIControlEvents>() { event in� // ログイン処理�}���loginButton.dynEvent.filter(==, .TouchUpInside) ->> loginButtonTapListener
TableにはUtilityクラス
self.tableViewDataSourceBond = UITableViewDataSourceBond(tableView: self.tableView)
self.news = DynamicArray([])
….
self.news.map { (entry: AnyObject) -> UITableViewCell in
let result:NSDictionary = entry as NSDictionary
let cell = (self.tableView.dequeueReusableCellWithIdentifier("cell") as? ListViewCell)!
let title:Dynamic<String> = Dynamic(result["title"] as String)
title ->> cell.label
return cell
} ->> self.tableViewDataSourceBond
cellForRowAtIndexPathとかnumbersOfRowinSectionとか必要なし!
Tableの状態を気にせず処理を書ける
どういう使い方が良いのか?
状態にごとに処理を書くのでなく、
データをつないで処理を書く。
状態がある → 条件分岐がある → バグの元
どうやって実装してるの?
class StepCounter {
var totalSteps: Int = 0 {
willSet(newTotalSteps) {
println("Step \(newTotalSteps) が追加されます! ")
}
didSet {
println(" \(oldValue) Stepが変更されました!)
println("今は \(totalSteps)")
}
}
}
propertyObsever 使ってます!