1 of 16

SwiftBondでつなげてプログラミング

山本たかし

2 of 16

自己紹介

もともと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

3 of 16

ソースについて

https://github.com/paul-yamamoto/BondExample/

https://github.com/paul-yamamoto/YahooRSS/

4 of 16

SwiftBondとは

  • UI部品を拡張して扱いやすくするライブラリ
  • TextField label などのデータをつないでくれる。
  • 関数型プログラミングをサポート

https://github.com/SwiftBond/Bond

インストールはcocoapods が簡単

pod 'Bond', '~> 3.0'

5 of 16

‘->>’だけでつながる

self.textfield ->> self.label

<->> ‘と ‘->|’ もある

6 of 16

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の状態を監視する処理を入れる必要がある

7 of 16

つなぐ時に処理をはさむ

self.textField.dynText.map { "フィールドの値は " + $0 }

->> self.label

8 of 16

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

9 of 16

Dynamic型の処理は繋げて実行できる

number.filter { $0 > 10 }.map { "\($0)" } ->> label

10 of 16

肝は Dynamic<T>型

var myString:Dynamic<String>

myString ->> self.label

11 of 16

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型に集約する

12 of 16

配列の操作も便利

lazy var loginButtonTapListener = Bond<UIControlEvents>() { event in� // ログイン処理�}���loginButton.dynEvent.filter(==, .TouchUpInside) ->> loginButtonTapListener

13 of 16

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の状態を気にせず処理を書ける

14 of 16

どういう使い方が良いのか?

状態にごとに処理を書くのでなく、

データをつないで処理を書く。

状態がある → 条件分岐がある → バグの元

15 of 16

どうやって実装してるの?

class StepCounter {

var totalSteps: Int = 0 {

willSet(newTotalSteps) {

println("Step \(newTotalSteps) が追加されます! ")

}

didSet {

println(" \(oldValue) Stepが変更されました!)

  println("今は \(totalSteps)")

}

}

}

propertyObsever 使ってます!

16 of 16

詳しくは