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

ReactiveCocoa 4.1入門

ReactiveCocoa 4.1入門

881ccaf2edd00d9951f1cb8fe899d336?s=128

Nicholas Maccharoli

April 15, 2016
Tweet

Transcript

  1. REACTIVECOCOAೖ໳ Signals, SignalProducers and Events! Oh my!

  2. ࣗݾ঺հ Nicholas Maccharoli (χίϥεɾϚΧϩʔϦ) VASILYͰiOSΤϯδχΞΛ͍ͯ͠·͢ OSSͱ͔Swift Evolutionʹߩݙ͍ͯ͠·͢ ࠷ۙSwift Evolution SE-0053ΛఏҊͯ͠Swift3.0ʹ

    ࠾༻͞Ε·ͨ͠ʂ github.com/nirma @din0sr
  3. FRP(FUNCTIONAL REACTIVE PROGRAMMING) ͷϝϦοτ͸ʁ > ίʔυϊΠζ͕ݮΒͤ·͢ > @IBAction, NSNotificationCenter͓ΑͼCallback/ DelegateͷύλʔϯΑΓ΋ɺ΋ͬͱγϯϓϧ

    ͳ࣮૷͕Ͱ͖·͢ɻ
  4. ྫ: ϦϑϨογϡϘλϯͷΫϦοΫΠϕϯτ (Ұൠతͳ࣮૷) @IBAction func refreshButtonClicked(sender: AnyObject) { updateViewForState(.Loading) performNetworkRequest()

    { updateModel() dispatch_async(dispatch_get_main_queue()) { updateViewForState(.Success) } } }
  5. refreshButtonClicked:͕ݺ͹ΕͨΒ 1. ϘλϯͷදࣔΛߋ৽ 2. ϩʔσΟϯάΞΠίϯΛදࣔ 3. ωοτϫʔΫϦΫΤετ 4. ϦΫΤετ͕׬ྃͨ͠ΒCallbackͰUIͱϞσ ϧΛߋ৽͢Δ

  6. Ұͭͷϝιουͷதʹෳ਺ͷ੹೚ͷॲཧ͕ ݻ·͍ͬͯͯྑ͘ͳ͍ɻ γϯϓϧʹॻ͖׵͍͑ͨɻ

  7. ϧʔϓॲཧͩͱ͜ΜͳΠϝʔδ Before: var counter = 0 var animationImages = [UIImage]()

    while counter < 10 { let imageString = "animation_image_\(counter)" if let image = UIImage(named: imageString) { animationImages += [image] } }
  8. ϧʔϓॲཧͩͱ͜ΜͳΠϝʔδ After: (0..<10).flatMap { UIImage(named: "animation_image_\($0)") }

  9. RAC FTW!

  10. REACTIVECOCOAͱRXͷҧ͍ > Naming Convention > Rx: Hot Observable, Cold Observable

    > ReactiveCocoa: Signal, SignalProducer > Cocoaઐ༻API֦ு > ΑΓγϯϓϧͳઃܭ > etc
  11. None
  12. YES, SIGNALS! SignalͰΠϕϯτΛड͚औͬͯObserverͱ͔ DisposableͰSignalૢ࡞͕Ͱ͖·͢ɻ

  13. EVENTS... /// Signals must conform to the grammar: /// `Next*

    (Failed | Completed | Interrupted)?` public enum Event<Value, Error : ErrorType> { /// A value provided by the signal. case Next(Value) /// The signal terminated because of an error. No further events will be /// received. case Failed(Error) /// The signal successfully terminated. No further events will be received. case Completed /// Event production on the signal has been interrupted. No further events /// will be received. case Interrupted /// Whether this event indicates signal termination (i.e., that no further /// events will be received). }
  14. SIGNALS, CHEAP ৗʹൃੜ͠͏ΔΠϕϯτετϦʔϜ > UIίϯτϩʔϧ > APIϦΫΤετ > DB Read

    / Write > UINotificationCenter > ͳΜͰ΋
  15. SIGNAL࡞੒ͱ࢖͍ํ let (userNameTextSignal, observer) = Signal<String, NoError>.pipe() userNameTextSignal.observeNext { userName

    in print("Next Event: \(userName)") } observer.sendNext("l") // Next Event: l observer.sendNext("la") // NExt Event: la observer.sendNext("lat") // Next Event: lat observer.sendNext("latt") // Next Event: latn observer.sendNext("lattn") // Next Event: lattn observer.sendNext("lattne") // Next Event: lattne observer.sendNext("lattner") // Next Event: lattner observer.sendCompleted()
  16. SIGNAL'S FRIENDS MAP, FILTER, REDUCE RAC Marbles

  17. None
  18. None
  19. None
  20. None
  21. None
  22. None
  23. None
  24. SIGNAL OPERATORS IN ACTION - FILTER let (userNameTextSignal, observer) =

    Signal<String, NoError>.pipe() let improvedUserNameTextSignal = userNameTextSignal.filter { $0.characters.count > 4 } improvedUserNameTextSignal.observeNext { userName in print("Next Event: \(userName)") } observer.sendNext("lattn") observer.sendNext("lattne") observer.sendNext("lattner") observer.sendCompleted()
  25. طଘͷSIGNAL͔Β৽͍͠SIGNALΛ࡞Δ let (userNameTextSignal, observer) = Signal<String, NoError>.pipe() let userNameValidSignal =

    userNameTextSignal.map { return $0.characters.count > 5 } let backgroundColorSignal = userNameValidSignal.map { return $0 ? UIColor.greenColor() : UIColor.redColor() }
  26. SIGNALS & END OF LIFE swiftͷGeneratorTypeͱಉ͡Α͏ʹҰճSignal Λ࢖͍ऴΘͬͨΒ࠶ར༻Ͱ͖ͳ͍ɻ

  27. SIGNALPRODUCER (COLD SIGNALS) > SignalProducers ͸ Signal ͷϑΝΫτϦʔ > ߪಡ͠ͳ͍͔͗Γɺॲཧ͸։࢝͞Εͳ͍

    > Signal Operators can be 'Lifted'
  28. SIGNALPRODUCER - NOTHING var userNameProducer = SignalProducer<String, NoError> { (observer,

    disposable) in ["foo", "bar", "zap", "bin", "fizz"].forEach { userName in print("Sending Username: \(userName)") observer.sendNext(userName) } }
  29. SIGNALPRODUCER - SOMETHING var userNameProducer = SignalProducer<String, NoError> { (observer,

    disposable) in ["foo", "bar", "zap", "bin", "fizz"].forEach { userName in print("Sending Username: \(userName)") observer.sendNext(userName) } } userNameProducer.startWithNext { userName in print("Received Username: \(userName)") }
  30. OUTPUT Sending Username: foo Received Username: foo Sending Username: bar

    Received Username: bar Sending Username: zap Received Username: zap Sending Username: bin Received Username: bin Sending Username: fizz Received Username: fizz
  31. SIGNALPRODUCER - SIGNALPRODUCER͔ΒSIGNALPRODUCER࡞ Δ var userNameProducer = SignalProducer<String, NoError> {

    (observer, disposable) in ["foo", "bar", "zap", "bin", "fizz"].forEach { userName in print("Sending Username: \(userName)") observer.sendNext(userName) } } userNameProducer.startWithNext { userName in print("Received Username: \(userName)") } let zCounterSignal = userNameProducer.map { $0.containsString("z") } zCounterSignal.startWithNext { if $0 { print("Contains z!") } else { print("No z here.") } }
  32. OUTPUT No z here. No z here. Contains z! No

    z here. Contains z!
  33. RAC4.0ͷAPIมߋ > Based on Swift 2.0 > RACSignal͕ͳ͘ͳΓ·ͨ͠ (This is

    a lie.) > RAC3.0͔ΒRACSignal (HOT, COLD) ͕ Signal, SignalProducerʹมߋ > Global Functions Protocol Extensions > |>(Pipe-Left)͸ී௨ͷ.(Dot Operator)ʹมߋ
  34. ·ͱΊ > RAC4͸͍͍FRPϥΠϒϥϦͱͯ͠ઃܭ͕ྑ͍ > ίϛϡχςΟ͕ϔϧγʔͰਐԽ΋ૣ͍͚ Ͳɺ·ͩϨΨγʔίʔυ͕࢒͍ͬͯΔͷ Ͱ'5/5'Λ্͛ΒΕͳ͍Ͱ͢ > Cocoa֦ு͸ศར͚ͩͲɺϥΠϒϥϦΛං େԽ͍ͤͯ͞Δ