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
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
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
61
RxSwift แแ ตแแ กแจแแ กแแ ต
devxoul
1
370
ReactorKit์ผ๋ก ๋จ๋ฐฉํฅ ๋ฐ์ํ ์ฑ ๋ง๋ค๊ธฐ
devxoul
0
180
Swift - ํผ์ ๊ณต๋ถํ๋ฉด ๋ถ๋ช ํ ์ํ ํ ๋๊น ๊ฐ์ด ๊ณต๋ถํ๊ธฐ
devxoul
10
3.3k
แแ ฉแแแ ณแซ แแ ตแแ กแแ ตแแ ฅ, แแ กแแ ณแซ แแ ณแ แ ฉแแ ฆแจแแ ณแแ ขแแ ตแแ ฅ, แแ ตแแ กแผแแ กแซ แแ ขแแ กแฏแแ ก
devxoul
0
130
Other Decks in Programming
See All in Programming
TSKaigi Night Talks 2026_TypeScriptใงใตใใฉใคใใงใผใณใฎๆดๅๆงใๅใซ้ใ่พผใใ
geekplus_tech
0
430
TypeScript+Orvalใฆใๅฎ็พใใๅๅฎๅ จใใคๅ ็ขใฆใในใฑใผใฉใใใซใชใใซใใใฃใใซ้็ฅๅบ็ค / TSKaigi Night talks ~after conference~
d0riven
0
390
ไพๅคใฎๆญฃใใๆฑใๆน ใใฎใจใฉใผ try-catchใใฆๅคงไธๅคซ๏ผ
jinwatanabe
0
340
ใใใใAgentCoreใ่งฆใๆนใธใใฌใณใใฏGatewayใงใ
har1101
6
480
ใฉใใพใงใใใใฆ่จฑใใใใฎใ
tk3fftk
0
430
ใฉใณใใฟใคใ LTไผ3ๅจๅนด๏ผใฉใณใใฟใคใ LTไผใ3ๅนด้็ถใใใใใ่ฉฑ
y0hgi
1
130
1B+ /day่ฆๆจกใฎใญใฐใ็ฎก็ใใๆ่ก
broadleaf
0
130
Generative UI & AI-Assistants for Your Angular Solutions
manfredsteyer
PRO
0
140
SREใฎ็ฉใฟ้ใญใAI้งๅ้็บใฎใฌใผใใฌใผใซใซใชใฃใ โ 7ใคใฎๅฎ่ทต/SRE Guardrails The 7
tomoyakitaura
7
2.9k
ใใฃใผใใใใฏใง่ฒใฆใAI้็บ
kotaminato
1
110
ใขใซใดใชใบใ ใฏไฝใๅง็ธฎใใฆใใใฎใ โ Haskell ใใ่ฒใฃใใๅง็ธฎไปฃๆฐใใจใใใกใณใฟใซใขใใซ
naoya
15
2.9k
้นฟ้ใใใซ่ใ๏ผใTypeScriptใณใผใใฌใทใ้ใใง็ฃจใๅฎ่ทตๅ
tonkotsuboy_com
4
1k
Featured
See All Featured
Groundhog Day: Seeking Process in Gaming for Health
codingconduct
0
240
Bioeconomy Workshop: Dr. Julius Ecuru, Opportunities for a Bioeconomy in West Africa
akademiya2063
PRO
1
170
The agentic SEO stack - context over prompts
schlessera
0
840
The Curse of the Amulet
leimatthew05
2
13k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
234
17k
Introduction to Domain-Driven Design and Collaborative software design
baasie
1
890
Why You Should Never Use an ORM
jnunemaker
PRO
61
9.9k
Speed Design
sergeychernyshev
33
1.9k
ใใณใใใใฃใณในใซ๏ผๆชๆฅใใคใใใใญใใฏใใญใผใใใใ #pmconf2020
aki_iinuma
128
56k
Rails Girls Zรผrich Keynote
gr2m
96
14k
Winning Ecommerce Organic Search in an AI Era - #searchnstuff2025
aleyda
1
2.1k
่ทไฝใซใใใใใๅ จๅกใใชใผใใผใทใใใ็บๆฎใใใใผใ ไฝใ / Building a team where everyone can demonstrate leadership regardless of position
madoxten
63
55k
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