Slide 1

Slide 1 text

Functional Reactive Programming in Swift Ash  Furrow

Slide 2

Slide 2 text

Agenda 1. Func'onal  reac've  programming  uses  a  concept  call  “signals”   2. Reac'veCocoa  uses  signals  to  reduce  mutable  state   3. Ge>ng  started  is  easy

Slide 3

Slide 3 text

Signals

Slide 4

Slide 4 text

Signals • At  the  core  of  FRP  are  signals   • Signals  send  values  over  'me,  un'l  they  complete  or  error  out   • A  signal  never  sends  anything  aGer  comple'ng  or  erring     • A  signal  either  completes,  or  errors  out,  but  never  both   • A  signal  has  no  concept  of  a  “current  value”  or  “past  values”   • It’s  like  a  pipe

Slide 5

Slide 5 text

Signals • Signals  can  be  chained  to  transform  the  values  that  they  send   • This  is  core  to  FRP:  data  transforma'on  of  values  sent  over  'me   • In  math  terms,  it’s  f(g(y))

Slide 6

Slide 6 text

ReactiveCocoa

Slide 7

Slide 7 text

No content

Slide 8

Slide 8 text

• Reac'veCocoa  is  a  framework  developed   by  GitHub   • Reac'veCocoa  is  an  implementa'on  of   FRP  on  iOS/OS  X   • It’s  currently  being  revamped  with  SwiG  to   version  3.0

Slide 9

Slide 9 text

Signals • Signals  are  typically  built  on  KVO   • They  can  also  be  created  manually   • Crea'ng  a  signal  is  easy   • RACObserve()   • Wraps  a  dynamic  property   • Sends  a  new  value  for  updated  property  values

Slide 10

Slide 10 text

Signals • Subscribe  to  a  signal  to  perform  side-­‐effects  when  it  sends  new  values   • Or  use  bindings  (later)

Slide 11

Slide 11 text

public func RACObserve(target: NSObject!, keyPath: String) -> RACSignal { return target.rac_valuesForKeyPath(keyPath, observer: target) } github.com/AshFurrow/Swift-RAC-Macros

Slide 12

Slide 12 text

let signal = RACObserve(object, "number") signal.subscribeNext { (number) -> Void in println("Received \(number)") }

Slide 13

Slide 13 text

Signal Operators • Signal  operators  transform  the  values  sent  by  signals   • These  are  func'ons  on  a  signal  that  return  a  new  signal

Slide 14

Slide 14 text

No content

Slide 15

Slide 15 text

Map • Mapping  performs  a  value  transforma'on  on  the  given  signal   • It  “maps”  each  value  sent  along  the  signal  to  a  new  value   • It  then  passes  that  new  value  along,  crea'ng  a  new  signal   • This  is  the  canonical  value  transforma'on

Slide 16

Slide 16 text

let signal = RACObserve(object, “number") signal.map { (number) -> AnyObject! in return "\(number)" }.subscribeNext { (string) -> Void in println("Received \(string)") }

Slide 17

Slide 17 text

let signal = RACObserve(object, “person") signal.map { (object) -> AnyObject! in return (object as Person).name }.subscribeNext { (name) -> Void in println(“name: \(name)") }

Slide 18

Slide 18 text

func toName(person: AnyObject!) -> AnyObject! { return (person as Person).name } let signal = RACObserve(object, “person") signal.map(toName).subscribeNext { (name) -> Void in println(“name: \(name)") }

Slide 19

Slide 19 text

Filter • Filtering  allows  values  that  pass  some  test  to  “pass  through”

Slide 20

Slide 20 text

someNumberSignal.filter { (object) -> Bool in return (object as NSNumber) > 5 }.subscribeNext { (object) -> Void in return "The number is \(object)" }

Slide 21

Slide 21 text

Bindings • Bindings  can  bind  a  property  to  the  latest  value  sent  on  a  signal   • Bindings  are  typically  created  with  the  RAC  func'on   • All  bindings  created  with  the  RAC  func'on  are  one-­‐way   • Bindings  are  the  secret  sauce  that  hold  apps  together

Slide 22

Slide 22 text

public struct RAC { var target: NSObject var keyPath: String var nilValue: AnyObject? public init(_ target: NSObject, _ keyPath: String, nilValue: AnyObject? = nil) { self.target = target self.keyPath = keyPath self.nilValue = nilValue } func assignSignal(signal : RACSignal) -> RACDisposable { return signal.setKeyPath(self.keyPath, onObject: self.target, nilValue: self.nilValue) } } infix operator <~ {} public func <~ (rac: RAC, signal: RACSignal) -> RACDisposable { return signal ~> rac } public func ~> (signal: RACSignal, rac: RAC) -> RACDisposable { return rac.assignSignal(signal) } github.com/AshFurrow/Swift-RAC-Macros

Slide 23

Slide 23 text

RAC(textField, "text") <~ RACObserve(self, "someString")

Slide 24

Slide 24 text

Derived State • State  is  avoided  in  Reac'veCocoa,  but  is  unavoidable  in  Cocoa   • Instead  of  hacky  workarounds,  we  derive  the  state  from  signals   • Similar  to  the  last  example’s  enabled  state  binding

Slide 25

Slide 25 text

Other Operators • combineLatest()   • takeUn'l()   • scheduleOn()   • thro_le()   • not(),  and(),  or()

Slide 26

Slide 26 text

Getting Started

Slide 27

Slide 27 text

Getting Started • Ge>ng  started  with  Reac'veCocoa  is  easy   • Install  Reac'veCocoa  in  your  project  as  a  submodule   • Switch  to  the  swiG-­‐development  branch

Slide 28

Slide 28 text

Getting Started • Start  by  replacing  KVO  methods  with  RACObserve   • Use  subscribeNext()  or  doNext()  for  side-­‐effects   • Start  looking  for  opportuni'es  to  replace  state  with  signals

Slide 29

Slide 29 text

Getting Started • When  create  a  property,  ask  yourself  if  a  signal  would  be  appropriate   • Is  it  important  to  know  the  value  of  the  property  aGer  it’s  set?   • Are  side-­‐effects  performed  when  it’s  changed?

Slide 30

Slide 30 text

Demo github.com/AshFurrow/MBLTDev

Slide 31

Slide 31 text

Demo • No'ce  subscribeNext:  is  used  for  side-­‐effects   • Cocoa  Touch  isn’t  built  on  FRP,  so  we  need  side-­‐effects   • Network  results  are  delivered  on  a  background  scheduler   • Use  deliverOn()  to  reschedule  them

Slide 32

Slide 32 text

github.com/artsy/eidolon

Slide 33

Slide 33 text

Eidolon • Completely  open  source  iOS  8  SwiG  app  wri_en  using  Reac'veCocoa   • Lots  of  examples  of  its  use   • Observing  model  proper'es   • User  interface  changes   • Networking  code   • S'll  a  work-­‐in-­‐progress

Slide 34

Slide 34 text

Getting Started • Start  slowly   • You’re  responsible  for  this  decision   • Be  prepared  to  answer  ques'ons   • There  is  a  community  to  support  you

Slide 35

Slide 35 text

Wrap Up 1. Func'onal  reac've  programming  uses  a  concept  call  “signals”   2. Reac'veCocoa  uses  signals  to  reduce  mutable  state   3. Ge>ng  started  is  easy

Slide 36

Slide 36 text

http://leanpub.com/iosfrp

Slide 37

Slide 37 text

@ashfurrow ashfurrow.com