Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
MVVM
Search
Matt Diephouse
May 13, 2014
Programming
260
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
MVVM
Matt Diephouse
May 13, 2014
More Decks by Matt Diephouse
See All by Matt Diephouse
Noble Cocoa
mdiep
2
270
Static Libraries
mdiep
1
140
Other Decks in Programming
See All in Programming
機械に任せるテスト、人が見るテスト ⽣成AIで引き直した、運⽤保守フェーズの線引き
dske104
0
190
[Rails World 2026] Durable orchestration on Rails: from continuation to workflow
palkan
1
750
全ての永続トークンを、生まれる前に消し去りたい!
sylph01
2
880
残高管理から台帳サービスへの進化
artoy
1
200
すこし踏み込む CancellationToken
htkym
2
1.7k
golang-bob.pdf
iwatsukayura
0
130
Jetpack Compose Mechanisms
skydoves
3
820
Agentic Software Factoryに、すごく賢いIF文を。 / super smart IF statement into the Agentic Software Factory.
rkaga
8
2.2k
Herb in Rails 8.2: Your ERB views, now HTML-aware @ Kaigi on Rails 2026, Tokyo, Japan
marcoroth
2
220
見えないものを探る要求要件定義に必要な基本的思考 / invisible-requirement-thinking
minodriven
15
8.5k
IBM Bob Dojo #1 仕様駆動開発入門
oniak3ibm
PRO
0
390
KiroのSpecで「五目並べ」を作ってみる
satoshi256kbyte
1
380
Featured
See All Featured
From π to Pie charts
rasagy
1
400
Claude Code どこまでも/ Claude Code Everywhere
nwiizo
68
59k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
31
3.4k
Avoiding the “Bad Training, Faster” Trap in the Age of AI
tmiket
0
270
HTML-Aware ERB: The Path to Reactive Rendering @ RubyCon 2026, Rimini, Italy
marcoroth
5
820
Chrome DevTools: State of the Union 2024 - Debugging React & Beyond
addyosmani
10
1.4k
It's Worth the Effort
3n
188
29k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
37
6.6k
Believing is Seeing
oripsolob
1
240
How to Grow Your eCommerce with AI & Automation
katarinadahlin
PRO
2
330
Building Adaptive Systems
keathley
44
3.2k
Leo the Paperboy
mayatellez
10
2.4k
Transcript
MVVM Model – View – ViewModel
WHAT IS MVVM?
IT'S LIKE MVC, BUT DIFFERENT.
BUT IT'S NOT THAT DIFFERENT.
IT'S JUST DIFFERENT ENOUGH.
Example: IPHONE RECIPE APP A TABLE OF RECIPES GROUPED ALPHABETICALLY
MVC 1.0
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return self.fetchedResultsController.sections.count; } - (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section { id<NSFetchedResultsSectionInfo> info = self.fetchedResultsController.sections[section]; return info.numberOfObjects; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:...]; RCPRecipe *recipe = [self.fetchedResultsController objectAtIndexPath:indexPath]; cell.textLabel.text = [NSString stringWithFormat:@"%@ by %@", recipe.name, recipe.author.name]; return cell; }
MVC 1.0 ▸ Logic is tied to presentation ▸ It
can only be tested visually ▸ The code is verbose ▸ Tightly coupled to the database and model ▸ No separation of concerns
MVC 2.0
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return self.numberOfSections; } - (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section { return [self numberOfRecipesInSection:section]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:...]; RCPRecipe *recipe = [self recipeAtIndexPath:indexPath]; cell.textLabel.text = [NSString stringWithFormat:@"%@ by %@", recipe.name, recipe.author.name]; return cell; }
- (NSInteger)numberOfSections { return self.fetchedResultsController.sections.count; } - (NSInteger)numberOfRecipesInSection:(NSInteger)section { id<NSFetchedResultsSectionInfo>
info = self.fetchedResultsController.sections[section]; return info.numberOfObjects; } - (RCPRecipe *)recipeAtIndexPath:(NSIndexPath *)indexPath { return [self.fetchedResultsController objectAtIndexPath:indexPath]; }
MVC 2.0 ▸ Some logic could be tested in code
▸ Partial separation of concerns ▸ Reusable methods for getting model objects ▸ Slightly less verbose
MVC 2.0 ▸ Some logic is still tied to presentation
▸ Still requires visual testing ▸ Tightly coupled to the model
MVC 3.0
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return self.numberOfSections; } - (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section { return [self numberOfRecipesInSection:section]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:...]; RCPRecipe *recipe = [self recipeAtIndexPath:indexPath]; cell.textLabel.text = [self displayNameForRecipe:recipe]; return cell; }
MVC 3.0 ▸ Logic is testable in code ▸ Separation
of concerns
MVC 3.0 ▸ Tightly coupled to the model ▸ Testing
per-row logic requires an entire table view ▸ Logic could easily depend on view
MVVM
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return self.viewModel.numberOfSections; } - (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section { return [self.viewModel numberOfRecipesInSection:section]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:...]; RCPRecipeViewModel *viewModel = [self.viewModel viewModelAtIndexPath:indexPath]; cell.textLabel.text = viewModel.displayName; return cell; }
@interface RCPRecipeListViewModel : NSObject @property (assign, nonatomic) NSInteger numberOfSections; -
(NSInteger)numberOfRecipesInSection:(NSInteger)section; - (RCPRecipeViewModel *)viewModelAtIndexPath:(NSIndexPath *)indexPath; @end
@interface RCPRecipeViewModel : NSObject @property (copy, nonatomic) NSString *displayName; -
(instancetype)initWithRecipe:(RCPRecipe *)recipe; @end
MVVM ▸ Separation of concerns ▸ Testable in code ▸
Easy to test per-row logic ▸ Loosely coupled ▸ Independent of UIKit/AppKit ▸ Easily have different row types
Q & A