SlideShare a Scribd company logo
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

More Related Content

PDF
ReactorKit으로 단방향 반응형 앱 만들기
PDF
RxSwift Testing 같이 시작하기 feat. RxBlocking, RxTest
PDF
A Framework Driven Development
PDF
iOS Modular Architecture with Tuist
PDF
InjectionIII의 Hot Reload를 이용하여 앱 개발을 좀 더 편하게 하기.pdf
PPTX
マイクロサービスにおける 非同期アーキテクチャ
PDF
Let'Swift 2023 iOS 애플리케이션 개발 생산성 고찰
- 정시 퇴근을 위해 우리는 어떻게 해야할 것인가?
PDF
はじめてのGit forデザイナー&コーダー
ReactorKit으로 단방향 반응형 앱 만들기
RxSwift Testing 같이 시작하기 feat. RxBlocking, RxTest
A Framework Driven Development
iOS Modular Architecture with Tuist
InjectionIII의 Hot Reload를 이용하여 앱 개발을 좀 더 편하게 하기.pdf
マイクロサービスにおける 非同期アーキテクチャ
Let'Swift 2023 iOS 애플리케이션 개발 생산성 고찰
- 정시 퇴근을 위해 우리는 어떻게 해야할 것인가?
はじめてのGit forデザイナー&コーダー

What's hot (20)

PDF
Anatomy of a Spring Boot App with Clean Architecture - Spring I/O 2023
PPTX
SOLID, DRY, SLAP design principles
PDF
Flutterで単体テストを行う方法とGitHub Actionsを使った自動化
PDF
생산성을 높여주는 iOS 개발 방법들.pdf
PDF
Dockerfileを改善するためのBest Practice 2019年版
PDF
[LetSwift 2023] 객체지향-함수형 아키텍처 직접 만들기
PDF
LetSwift 2017 - 토스 iOS 앱의 개발/배포 환경
PDF
이승재, 일정대로 출시하기 왜 & 어떻게: 개발자를 위한 제작진행개론, NDC2017
PDF
Clean architecture
PPTX
ユーザ要望に応えるView customize活用事例
PDF
React Typescript for beginners: Translator app with Microsoft cognitive services
PDF
20220716_만들면서 느껴보는 POP
PDF
ノンプログラマでも今日から使える「Git」でバージョン管理
PDF
PHP-FPM の子プロセス制御方法と設定をおさらいしよう
PDF
ELCE 2012 - Dive into Android Networking: Adding Ethernet Connectivity
PPTX
BDD testing with cucumber
PDF
Redux Toolkit - Quick Intro - 2022
PPTX
Cucumber BDD
PDF
Go Friday 傑作選
PDF
Micro Frontend Platforms for Kubernetes
Anatomy of a Spring Boot App with Clean Architecture - Spring I/O 2023
SOLID, DRY, SLAP design principles
Flutterで単体テストを行う方法とGitHub Actionsを使った自動化
생산성을 높여주는 iOS 개발 방법들.pdf
Dockerfileを改善するためのBest Practice 2019年版
[LetSwift 2023] 객체지향-함수형 아키텍처 직접 만들기
LetSwift 2017 - 토스 iOS 앱의 개발/배포 환경
이승재, 일정대로 출시하기 왜 & 어떻게: 개발자를 위한 제작진행개론, NDC2017
Clean architecture
ユーザ要望に応えるView customize活用事例
React Typescript for beginners: Translator app with Microsoft cognitive services
20220716_만들면서 느껴보는 POP
ノンプログラマでも今日から使える「Git」でバージョン管理
PHP-FPM の子プロセス制御方法と設定をおさらいしよう
ELCE 2012 - Dive into Android Networking: Adding Ethernet Connectivity
BDD testing with cucumber
Redux Toolkit - Quick Intro - 2022
Cucumber BDD
Go Friday 傑作選
Micro Frontend Platforms for Kubernetes
Ad

Similar to Hello, ReactorKit  (20)

