Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Hello, ReactorKit ๐
Search
Suyeol Jeon
June 28, 2018
Programming
120
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Hello, ReactorKitย ๐
https://www.slideshare.net/devxoul/hello-reactorkit
Suyeol Jeon
June 28, 2018
More Decks by Suyeol Jeon
See All by Suyeol Jeon
แแ ฅแผแแ กแผแแ กแแ ณแซ iOS แแ ขแแ กแฏแแ ก แแ ฌแแ ต
devxoul
2
260
แ แ ฆแแ ฅแแ ต แแ ณแ แ ฉแแ ฆแจแแ ณแแ ฆแแ ฅ แแ ดแแ ฉแซแแ ฅแผ แแ ฎแแ ตแธแแ กแแ ต
devxoul
1
2.6k
Let's TDD
devxoul
0
110
Build Funnels with Google BigQuery
devxoul
0
63
RxSwift แแ ตแแ กแจแแ กแแ ต
devxoul
1
370
ReactorKit์ผ๋ก ๋จ๋ฐฉํฅ ๋ฐ์ํ ์ฑ ๋ง๋ค๊ธฐ
devxoul
0
190
Swift - ํผ์ ๊ณต๋ถํ๋ฉด ๋ถ๋ช ํ ์ํ ํ ๋๊น ๊ฐ์ด ๊ณต๋ถํ๊ธฐ
devxoul
10
3.3k
แแ ฉแแแ ณแซ แแ ตแแ กแแ ตแแ ฅ, แแ กแแ ณแซ แแ ณแ แ ฉแแ ฆแจแแ ณแแ ขแแ ตแแ ฅ, แแ ตแแ กแผแแ กแซ แแ ขแแ กแฏแแ ก
devxoul
0
130
Other Decks in Programming
See All in Programming
TSX ใฎ <Hoge<Fuga>> ใจใใๆงๆใซ้ฉใใ่ฉฑ / tsx-type-argument-syntax
kanaru0928
0
160
ใณใผใใฃใณใฐใซใผใซใฎ้ฎฎๅบฆใไฟใกใใ for SRE NEXT 2026 / keep-fresh-go-internal-conventions-sre-next-2026
handlename
0
160
ไฝฟใใชใใ่ฒใฆใ Claude Code โ ้็บใใญใผใฎ1ใณใใณใๅ ร ็นฐใ่ฟใๆๆใฎ่ชๅไป็ตใฟๅ
shiki_kakaku
0
1.5k
ใใๅๅนดใใใใงAIใซไฝใใใR็จใใผใซ
eitsupi
0
350
ใใชใใใ็ตถๅฏพใซ่จฑใใชใ๏ผ๏ผ๏ผCDK้็จ / CDK Ops with Zero Tolerance for Drifts (?)
akihisaikeda
1
140
20260722_microCMSใง่ใใใAIๆไปฃใฎใณใณใใณใ้็จ่จญ่จ
yosh1
0
190
ใๅฏใฆใฆใไปไบใ้ฒใใClaude Codeใง็ตใ็ฌฌไบใฎ่ณ
tomoyafujita2016
0
240
Haskell/Servantใ้ใใฆWebใใใซใฆใงใขใๆใ็ดใ
pizzacat83
1
630
What's New in Android 2026
veronikapj
0
240
FDEใๅฎ็พใใAI้งๅ็ตๅถใฎ็พๅจๅฐ
gonta
2
240
AWS CDK ใใไฝใใฃใฆใฟใ ใใใซในใฏใฉใใใง่ฆใใ CDK ใฎ่ฃๅดใ / aws-cdk-from-scratch
gotok365
3
2.7k
ๅฃใใใใผใตใใๅงใใ้ขๆฐๅ่จญ่จใจๆงๆ็ใชใใผใต #fp_matsuri
raiga0310
2
420
Featured
See All Featured
Building the Perfect Custom Keyboard
takai
2
820
Mozcon NYC 2025: Stop Losing SEO Traffic
samtorres
1
450
Build The Right Thing And Hit Your Dates
maggiecrowley
39
3.4k
Agile that works and the tools we love
rasmusluckow
331
22k
Why Your Marketing Sucks and What You Can Do About It - Sophie Logan
marketingsoph
0
340
ไธ็ใฎไบบๆฐใขใใช100ๅใๅๆใใฆ่ฆใใใใคใฆใฉใผใซ่จญ่จใฎๅฟๅพ
akihiro_kokubo
PRO
72
41k
Pawsitive SEO: Lessons from My Dog (and Many Mistakes) on Thriving as a Consultant in the Age of AI
davidcarrasco
0
200
Code Reviewing Like a Champion
maltzj
528
40k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
16
2.1k
Large-scale JavaScript Application Architecture
addyosmani
515
110k
Become a Pro
speakerdeck
PRO
31
6k
First, design no harm
axbom
PRO
2
1.2k
Transcript
Hello, ReactorKit! Suyeol Jeon https://github.com/devxoul
Jeon Suyeol StyleShare Inc. Open Source Lover Then URLNavigator RxSwift
ObjectMapper
Why?
Why? Massive View Controller
Why? Massive View Controller RxSwift State Managing
Massive View Controller https://developer.apple.com/library/archive/documentation/General/Conceptual/DevPedia-CocoaCore/MVC.html
Massive View Controller https://developer.apple.com/library/archive/documentation/General/Conceptual/DevPedia-CocoaCore/MVC.html
Massive View Controller https://developer.apple.com/library/archive/documentation/General/Conceptual/DevPedia-CocoaCore/MVC.html
RxSwift State Managing Cyclic Data Dependencies
RxSwift State Managing currentValue increaseValue()
RxSwift State Managing currentValue increaseValue() last state
RxSwift State Managing currentValue increaseValue() last state result
RxSwift State Managing Cyclic Data Dependencies
RxSwift State Managing Cyclic Data Dependencies Pagination List operation Value
update ...
RxSwift State Managing After a while...
RxSwift State Managing After a while... Variable<Int> PublishSubject<Int> PublishRelay<[Item]> Variable<User>
BehaviorSubject<String> Variable<String>
I wanted to... 1. Avoid Massive View Controller
I wanted to... 1. Avoid Massive View Controller 2. Take
advantages of RxSwift
I wanted to... 1. Avoid Massive View Controller 2. Take
advantages of RxSwift 3. Manage states gracefully
ReactorKit
ReactorKit can... 1. Avoid Massive View Controller โ
ReactorKit can... 1. Avoid Massive View Controller โ Separates responsibilities
of view and logic
ReactorKit can... 1. Avoid Massive View Controller โ Separates responsibilities
of view and logic View Controller becomes simple
ReactorKit can... 2. Take advantages of RxSwift โ
ReactorKit can... 2. Take advantages of RxSwift โ Based on
RxSwift
ReactorKit can... 2. Take advantages of RxSwift โ Based on
RxSwift All of RxSwift features are available
ReactorKit can... 3. Manage states gracefully โ
ReactorKit can... 3. Manage states gracefully โ Unidirectional data flow
ReactorKit can... 3. Manage states gracefully โ Unidirectional data flow
Modify states only in reduce()
ReactorKit can... 3. Manage states gracefully โ Unidirectional data flow
Modify states only in reduce() State management became easy
ReactorKit can... Be the future ~1.1K โญ ~50K downloads ~900
apps https://starcharts.herokuapp.com/ReactorKit/ReactorKit
ReactorKit can... Be the future ~1.1K โญ ~50K downloads ~900
apps https://starcharts.herokuapp.com/ReactorKit/ReactorKit
Basic Concept
Basic Concept Abstraction of User Interaction Abstraction of View State
Basic Concept Renders view states Handles user interactions ViewController, Cell,
...
Basic Concept protocol View { associatedtype Reactor var disposeBag: DisposeBag
// gets called when // self.reactor is changed func bind(reactor: Reactor) }
Basic Concept protocol StoryboardView { associatedtype Reactor var disposeBag: DisposeBag
// gets called when // the view is loaded func bind(reactor: Reactor) } // for Storyboard support
Basic Concept Performs business logic Manages states Corresponds to view
Basic Concept protocol Reactor { associatedtype Action associatedtype Mutation associatedtype
State var initialState: State }
Basic Concept Based on RxSwift
Data Flow
Data Flow
Data Flow Action โ State โ
Data Flow Action โ Mutation โ State
Data Flow Action โ Mutation โ State State manipulator
Data Flow State manipulator Async-able Action โ Mutation โ State
Data Flow State manipulator Async-able Not exposed to view Action
โ Mutation โ State
Data Flow (Action) -> Observable<Mutation> (State, Mutation) -> State
Data Flow
Data Flow class ProfileViewReactor: Reactor { enum Action { }
struct State { } }
Data Flow class ProfileViewReactor: Reactor { enum Action { case
follow // user interaction } struct State { } }
Data Flow class ProfileViewReactor: Reactor { enum Action { case
follow // user interaction } struct State { var isFollowing: Bool // view state } }
Data Flow class ProfileViewReactor: Reactor { enum Action { case
follow // user interaction } struct State { var isFollowing: Bool // view state } } Execute user follow API โ Change state
Data Flow class ProfileViewReactor: Reactor { enum Action { case
follow // user interaction } struct State { var isFollowing: Bool // view state } } Execute user follow API โ Change state Async
Data Flow class ProfileViewReactor: Reactor { enum Action { case
follow // user interaction } enum Mutation { } struct State { var isFollowing: Bool // view state } }
Data Flow class ProfileViewReactor: Reactor { enum Action { case
follow // user interaction } enum Mutation { case setFollowing(Bool) // change state } struct State { var isFollowing: Bool // view state } }
Data Flow
Data Flow Tap follow button
Data Flow Action.follow
Data Flow Action.follow
Data Flow UserService.follow()
Data Flow UserService
Data Flow Observable<Bool>
Data Flow
Data Flow Mutation.setFollowing(true)
Data Flow Mutation.setFollowing(true)
Data Flow isFollowing = true
Data Flow Update follow button
Data Flow
More Examples
More Examples
Advanced View Communications Testing View and Reactor
View Communications ProfileViewController ProfileViewReactor
View Communications UICollectionView ProfileViewController ProfileViewReactor
View Communications UICollectionView ProfileViewController ProfileViewReactor UserCell
View Communications Passing user data Observing button tap
View Communications - Passing user data ProfileView Controller UserCell ProfileView
Reactor
View Communications - Passing user data ProfileView Controller UserCell ProfileView
Reactor 1. User
View Communications - Passing user data ProfileView Controller UserCell ProfileView
Reactor 1. User 2. User
View Communications - Passing user data // ProfileViewReactor struct State
{ }
View Communications - Passing user data // ProfileViewReactor struct State
{ var user: User? }
View Communications - Passing user data // ProfileViewReactor struct State
{ var user: User? } // ProfileViewController let cell = collectionView.dequeue... return cell
View Communications - Passing user data // ProfileViewReactor struct State
{ var user: User? } // ProfileViewController let cell = collectionView.dequeue... if let reactor = self.reactor { } return cell
View Communications - Passing user data // ProfileViewReactor struct State
{ var user: User? } // ProfileViewController let cell = collectionView.dequeue... if let reactor = self.reactor { cell.user = reactor.currentState.user } return cell
View Communications - Observing button tap ProfileView Controller UserCell ProfileView
Reactor
View Communications - Observing button tap ProfileView Controller UserCell ProfileView
Reactor 1. rx.tap
View Communications - Observing button tap ProfileView Controller UserCell ProfileView
Reactor 2. Action.follow 1. rx.tap
View Communications - Observing button tap ProfileView Controller UserCell ProfileView
Reactor 2. Action.follow 1. rx.tap Reactive Extension
View Communications - Observing button tap // UserCell extension Reactive
where Base: UserCell { }
View Communications - Observing button tap // UserCell extension Reactive
where Base: UserCell { var buttonTap: ControlEvent<Void> { } }
View Communications - Observing button tap // UserCell extension Reactive
where Base: UserCell { var buttonTap: ControlEvent<Void> { return self.base.followButton.rx.tap } }
View Communications - Observing button tap // UserCell extension Reactive
where Base: UserCell { var buttonTap: ControlEvent<Void> { return self.base.followButton.rx.tap } } // ProfileViewController cell.user = reactor.currentState.user
View Communications - Observing button tap // UserCell extension Reactive
where Base: UserCell { var buttonTap: ControlEvent<Void> { return self.base.followButton.rx.tap } } // ProfileViewController cell.user = reactor.currentState.user cell.rx.buttonTap
View Communications - Observing button tap // UserCell extension Reactive
where Base: UserCell { var tap: ControlEvent<Void> { return self.base.followButton.rx.tap } } // ProfileViewController cell.user = reactor.currentState.user cell.rx.buttonTap .map { Reactor.Action.follow }
View Communications - Observing button tap // UserCell extension Reactive
where Base: UserCell { var tap: ControlEvent<Void> { return self.base.followButton.rx.tap } } // ProfileViewController cell.user = reactor.currentState.user cell.rx.buttonTap .map { Reactor.Action.follow } .bind(to: reactor.action)
View Communications - Observing button tap // UserCell extension Reactive
where Base: UserCell { var tap: ControlEvent<Void> { return self.base.followButton.rx.tap } } // ProfileViewController cell.user = reactor.currentState.user cell.rx.buttonTap .map { Reactor.Action.follow } .bind(to: reactor.action) .disposed(by: self.disposeBag)
View Communications UICollectionView ProfileViewController ProfileViewReactor UserCell
View Communications UICollectionView ProfileViewController ProfileViewReactor UserCell UserCellReactor
View Communications - Passing user data ProfileView Controller UserCell ProfileView
Reactor
View Communications - Passing user data ProfileView Controller UserCell ProfileView
Reactor UserCell Reactor
View Communications - Passing user data ProfileView Controller UserCell ProfileView
Reactor 1. CellReactor UserCell Reactor
View Communications - Passing user data ProfileView Controller UserCell ProfileView
Reactor 1. CellReactor 2. CellReactor UserCell Reactor
View Communications - Passing user data ProfileView Controller UserCell ProfileView
Reactor 1. CellReactor 2. CellReactor UserCell Reactor
View Communications - Passing user data // ProfileViewReactor struct State
{ var user: User? }
View Communications - Passing user data // ProfileViewReactor struct State
{ var user: User? var userCellReactor: UserCellReactor? }
View Communications - Passing user data // ProfileViewReactor struct State
{ var user: User? var userCellReactor: UserCellReactor? } // ProfileViewController cell.user = reactor.currentState.user
View Communications - Passing user data // ProfileViewReactor struct State
{ var user: User? var userCellReactor: UserCellReactor? } // ProfileViewController cell.user = reactor.currentState.user cell.reactor = reactor.currentState.userCellReactor
Testing View and Reactor What to test? View Reactor
Testing View and Reactor What to test? View Action: on
user interaction โ action sent? Reactor
Testing View and Reactor What to test? View Action: on
user interaction โ action sent? State: on state change โ view updated? Reactor
Testing View and Reactor What to test? View Action: on
user interaction โ action sent? State: on state change โ view updated? Reactor State: on action receive โ state updated?
Testing View and Reactor How to test?
Testing View and Reactor How to test? Reactor.stub()
Testing View and Reactor How to test? Reactor.stub() state: set
fake state
Testing View and Reactor How to test? Reactor.stub() state: set
fake state action: send fake action
Testing View and Reactor How to test? Reactor.stub() state: set
fake state action: send fake action actions: log received actions
Testing View and Reactor - View Action
Testing View and Reactor - View Action When: follow button
taps Then: sends follow action
Testing View and Reactor - View Action // given let
reactor = ProfileViewReactor() // when // then
Testing View and Reactor - View Action // given let
reactor = ProfileViewReactor() reactor.stub.isEnabled = true // when // then
Testing View and Reactor - View Action // given let
reactor = ProfileViewReactor() reactor.stub.isEnabled = true reactor.stub.state.value.user = User() // when // then
Testing View and Reactor - View Action // given let
reactor = ProfileViewReactor() reactor.stub.isEnabled = true reactor.stub.state.value.user = User() let viewController = ProfileViewController() viewController.reactor = reactor // when // then
Testing View and Reactor - View Action // given let
reactor = ProfileViewReactor() reactor.stub.isEnabled = true reactor.stub.state.value.user = User() let viewController = ProfileViewController() viewController.reactor = reactor // when let button = viewController.userCell.followButton // then
Testing View and Reactor - View Action // given let
reactor = ProfileViewReactor() reactor.stub.isEnabled = true reactor.stub.state.value.user = User() let viewController = ProfileViewController() viewController.reactor = reactor // when let button = viewController.userCell.followButton button.sendActions(for: .touchUpInside) // then
Testing View and Reactor - View Action // given let
reactor = ProfileViewReactor() reactor.stub.isEnabled = true reactor.stub.state.value.user = User() let viewController = ProfileViewController() viewController.reactor = reactor // when let button = viewController.userCell.followButton button.sendActions(for: .touchUpInside) // then let lastAction = reactor.stub.actions.last XCTAssertEqual(lastAction, .follow)
Testing View and Reactor - View State When: following the
user Then: button is selected
Testing View and Reactor - View State // given let
cellReactor = UserCellReactor() // when // then
Testing View and Reactor - View State // given let
cellReactor = UserCellReactor() cellReactor.stub.isEnabled = true // when // then
Testing View and Reactor - View State // given let
cellReactor = UserCellReactor() cellReactor.stub.isEnabled = true let cell = UserCell() cell.reactor = cellReactor // when // then
Testing View and Reactor - View State // given let
cellReactor = UserCellReactor() cellReactor.stub.isEnabled = true let cell = UserCell() cell.reactor = cellReactor // when cellReactor.stub.state.value.isFollowing = true // then
Testing View and Reactor - View State // given let
cellReactor = UserCellReactor() cellReactor.stub.isEnabled = true let cell = UserCell() cell.reactor = cellReactor // when cellReactor.stub.state.value.isFollowing = true // then XCTAssertTrue(cell.followButton.isSelected)
Testing View and Reactor - Reactor State When: receive follow
action Then: update following state ProfileView Reactor
Testing View and Reactor - Reactor State // given let
reactor = ProfileViewReactor() // when // then
Testing View and Reactor - Reactor State // given let
reactor = ProfileViewReactor() // when reactor.action.onNext(.follow) // then
Testing View and Reactor - Reactor State // given let
reactor = ProfileViewReactor() // when reactor.action.onNext(.follow) // then let user = reactor.currentState.user XCTAssertEqual(user?.isFollowing, true)
Future Ideas Development Documentation Community
Development Testing Support SectionReactor AlertReactor ModelReactor Plugins ... Nested stub
Dummy reactor ... Building Extensions
Documentation Best Practices Translations Code-level Documentation
Community RxSwift Slack #reactorkit (English) https://rxswift-slack.herokuapp.com Swift Korea Slack #reactorkit
(Korean) http://slack.swiftkorea.org
https://reactorkit.io