Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Functional Reactive Programming in Swift

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: http://mbltdev.ru
Sample code: https://github.com/AshFurrow/MBLTDev

Ash Furrow

October 28, 2014
Tweet

More Decks by Ash Furrow

Other Decks in Programming

Transcript

  1. 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
  2. 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
  3. 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))
  4. • 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
  5. 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
  6. Signals • Subscribe  to  a  signal  to  perform  side-­‐effects  when

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

    target.rac_valuesForKeyPath(keyPath, observer: target) } github.com/AshFurrow/Swift-RAC-Macros
  8. Signal Operators • Signal  operators  transform  the  values  sent  by

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

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

    in return (object as Person).name }.subscribeNext { (name) -> Void in println(“name: \(name)") }
  12. 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)") }
  13. someNumberSignal.filter { (object) -> Bool in return (object as NSNumber)

    > 5 }.subscribeNext { (object) -> Void in return "The number is \(object)" }
  14. 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
  15. 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
  16. 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
  17. Other Operators • combineLatest()   • takeUn'l()   • scheduleOn()

      • thro_le()   • not(),  and(),  or()
  18. 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
  19. 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
  20. 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?
  21. 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
  22. 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
  23. Getting Started • Start  slowly   • You’re  responsible  for

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