HOWTO:
MVVM + RAC +TDD
Note: All info is subject to change.
April 2015 1
ABOUT
Alexey Demedeckiy
iOS developer at Ciklum CSC CI
Mentor
2
BACKGROUND
B2B projects.
Rich data flow.
Rich UI.
Animation driven UI.
3
AGENDA
Road to MVVM
MVVM State of the union
TDD on UI?
RAC?
Outro
4
MASSIVEVIEW CONTROLLER
UIViewController
UIKit
Network
Data
storage
Business
logic
Custom
interface
System
Interaction
5
APPLE MVC
UIViewController
UIKit
Network
Data
storage
Business
logic
Custom
interface
System
Interaction
6
MVVM (RICHVIEW)
UIViewController
UIKit
Network
Data
storage
Business
logic
Custom
interface
System
Interaction
@interface MyView: UIView
id<MyViewModel>
7
MVVM (RICHVIEW)
UIViewController
UIKit
Network
Data
storage
Business
logic
Custom
interface
System
Interaction
@interface MyView: UIView
id<MyViewModel>
8
MVVM (RICHVIEW) + RAC
UIViewController
UIKit
Network
Data
storage
Business
logic
Custom
interface
System
Interaction
@interface MyView: UIView
id<MyViewModel>
9
MVVM (RICHVIEW) + RAC
UIViewController
UIKit
Network
Data
storage
Business
logic
Custom
interface
System
Interaction
@interface MyView: UIView
id<MyViewModel>
10
MVVM 2.0
11
ONE DIRECTION STATE FLOW
Source Destination
Data as @properties
12
NO HIDDEN CONNECTIONS
Source Destination
Data as @properties
Call methods
Set values
13
ONE DIRECTION EVENT FLOW
Source Destination
(void)[source callMethod]
14
NO SIDE EFFECTS
Source Destination
(void)[source callMethod]
Return values
Call methods
15
HOWTO ACHIEVE?
Destination owns a Source.
Destination calls a Source.
Destination look at Source state.
Destination is derived from Source.
16
AT SCALE
D1
S2
S1
D2
System
strong link
17
MVVM
View
Model
ViewModel
UIKit
state flow
event and ownership flow
18
AT SCALE
No singletons.
Context derived object graph.
Lifecycle is determined by (UI + BL)
19
MVVM AT SCALE
View
Model
ViewModel
UIKit App component
Creation 20
DECOMPOSITION IS A KEY
View decomposed to UIViews, UIViewControllers, DataSources,
Delegates, Managers, Storyboards…
View Model decomposed toView Models.
Model decomposed to Core, Services, Facades.
21
CODE / LAYER DISTRIBUTION
0
25
50
75
100
Content feed Content editor Offline content Offline with sync
View ViewModel Model
22
VIEW LAYER
Storyboard backed, XIB backed, code - no matter.
Layout.
Localization.
Render efficiency.
23
VIEW LAYER CONNECTIONS
View
View Model
Data display
View
View Model
Alternate layout
View
View
Model
Tab like interface
View
View
Model
View Model
24
VIEWTESTING
View
TestViewModel ViewModel
Model
AppAcceptance
testing
MockView Model
Unit testing
25
TDD INVIEW: SETUP
26
TDD INVIEW: SETUP
ARC Safe creation Window for events
27
TDD INVIEW: DEALLOC
28
TDD INVIEW: DEALLOC
Expect dealloc RAC Dealloc hook Check deallocARC safe nil
29
TDD INVIEW: RELOAD DATA
30
TDD INVIEW: RELOAD DATA
Flag HOOK on SUT method CheckSet flag
31
TDD INVIEW: CELLTAP
Load mock data to table view
32
TDD INVIEW: CELLTAP
Setup expectation for correct call
33
TDD INVIEW: CELLTAP
Setup expectation for correct call
Verify call correctness
Fire expectation Is Equal to string wrapper
34
TDD INVIEW: CELLTAP
Send event to cell
35
TDD INVIEW: CELLTAP
Send event to cell
Push segue require NavConWait for UIKit internalsSend event
Verify
36
TDD INVIEW: P.S
KIF for interacting.
We need to wait. Sometimes.
Test Behavior not code.
37
VIEWMODEL LAYER
WD40 for your data.
Intermediate view context.
Umbrella for interfaces.
Thin (5-15 % of code)
38
VIEWMODEL CONNECTIONS
View Model
Model
View
Model
Model
View Model
Model
View
Model
Model
Core
39
VIEW MODELTESTING
TDD
As simple as possible.
Model state changes —ViewModel state changes
ViewModel receive call — Model receive call
Can hold more than one model.
40
MODEL LAYER
Core
F1
F2
F3
VM1
VM2
VM3
S1
S2
S3
41
FACADES
Holding temporary contexts.
Thin API
Join several Core APIs.
42
FACADES: EXAMPLES
Create new appointment in calendar.
Write email.
Fail possible action
etc.
43
CORE
Fail = Crash
Minimum frameworks. (Core Data instances may be exceptions)
Do not owns a facades.
Owns services.
Data consistence.
44
SERVICES
All system API
All frameworks.
Request / Response API.
No cross service communication.
45
MODEL: PS
Can be simpler.
Much simpler.
46
WHAT ABOUT BINDINGS?
Any bindings is implementation detail.
Cross layer usage.
At least cross object.
47
KINDS OF MESSAGES:
FROM: TO:
Data
Data
Call
Call
Data
48
BINDINGS AS REACTIONS
SOURCE: DESTINATION:
State
State
Action
Broadcast
State
49
APPLE PUSH OPTIONS
SOURCE: DESTINATION:
set @property Setter
Call method Method
50
APPLE PUSH OPTIONS
SOURCE: DESTINATION:
set @property Setter
Call method Method
Source is depend on Destination.
Abstract layer depend on Concrete
51
APPLE PULL OPTIONS
SOURCE: DESTINATION:
KVO
KVO
- observe…
NSNotification @selector()
52
APPLE PULL OPTIONS
SOURCE: DESTINATION:
KVO
KVO
- observe…
NSNotification @selector()
String based typing.
Runtime error detection.
Threads and ownership
53
RAC OPTIONS:
SOURCE: DESTINATION:
@property …
RAC(…) = …
rac_liftSelector:
RACSignal* …
RAC(…) = …
54
RAC USING
55
RAC USING: SUBSCRIBE NEXT
Don’t
56
RAC USING: SUBSCRIBE NEXT
rac_liftSelector
RAC(…)
Exception: -(RACSignal*)fn (limited context)
57
RAC USING: NO LOGIC INSIDE
Do not mix with UIKit
Do not mix with Networking
Do not mix with Layout
Do not mix with CoreData
Do not mix with Threading
58
RAC USING:ABSTRACTTOOLS
59
RAC USING:ABSTRACTTOOLS
60
RAC USING: DECOMPOSE
Fixing on instance
Tech details
Actual binding
61
RAC USING: DECOMPOSE
62
RAC USING: DECOMPOSE
63
RAC USING: DOUBLE WEAK
64
RAC USING: DOUBLE WEAK
view not loaded yet
first value missed
replay value
65
RAC: PS
Just glue.
Powerful.
Dangerous.
66
FUTURE
ComponentsKit (@Facebook)
Swift
Implicit binding
LINKS
http://cocoasamurai.blogspot.ca/2013/03/basic-mvvm-with-
reactivecocoa.html
https://speakerdeck.com/jspahrsummers/code-reuse-with-mvvm
https://speakerdeck.com/dalog/m-v-vm-basics
http://componentkit.org/
http://jlongster.com/Removing-User-Interface-Complexity,-or-
Why-React-is-Awesome
QUESTIONS
email: dalog@me.com
skype: nobidon
THE END
69

Алексей Демедецкий: How to: RAC, TDD, MVVM