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
69
RxSwift แแ ตแแ กแจแแ กแแ ต
devxoul
1
370
ReactorKit์ผ๋ก ๋จ๋ฐฉํฅ ๋ฐ์ํ ์ฑ ๋ง๋ค๊ธฐ
devxoul
0
190
Swift - ํผ์ ๊ณต๋ถํ๋ฉด ๋ถ๋ช ํ ์ํ ํ ๋๊น ๊ฐ์ด ๊ณต๋ถํ๊ธฐ
devxoul
10
3.3k
แแ ฉแแแ ณแซ แแ ตแแ กแแ ตแแ ฅ, แแ กแแ ณแซ แแ ณแ แ ฉแแ ฆแจแแ ณแแ ขแแ ตแแ ฅ, แแ ตแแ กแผแแ กแซ แแ ขแแ กแฏแแ ก
devxoul
0
130
Other Decks in Programming
See All in Programming
ไปๆงๆธใๆธใๅใซใใผใในใไฝใ - Agent Native้็บใฏใๆข็ดขใ้ใใๅคๅฎใๅบใใ
gotalab555
4
1.7k
FastAPI ใฎไธฆ่กๅฆ็ใขใใซใๅฎๅ จใซ็่งฃใใ
hoto17296
6
2.3k
AI Readyใฎๆญฃไฝใฏใใผใฟใใใธใกใณใใ ใกใใชใชใณ2.0ใฎๆๅ็ท
freee
PRO
0
350
KotlinConf Extended South Korea 2026 Keynote
l2hyunwoo
0
120
ใใใซ3ใณใใใญใใฏใใใใใใใใโโ็ๆAIๆไปฃใซใใใโไพกๅคใๅฑใใชใ็็ฑโใฎๆง้
kosuket
0
560
Pythonใฎๅฎ่กใฏใฉใใพใง่ณขใใชใฃใใฎใ๏ผ CPythonใจPyPyใใ่ฆใๆ้ฉๅใฎใใใฟ
curekoshimizu
3
1.1k
typoใชใใใญใใ
raspython3
0
210
ไปๆง้งๅ้็บใฎๆถ่ฒปๆ้
watany
20
8.8k
ไบบ้ใฎ็ฎใฏใใใใชใใใ ใใJPEGใฏ30ๅนดใใค
yuzneri
12
19k
ๆบๅ ใใณใบใชใณๆฆ่ฆ็ทจ
hideg
0
200
ๅฑไบบๅใใ็ฅ่ญใใ AIใ่พฟใใๅฐๅณใซใใ
pkshadeck
PRO
1
200
ใไบบใ่ฉไพกใใ AIใใฎ่จญ่จใจๅฎ่ฃ ย
ryoyanara
0
220
Featured
See All Featured
Primal Persuasion: How to Engage the Brain for Learning That Lasts
tmiket
0
430
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
52
6k
How to build a perfect <img>
jonoalderson
1
5.9k
Leveraging LLMs for student feedback in introductory data science courses - posit::conf(2025)
minecr
1
350
ๅไบบ้็บใฎๅคฑๆใ้ฟใใใคใฑใฆใ่ใๆน / tips for indie hackers
panda_program
123
22k
Conquering PDFs: document understanding beyond plain text
inesmontani
PRO
4
3k
Leveraging Curiosity to Care for An Aging Population
cassininazir
1
470
How to Build an AI Search Optimization Roadmap - Criteria and Steps to Take #SEOIRL
aleyda
1
2.1k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
31
3.3k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
333
23k
What Being in a Rock Band Can Teach Us About Real World SEO
427marketing
0
1.1k
Utilizing Notion as your number one productivity tool
mfonobong
4
550
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