Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Speaker Deck
PRO
Sign in
Sign up for free
Building Fabric.app with ReactiveCocoa
Javier Soto
June 15, 2016
Programming
3
1k
Building Fabric.app with ReactiveCocoa
Overview of how the Fabric App was built by taking advantage of some of ReactiveCocoa's features.
Javier Soto
June 15, 2016
Tweet
Share
More Decks by Javier Soto
See All by Javier Soto
try! Swift Tokyo 2018: Optimizing Swift code for separation of concerns and simplicity
javisoto
9
76k
Rubik's Cubes and Genetic Algorithms In Swift
javisoto
1
690
NSSpain 2016: Building Fabric.app in Swift
javisoto
4
650
Swift User Group - April 2016: Building Fabric.app in Swift
javisoto
4
24k
Swift Summit San Francisco October 2015
javisoto
4
1.1k
iOS Conf Singapore October 2015
javisoto
0
490
NSMeetup San Francisco July 2015
javisoto
3
630
RAC3, A Real World Use Case (aka ReactiveChess)
javisoto
0
410
Back to the Futures
javisoto
4
13k
Other Decks in Programming
See All in Programming
SwiftUI+TCAに挑戦!NewsPicks iOSアプリのリアーキテクチャ/re-architecture-newspicks-ios-app-with-swiftui-and-tca
takehilo
0
400
実践 SpiceDB - クライドネイティブ時代をサバイブできるパーミッション管理の実装を目指して / Practical SpiceDB
lmt_swallow
0
130
10歳の minne から、これから長く続くプロダクトを作るすべての人へ
tsumichan
9
3.6k
More Than Micro Frontends: 3 Further Use Cases for Module Federation @DWX 2022
manfredsteyer
PRO
0
370
ストア評価「2.4」だったCOCOARアプリを1年で「4.4」になんとかした方法@Cloud CIRCUS Meetup #2
1901drama
0
180
Computer Vision Seminar 1/コンピュータビジョンセミナーvol.1 OpenCV活用
fixstars
0
160
kintoneでランダム取得を作ってみた(imoniCamp 2022-07-27)
shokun1108
0
140
料理の注文メニューの3D化への挑戦
hideg
0
280
段階的な技術的負債の解消方法.pdf
ko2ic
2
920
Atomic Design とテストの○○な話
takfjp
2
800
ベストプラクティス・ドリフト
sssssssssssshhhhhhhhhh
1
210
Introduction to Property-Based Testing @ COSCUP 2022
cybai
1
150
Featured
See All Featured
How To Stay Up To Date on Web Technology
chriscoyier
780
250k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
119
28k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
655
120k
What’s in a name? Adding method to the madness
productmarketing
11
1.6k
Debugging Ruby Performance
tmm1
65
10k
10 Git Anti Patterns You Should be Aware of
lemiorhan
638
52k
Creatively Recalculating Your Daily Design Routine
revolveconf
207
10k
Thoughts on Productivity
jonyablonski
44
2.4k
5 minutes of I Can Smell Your CMS
philhawksworth
196
18k
Designing the Hi-DPI Web
ddemaree
272
32k
How to Ace a Technical Interview
jacobian
266
21k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
224
49k
Transcript
Building Fabric.app with Reac5veCocoa "Building Fabric.app with Reac6veCocoa" - Javier
Soto. RACDC2016 - April 2016 1
Intro @Javi "Building Fabric.app with Reac6veCocoa" - Javier Soto. RACDC2016
- April 2016 2
Outline • Intro • History • Contribu.ng to Reac.veCocoa •
Fabric App Architecture • RAC examples from Fabric App "Building Fabric.app with Reac6veCocoa" - Javier Soto. RACDC2016 - April 2016 3
Intro: What is Fabric.app? "Building Fabric.app with Reac6veCocoa" - Javier
Soto. RACDC2016 - April 2016 4
What is Fabric.app? "Building Fabric.app with Reac6veCocoa" - Javier Soto.
RACDC2016 - April 2016 5
History h"ps:/ /github.com/blog/1107-reac8vecocoa-for-a-be"er-world "Building Fabric.app with Reac6veCocoa" - Javier Soto.
RACDC2016 - April 2016 6
History • Reac&veCocoa 1: May 2012 (Objec&ve-C) • Reac&veCocoa 2:
September 2013 (Objec&ve-C) • Reac&veCocoa 3: September 2015 (Swi@ 1) • Reac&veCocoa 4: January 2016 (Swi@ 2) "Building Fabric.app with Reac6veCocoa" - Javier Soto. RACDC2016 - April 2016 7
"Building Fabric.app with Reac6veCocoa" - Javier Soto. RACDC2016 - April
2016 8
Contribu)ng to Reac)veCocoa "Building Fabric.app with Reac6veCocoa" - Javier Soto.
RACDC2016 - April 2016 9
Contribu)ng to Reac)veCocoa: Coding • Refactoring • New tests •
Proposing new operators • Compa5bility with new Swi; versions "Building Fabric.app with Reac6veCocoa" - Javier Soto. RACDC2016 - April 2016 10
Contribu)ng to Reac)veCocoa: Other ways! • Replying to issues •
Wri1ng / improving docs • Helping other users • Evangelizing "Building Fabric.app with Reac6veCocoa" - Javier Soto. RACDC2016 - April 2016 11
Fabric App Architecture "Building Fabric.app with Reac6veCocoa" - Javier Soto.
RACDC2016 - April 2016 12
Fabric App Architecture • FabricAPI.framework: • Networking • Models •
Fabric App: • View Controllers • View Models "Building Fabric.app with Reac6veCocoa" - Javier Soto. RACDC2016 - April 2016 13
Examples of Usage of Reac0veCocoa in the Fabric App "Building
Fabric.app with Reac6veCocoa" - Javier Soto. RACDC2016 - April 2016 14
Examples - Networking final class AuthenticatedFabricAPI { func applications() ->
SignalProducer<[Application], FabricAPIError> { return apiNetworking.requestJSONProducer( URL: APIURL(path: "api/v3/projects"), method: .GET ) .attemptMap(Application.decodeObjectsInJSON) .observeOn(UIScheduler()) } } "Building Fabric.app with Reac6veCocoa" - Javier Soto. RACDC2016 - April 2016 15
DataLoadState final class MyViewModel { var data: MyEntity? } "Building
Fabric.app with Reac6veCocoa" - Javier Soto. RACDC2016 - April 2016 16
DataLoadState enum DataLoadState<DataType> { case Loading case Failed case Loaded(DataType)
} "Building Fabric.app with Reac6veCocoa" - Javier Soto. RACDC2016 - April 2016 17
DataLoadState enum DataLoadState<DataType> { case Loading case Failed case Loaded(DataType)
} extension SignalProducerType { func materializeToLoadState() -> SignalProducer<DataLoadState<Value>, NoError> { let producer = self .map(DataLoadState.Loaded) .startWithValue(DataLoadState.Loading) return producer.ignoreErrors(replacementValue: DataLoadState<Value>.Failed) } } "Building Fabric.app with Reac6veCocoa" - Javier Soto. RACDC2016 - April 2016 18
extension SignalProducerType where Value: DataLoadState { func ignoreLoadingAndErrorsAfterSuccess() -> SignalProducer<DataLoadState<Value.DataType>,
Error> { var hasSuccededOnce = false return self.filter { value in defer { if value.success { hasSuccededOnce = true } } return !hasSuccededOnce || value.success } } "Building Fabric.app with Reac6veCocoa" - Javier Soto. RACDC2016 - April 2016 19
Examples - View Models typealias ApplicationLoadState = DataLoadState<[Application]> final class
ApplicationListViewModel { let applications: AnyProperty<ApplicationLoadState> private let applicationsMutableProperty = MutableProperty(ApplicationLoadState.loading()) init(fabricAPI: AuthenticatedFabricAPI) { self.applications = AnyProperty(self.applicationsMutableProperty) self.applicationsMutableProperty <~ fabricAPI.applications().materializeToLoadState() } } "Building Fabric.app with Reac6veCocoa" - Javier Soto. RACDC2016 - April 2016 20
Examples - Consuming Data From a View Model self.viewModel.applications.producer.startWithNext {
applicationsLoadState in switch applicationsLoadState { case .Loading: label.text = "Loading..." case .Failed: label.text = "Error loading applications!" case .Loaded(let applications): reloadTableView(applications: applications) } } "Building Fabric.app with Reac6veCocoa" - Javier Soto. RACDC2016 - April 2016 21
Reac%veCocoa Extensions "Building Fabric.app with Reac6veCocoa" - Javier Soto. RACDC2016
- April 2016 22
extension SignalProducerType { func startWithValue(value: Value) -> SignalProducer<Value, Error> {
return SignalProducer(value: value).concat(self.producer) } } "Building Fabric.app with Reac6veCocoa" - Javier Soto. RACDC2016 - April 2016 23
Reac%veCocoa Extensions extension SignalProducerType { func startWithNil() -> SignalProducer<Value?, Error>
{ return self .map(Optional.init) .startWithValue(nil) } "Building Fabric.app with Reac6veCocoa" - Javier Soto. RACDC2016 - April 2016 24
Reac%veCocoa Extensions extension SignalProducerType { func ignoreErrors( replacementValue replacementValue: Self.Value?
= nil ) -> SignalProducer<Value, NoError> { return self.flatMapError { _ in return replacementValue.map(SignalProducer.init) ?? .empty } } "Building Fabric.app with Reac6veCocoa" - Javier Soto. RACDC2016 - April 2016 25
Reac%veCocoa Extensions extension SignalProducerType { func failRandomly(withError error: Self.Error) ->
SignalProducer<Value, Error> { return self.attemptMap { value in let shouldFail = arc4random() % 3 == 0 return shouldFail ? Result(error: error) : Result(value: value) } } "Building Fabric.app with Reac6veCocoa" - Javier Soto. RACDC2016 - April 2016 26
Reac%veCocoa Extensions extension NSProcessInfo { var lowPowerModelEnabledProducer: SignalProducer<Bool, NoError> {
return NSNotificationCenter.defaultCenter() .rac_notifications(NSProcessInfoPowerStateDidChangeNotification, object: nil) .map { _ in return () } .startWithValue(()) .map { [unowned self] _ in return self.lowPowerModeEnabled } .skipRepeats(==) } } "Building Fabric.app with Reac6veCocoa" - Javier Soto. RACDC2016 - April 2016 27
Reac%veCocoa Extensions let shouldReload = combineLatest( viewIsOnScreen, NSProcessInfo.processInfo().lowPowerModelEnabledProducer.map { !$0
} ).map { $0 && $1 } let reloadPeriodically = shouldReload .flatMap(.Latest) { [unowned self] shouldReload in return shouldReload ? timer(30, onScheduler: scheduler).map { _ in () } : .empty } let request = reloadPeriodically.flatMap(.Latest) { someAPIRequest } "Building Fabric.app with Reac6veCocoa" - Javier Soto. RACDC2016 - April 2016 28
Reac%veCocoa Extensions extension SignalProducerType { func continueWhenApplicationIsBackgrounded( taskName taskName: String,
timeoutError: Self.Error ) -> SignalProducer<Value, Error> { } "Building Fabric.app with Reac6veCocoa" - Javier Soto. RACDC2016 - April 2016 29
Reac%veCocoa Extensions extension SignalProducerType { func repeatWith( producer: SignalProducer<(), NoError>,
throttleWithInterval: NSTimeInterval, onScheduler scheduler: DateSchedulerType ) -> SignalProducer<Value, Error> { return SignalProducer(value: ()).concat(producer) .throttle(throttleWithInterval, onScheduler: scheduler) .promoteErrors(Error) .flatMap(.Concat) { _ in return self.producer } } } "Building Fabric.app with Reac6veCocoa" - Javier Soto. RACDC2016 - April 2016 30
Reac%veCocoa Extensions self.api.request(parameterFoo: bar) .repeatWith( viewWillAppearProducer, throttleWithInterval: 60, onScheduler: QueueScheduler.mainQueueScheduler
) "Building Fabric.app with Reac6veCocoa" - Javier Soto. RACDC2016 - April 2016 31
Conclusion "Building Fabric.app with Reac6veCocoa" - Javier Soto. RACDC2016 -
April 2016 32
Ques%ons? "Building Fabric.app with Reac6veCocoa" - Javier Soto. RACDC2016 -
April 2016 33
Thank you! <3 ! See you next year! "Building Fabric.app
with Reac6veCocoa" - Javier Soto. RACDC2016 - April 2016 34