Functional Reactive Programming in Swift

0ebf471a3ae8df42a84f93a7efbbdbd0?s=47 Ash Furrow
October 28, 2014

Functional Reactive Programming in Swift

Take a look at how functional reactive programming works using ReactiveCocoa and Swift. See how to use existing Objective-C APIs with Swift and examine common concepts in functional reactive programming like data transformation, filtering, and binding. Finally, get some resources for how to begin your journey to becoming a ReactiveCocoa expert.

Presented at MBLTDev:
Sample code:


Ash Furrow

October 28, 2014


  1. Functional Reactive Programming in Swift Ash  Furrow

  2. 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
  3. Signals

  4. 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
  5. 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))
  6. ReactiveCocoa

  7. None
  8. • 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
  9. 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
  10. Signals • Subscribe  to  a  signal  to  perform  side-­‐effects  when

     it  sends  new  values   • Or  use  bindings  (later)
  11. public func RACObserve(target: NSObject!, keyPath: String) -> RACSignal { return

    target.rac_valuesForKeyPath(keyPath, observer: target) }
  12. let signal = RACObserve(object, "number") signal.subscribeNext { (number) -> Void

    in println("Received \(number)") }
  13. Signal Operators • Signal  operators  transform  the  values  sent  by

     signals   • These  are  func'ons  on  a  signal  that  return  a  new  signal
  14. None
  15. 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
  16. let signal = RACObserve(object, “number") { (number) -> AnyObject!

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

    in return (object as Person).name }.subscribeNext { (name) -> Void in println(“name: \(name)") }
  18. func toName(person: AnyObject!) -> AnyObject! { return (person as Person).name

    } let signal = RACObserve(object, “person") { (name) -> Void in println(“name: \(name)") }
  19. Filter • Filtering  allows  values  that  pass  some  test  to

     “pass  through”
  20. someNumberSignal.filter { (object) -> Bool in return (object as NSNumber)

    > 5 }.subscribeNext { (object) -> Void in return "The number is \(object)" }
  21. 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
  22. public struct RAC { var target: NSObject var keyPath: String

    var nilValue: AnyObject? public init(_ target: NSObject, _ keyPath: String, nilValue: AnyObject? = nil) { = target self.keyPath = keyPath self.nilValue = nilValue } func assignSignal(signal : RACSignal) -> RACDisposable { return signal.setKeyPath(self.keyPath, onObject:, 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) }
  23. RAC(textField, "text") <~ RACObserve(self, "someString")

  24. 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
  25. Other Operators • combineLatest()   • takeUn'l()   • scheduleOn()

      • thro_le()   • not(),  and(),  or()
  26. Getting Started

  27. 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
  28. 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
  29. 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?
  30. Demo

  31. 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

  33. 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
  34. Getting Started • Start  slowly   • You’re  responsible  for

     this  decision   • Be  prepared  to  answer  ques'ons   • There  is  a  community  to  support  you
  35. 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

  37. @ashfurrow