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
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Matt Diephouse
May 13, 2014
Programming
250
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
How I Stole PSI from Android Studio - DroidKaigi2026
worker8
0
110
DynamoDBの基礎を振り返りながらベクトル検索機能を理解する
musan
3
280
数年滞っていたダークモード対応をおよそ2週間で完了させる
chigichan24
0
700
Swift愛好会と私(ウホーイ) / Swift Fan Club and Uhooi
uhooi
0
150
スマート反転とウェブアクセシビリティ
camiha
0
180
Heart of Swift Concurrency
koher
0
250
XP祭りでしか伝わらないフリップネタ #xpjug
murabayashi
0
140
LL言語やWebフレームワークのPostgreSQL対応 〜DBの機能がユーザーに届くまで〜
kentaroutakeda
0
150
DroidKaigi 2026 「個人開発という実験場: Android エンジニアが手にする4つの自由」
slashnephy
0
230
AIは賢い。でも実行環境は? CLIおじさんがAI時代に伝えたいこと ~ CLIおじさんがAI時代に伝えたいこと ~
curekoshimizu
1
240
AgentCore CLI で進化した AWS での AI エージェントの作り方 : 必要な機能を必要な時に
icoxfog417
PRO
3
320
Deep dive into the select statement (GopherCon UK)
jespino
0
170
Featured
See All Featured
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
28
3.6k
Fashionably flexible responsive web design (full day workshop)
malarkey
408
67k
We Have a Design System, Now What?
morganepeng
55
8.3k
RailsConf 2023
tenderlove
30
1.5k
Navigating the moral maze — ethical principles for Al-driven product design
skipperchong
2
530
Highjacked: Video Game Concept Design
rkendrick25
PRO
1
450
Future Trends and Review - Lecture 12 - Web Technologies (1019888BNR)
signer
PRO
0
3.7k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
32
3k
How Fast Is Fast Enough? [PerfNow 2025]
tammyeverts
3
880
Large-scale JavaScript Application Architecture
addyosmani
515
110k
Prompt Engineering for Job Search
mfonobong
0
450
State of Search Keynote: SEO is Dead Long Live SEO
ryanjones
0
270
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