PDF
What 100M downloads taught us about iOS architectures
PDF
Materi Modern React Redux Power Point.pdf
PDF
From mvc to redux: 停看聽
PDF
Android architecture components - how they fit in good old architectural patt...
PPTX
React + Redux + TypeScript === ♥
PDF
ReRxSwift
PPTX
Spring Web Flow. A little flow of happiness.
PPTX
STATE MANAGEMENT IN REACT [Autosaved].pptx
PDF
Building Modern Web Applications using React and Redux
PPTX
Intro react js
ODP
Developing JSR 286 Portlets
PPTX
Damian Kmiecik - Road trip with Redux
PDF
Unidirectional Data Flow in Swift
PDF
How to use redux with react hooks in react native application
PPTX
Getting started with Redux js
PPT
Project Description Of Incident Management System Developed by PRS (CRIS) , N...
PPTX
iOS Architectures
PDF
React & The Art of Managing Complexity
PPTX
[Final] ReactJS presentation
PDF
Content-Driven Apps with React
What 100M downloads taught us about iOS architectures
Materi Modern React Redux Power Point.pdf
From mvc to redux: 停看聽
Android architecture components - how they fit in good old architectural patt...
React + Redux + TypeScript === ♥
ReRxSwift
Spring Web Flow. A little flow of happiness.
STATE MANAGEMENT IN REACT [Autosaved].pptx
Building Modern Web Applications using React and Redux
Intro react js
Developing JSR 286 Portlets
Damian Kmiecik - Road trip with Redux
Unidirectional Data Flow in Swift
How to use redux with react hooks in react native application
Getting started with Redux js
Project Description Of Incident Management System Developed by PRS (CRIS) , N...
iOS Architectures
React & The Art of Managing Complexity
[Final] ReactJS presentation
Content-Driven Apps with React
Ad

More from Suyeol Jeon (11)

PDF
Let's TDD
PDF
Building Funnels with Google BigQuery
PDF
RxSwift 시작하기
PDF
Swift - 혼자 공부하면 분명히 안할테니까 같이 공부하기
PDF
Evermind
PDF
StyleShare 2014년 8월 관점공유 - 전수열
PDF
Present your presentation
PDF
Joyfl 창업이야기.ssul
PDF
좋은 디자이너, 나쁜 프로젝트매니저, 이상한 개발자
PDF
Evermind (2차 평가)
PDF
I'm Traveling
Let's TDD
Building Funnels with Google BigQuery
RxSwift 시작하기
Swift - 혼자 공부하면 분명히 안할테니까 같이 공부하기
Evermind
StyleShare 2014년 8월 관점공유 - 전수열
Present your presentation
Joyfl 창업이야기.ssul
좋은 디자이너, 나쁜 프로젝트매니저, 이상한 개발자
Evermind (2차 평가)
I'm Traveling

Recently uploaded (20)

PPTX
AgentX UiPath Community Webinar series - Delhi
PPTX
Internship_Presentation_Final engineering.pptx
PPTX
ANIMAL INTERVENTION WARNING SYSTEM (4).pptx
PDF
Operating System & Kernel Study Guide-1 - converted.pdf
PPTX
Recipes for Real Time Voice AI WebRTC, SLMs and Open Source Software.pptx
PPTX
Fluid Mechanics, Module 3: Basics of Fluid Mechanics
PPTX
Unit 5 BSP.pptxytrrftyyydfyujfttyczcgvcd
PPTX
CH1 Production IntroductoryConcepts.pptx
PPTX
436813905-LNG-Process-Overview-Short.pptx
PDF
Arduino robotics embedded978-1-4302-3184-4.pdf
PPTX
24AI201_AI_Unit_4 (1).pptx Artificial intelligence
PPTX
Lesson 3_Tessellation.pptx finite Mathematics
PPTX
The-Looming-Shadow-How-AI-Poses-Dangers-to-Humanity.pptx
PDF
Evaluating the Democratization of the Turkish Armed Forces from a Normative P...
PDF
algorithms-16-00088-v2hghjjnjnhhhnnjhj.pdf
PPTX
Simulation of electric circuit laws using tinkercad.pptx
PPTX
Geodesy 1.pptx...............................................
PPTX
KTU 2019 -S7-MCN 401 MODULE 2-VINAY.pptx
PPTX
UNIT-1 - COAL BASED THERMAL POWER PLANTS
AgentX UiPath Community Webinar series - Delhi
Internship_Presentation_Final engineering.pptx
ANIMAL INTERVENTION WARNING SYSTEM (4).pptx
Operating System & Kernel Study Guide-1 - converted.pdf
Recipes for Real Time Voice AI WebRTC, SLMs and Open Source Software.pptx
Fluid Mechanics, Module 3: Basics of Fluid Mechanics
Unit 5 BSP.pptxytrrftyyydfyujfttyczcgvcd
CH1 Production IntroductoryConcepts.pptx
436813905-LNG-Process-Overview-Short.pptx
Arduino robotics embedded978-1-4302-3184-4.pdf
24AI201_AI_Unit_4 (1).pptx Artificial intelligence
Lesson 3_Tessellation.pptx finite Mathematics
The-Looming-Shadow-How-AI-Poses-Dangers-to-Humanity.pptx
Evaluating the Democratization of the Turkish Armed Forces from a Normative P...
algorithms-16-00088-v2hghjjnjnhhhnnjhj.pdf
Simulation of electric circuit laws using tinkercad.pptx
Geodesy 1.pptx...............................................
KTU 2019 -S7-MCN 401 MODULE 2-VINAY.pptx
UNIT-1 - COAL BASED THERMAL POWER PLANTS

Hello, ReactorKit 