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
Schlanke View Controller
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Chris Eidhof | @chriseidhof
October 05, 2013
Technology
3
590
Schlanke View Controller
Vortrag bei der Macoun 2013
Chris Eidhof | @chriseidhof
October 05, 2013
Tweet
Share
More Decks by Chris Eidhof | @chriseidhof
See All by Chris Eidhof | @chriseidhof
Dutch FP Day 2015
chriseidhof
2
390
Tiny Networking in Swift
chriseidhof
2
19k
Functional Swift - Brooklyn
chriseidhof
3
1.3k
Functional Swift - SF
chriseidhof
6
26k
Functional Swift
chriseidhof
6
1.3k
Functional Swift
chriseidhof
1
160
Functional Programming in Swift
chriseidhof
40
19k
Lighter View Controllers
chriseidhof
4
200
Parsing with Blocks
chriseidhof
2
240
Other Decks in Technology
See All in Technology
CDKで始めるTypeScript開発のススメ
tsukuboshi
1
360
2026年、サーバーレスの現在地 -「制約と戦う技術」から「当たり前の実行基盤」へ- /serverless2026
slsops
2
220
Amazon S3 Vectorsを使って資格勉強用AIエージェントを構築してみた
usanchuu
3
440
Digitization部 紹介資料
sansan33
PRO
1
6.8k
予期せぬコストの急増を障害のように扱う――「コスト版ポストモーテム」の導入とその後の改善
muziyoshiz
1
1.7k
Claude_CodeでSEOを最適化する_AI_Ops_Community_Vol.2__マーケティングx_AIはここまで進化した.pdf
riku_423
2
520
Ruby版 JSXのRuxが気になる
sansantech
PRO
0
140
茨城の思い出を振り返る ~CDKのセキュリティを添えて~ / 20260201 Mitsutoshi Matsuo
shift_evolve
PRO
1
220
M&A 後の統合をどう進めるか ─ ナレッジワーク × Poetics が実践した組織とシステムの融合
kworkdev
PRO
1
420
Embedded SREの終わりを設計する 「なんとなく」から計画的な自立支援へ
sansantech
PRO
3
2.3k
Frontier Agents (Kiro autonomous agent / AWS Security Agent / AWS DevOps Agent) の紹介
msysh
3
160
Tebiki Engineering Team Deck
tebiki
0
24k
Featured
See All Featured
The Language of Interfaces
destraynor
162
26k
Pawsitive SEO: Lessons from My Dog (and Many Mistakes) on Thriving as a Consultant in the Age of AI
davidcarrasco
0
62
Practical Orchestrator
shlominoach
191
11k
Tips & Tricks on How to Get Your First Job In Tech
honzajavorek
0
430
The AI Revolution Will Not Be Monopolized: How open-source beats economies of scale, even for LLMs
inesmontani
PRO
3
3k
Winning Ecommerce Organic Search in an AI Era - #searchnstuff2025
aleyda
0
1.9k
Building Experiences: Design Systems, User Experience, and Full Site Editing
marktimemedia
0
410
Data-driven link building: lessons from a $708K investment (BrightonSEO talk)
szymonslowik
1
910
Applied NLP in the Age of Generative AI
inesmontani
PRO
4
2k
Jamie Indigo - Trashchat’s Guide to Black Boxes: Technical SEO Tactics for LLMs
techseoconnect
PRO
0
55
世界の人気アプリ100個を分析して見えたペイウォール設計の心得
akihiro_kokubo
PRO
66
36k
Automating Front-end Workflow
addyosmani
1371
200k
Transcript
Macoun ⌘ Vorbereitung: 1. Demos, Files im Finder anordnen. 2.
Alle Programme die man für Demos benötigt vorher(!) starten. Bpsw: Xcode, Terminal, Refelection. 3. Präsentation starten und auf Zeichen oder Signal warten. Samstag, 5. Oktober 13
Schlanke View Controller Chris Eidhof Den Titel der Session und
darunter den eigenen Namen eintragen. Logo links oben anstatt dem Platzhalter. Nur auf diesem Slide! Samstag, 5. Oktober 13
WERBUNG Verkaufe Gouda im Wohnwagen Samstag, 5. Oktober 13
UITabellenAnzeigerAbgeordnete Samstag, 5. Oktober 13
Was ist die größte Datei in deinem Projekt? Samstag, 5.
Oktober 13
Was ist die größte Datei in deinem Projekt? 0 200
400 600 800 Samstag, 5. Oktober 13
(image by Manu Cornet) Samstag, 5. Oktober 13
(image by Manu Cornet) Samstag, 5. Oktober 13
View Controller sind nicht wiederverwendbar Samstag, 5. Oktober 13
find . -name "*.m" -exec wc -l "{}" \; |
sort -n Samstag, 5. Oktober 13
154 ./ViewControllers/THUserPrioritiesViewController.m 154 ./ViewControllers/THZoomingNavigationController.m 155 ./Extensions/NSArray+Extensions.m 155 ./Extensions/UIView+Extensions.m 168 ./Controllers/THPriorityTimelineCollectionController.m
179 ./Controllers/THUserScreenInstancesController.m 183 ./ViewControllers/THRootViewController.m 183 ./ViewControllers/THScreenInstanceViewController.m 185 ./Model/User+Extensions.m 192 ./ViewControllers/THEditPriorityViewController.m 221 ./ViewControllers/THScreeningBarViewController.m 243 ./Views/THTimeLineView.m 263 ./ViewControllers/THCardsViewController.m 279 ./Views/THSkillboxView.m Samstag, 5. Oktober 13
154 ./ViewControllers/THUserPrioritiesViewController.m 154 ./ViewControllers/THZoomingNavigationController.m 155 ./Extensions/NSArray+Extensions.m 155 ./Extensions/UIView+Extensions.m 168 ./Controllers/THPriorityTimelineCollectionController.m
179 ./Controllers/THUserScreenInstancesController.m 183 ./ViewControllers/THRootViewController.m 183 ./ViewControllers/THScreenInstanceViewController.m 185 ./Model/User+Extensions.m 192 ./ViewControllers/THEditPriorityViewController.m 221 ./ViewControllers/THScreeningBarViewController.m 243 ./Views/THTimeLineView.m 263 ./ViewControllers/THCardsViewController.m 279 ./Views/THSkillboxView.m Samstag, 5. Oktober 13
512 ./Classes/LessonResultViewController.m 514 ./Classes/Libs/ASIHTTPRequest/ASIDownloadCache.m 598 ./Classes/MainViewController.m 605 ./Classes/GameStartViewController.m 803 ./Classes/ResultViewController.m
818 ./Classes/RootViewController.m 1000 ./Classes/RankingViewController.m 1465 ./Classes/QuestionViewController.m 1590 ./Classes/REDACTEDAppDelegate.m 5125 ./Classes/Libs/ASIHTTPRequest/ASIHTTPRequest.m Samstag, 5. Oktober 13
... na gut, aber das ist ein wichtiger View Controller...
Samstag, 5. Oktober 13
STEPS Project Komplettes Betriebssystem in < 20K Zeilen Samstag, 5.
Oktober 13
Was können wir tun? Samstag, 5. Oktober 13
Ein View Controller vermittelt zwischen Modell und View Samstag, 5.
Oktober 13
Modelllogik Samstag, 5. Oktober 13
Viewlogik Samstag, 5. Oktober 13
Layout Samstag, 5. Oktober 13
Webservice Samstag, 5. Oktober 13
View Controller Modell Child View Controller Webservice Samstag, 5. Oktober
13
Demo Samstag, 5. Oktober 13
View Controller Modell Child View Controller Webservice Samstag, 5. Oktober
13
View Controller Modell Child View Controller Webservice Samstag, 5. Oktober
13
View Controller Modell Child View Controller Webservice Samstag, 5. Oktober
13
Modelllogik Entweder im Modell oder in einer separaten Klasse Samstag,
5. Oktober 13
18 ./NestedTodoList/main.m 30 ./Item.m 31 ./NestedTodoList/Store.m 49 ./NestedTodoList/PersistentStack.m 52 ./NestedTodoList/AppDelegate.m
255 ./NestedTodoList/ItemViewController.m Beispielprojekt Samstag, 5. Oktober 13
18 ./NestedTodoList/main.m 30 ./Item.m 31 ./NestedTodoList/Store.m 49 ./NestedTodoList/PersistentStack.m 52 ./NestedTodoList/AppDelegate.m
255 ./NestedTodoList/ItemViewController.m Beispielprojekt Samstag, 5. Oktober 13
Verantwortlichkeiten •Views konfigurieren •Table View Delegate •Table View Datasource •Fetched
Results Controller Delegate •Items hinzufügen •Items löschen Samstag, 5. Oktober 13
} Separate Klasse Verantwortlichkeiten •Views konfigurieren •Table View Delegate •Table
View Datasource •Fetched Results Controller Delegate •Items hinzufügen •Items löschen Samstag, 5. Oktober 13
} Separate Klasse Verantwortlichkeiten •Views konfigurieren •Table View Delegate •Table
View Datasource •Fetched Results Controller Delegate •Items hinzufügen •Items löschen } Modell Samstag, 5. Oktober 13
- (BOOL)textFieldShouldReturn:(UITextField*)t { NSString* title = t.text; NSUInteger order =
self.parent.children.count; Item* item = [NSEntityDescription insertNewObjectForEntityForName:@"Item" inManagedObjectContext:self.moc]; item.title = title; item.parent = self.parent; item.order = @(order); ... } Modell Samstag, 5. Oktober 13
- (BOOL)textFieldShouldReturn:(UITextField*)t { NSString* title = t.text; NSUInteger order =
self.parent.children.count; [Item insertItemWithTitle:title parent:self.parent inManagedObjectContext:self.moc]; ... } Modell Samstag, 5. Oktober 13
- (void)deleteItem:(id)object { Item* item = object; NSSet* siblings =
item.parent.children; NSPredicate* predicate = [NSPredicate predicateWithFormat:@"order > %@", item.order]; NSSet* itemsAfterSelf = [siblings filteredSetUsingPredicate:predicate]; [itemsAfterSelf enumerateObjectsUsingBlock:^(Item* sibling, BOOL* stop) { sibling.order = @(sibling.order.integerValue - 1); }]; [item.moc deleteObject:item]; } Samstag, 5. Oktober 13
- (void)deleteItem:(id)object { Item* item = object; NSSet* siblings =
item.parent.children; NSPredicate* predicate = [NSPredicate predicateWithFormat:@"order > %@", item.order]; NSSet* itemsAfterSelf = [siblings filteredSetUsingPredicate:predicate]; [itemsAfterSelf enumerateObjectsUsingBlock:^(Item* sibling, BOOL* stop) { sibling.order = @(sibling.order.integerValue - 1); }]; [item.moc deleteObject:item]; } Samstag, 5. Oktober 13
- (void)prepareForDeletion { NSSet* siblings = self.parent.children; NSPredicate* p =
[NSPredicate predicateWithFormat:@"order > %@", self.order]; NSSet* itemsAfterSelf = [siblings filteredSetUsingPredicate:p]; [itemsAfterSelf enumerateObjectsUsingBlock: ^(Item* sibling, BOOL* stop) { sibling.order = @(sibling.order.integerValue - 1); }]; } Samstag, 5. Oktober 13
18 ./NestedTodoList/main.m 31 ./NestedTodoList/Store.m 49 ./NestedTodoList/PersistentStack.m 52 ./NestedTodoList/AppDelegate.m 54 ./Item.m
241 ./NestedTodoList/ItemViewController.m Beispielprojekt Samstag, 5. Oktober 13
18 ./NestedTodoList/main.m 31 ./NestedTodoList/Store.m 49 ./NestedTodoList/PersistentStack.m 52 ./NestedTodoList/AppDelegate.m 54 ./Item.m
241 ./NestedTodoList/ItemViewController.m Beispielprojekt Samstag, 5. Oktober 13
View Controller Modell Child View Controller Webservice UITableViewDS Samstag, 5.
Oktober 13
View Controller Modell Child View Controller Webservice UITableViewDS Samstag, 5.
Oktober 13
@interface FetchedResultsControllerDataSource : NSObject <UITableViewDataSource, NSFetchedResultsControllerDelegate> Samstag, 5. Oktober 13
- (NSInteger)numberOfSectionsInTableView:(UITableView*)t { return self.fetchedResultsController.sections.count; } Samstag, 5. Oktober 13
- (NSInteger)tableView:(UITableView*)t numberOfRowsInSection:(NSInteger)s { id<NSFetchedResultsSectionInfo> section = self.fetchedResultsController.sections[s]; return section.numberOfObjects;
} Samstag, 5. Oktober 13
- (UITableViewCell*)tableView:(UITableView*)t cellForRowAtIndexPath:(NSIndexPath*)ip ? Samstag, 5. Oktober 13
#pragma mark NSFetchedResultsControllerDelegate Samstag, 5. Oktober 13
- (void)controller:(NSFetchedResultsController*)c didChangeObject:(id)anObject atIndexPath:(NSIndexPath*)indexPath forChangeType:(NSFetchedResultsChangeType)ct newIndexPath:(NSIndexPath*)newIndexPath Samstag, 5. Oktober 13
@property (nonatomic, weak) id <FRCDataSourceDelegate> delegate; Samstag, 5. Oktober 13
- (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath { id object = [self.frc objectAtIndexPath:indexPath]; id
cell = [tableView dequeueReusableCellWithIdentifier:self.reuseIdentifier forIndexPath:indexPath]; [self.delegate configureCell:cell withObject:object]; return cell; } Samstag, 5. Oktober 13
- (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath { id object = [self.frc objectAtIndexPath:indexPath]; id
cell = [tableView dequeueReusableCellWithIdentifier:self.reuseIdentifier forIndexPath:indexPath]; [self.delegate configureCell:cell withObject:object]; return cell; } Samstag, 5. Oktober 13
Demo Samstag, 5. Oktober 13
25 ./NestedTodoList/Store.m 49 ./NestedTodoList/PersistentStack.m 52 ./NestedTodoList/AppDelegate.m 64 ./Item.m 111 ./NestedTodoList/FRCDataSource.m
162 ./NestedTodoList/ItemViewController.m Beispielprojekt Samstag, 5. Oktober 13
25 ./NestedTodoList/Store.m 49 ./NestedTodoList/PersistentStack.m 52 ./NestedTodoList/AppDelegate.m 64 ./Item.m 111 ./NestedTodoList/FRCDataSource.m
162 ./NestedTodoList/ItemViewController.m Beispielprojekt Samstag, 5. Oktober 13
Wiederverwendbarkeit Samstag, 5. Oktober 13
Oder eine Oberklasse? Samstag, 5. Oktober 13
Nachteile von Oberklassen Es gibt nur eine Oberklasse Schwerer zu
wechseln, z.B. von UITableView nach UICollectionView Fehleranfälliger: z.B. super calls vergessen Samstag, 5. Oktober 13
Andere Kandidaten UICollectionViewDataSource UIPageViewControllerDataSource UIPickerViewDataSource Samstag, 5. Oktober 13
Mehr Kandidaten UICollectionViewDelegate UIScrollViewDelegate UITableViewDelegate UITableViewDelegate UITextFieldDelegate UINavigationControllerDelegate Samstag, 5.
Oktober 13
View Controller Modell Child View Controller Webservice Samstag, 5. Oktober
13
View Controller Modell Child View Controller Webservice Samstag, 5. Oktober
13
- (UITableViewCell*)tableView:(UITableView*)t cellForRowAtIndexPath:(NSIndexPath*)ip Samstag, 5. Oktober 13
@interface PhotoCell (ConfigureForPhoto) - (void)configureForPhoto:(Photo *)photo; @end PhotoCell+ConfigureForPhoto.h Samstag, 5.
Oktober 13
UITableViewController •Löscht Selektion •Daten neu laden •Scroll indicators zeigen •Editieren
•Scrollen zum first responder •Refresh control •.... Samstag, 5. Oktober 13
Samstag, 5. Oktober 13
View Controller Containment Samstag, 5. Oktober 13
Samstag, 5. Oktober 13
[self addChildViewController:sliderController]; [self.view addSubview:sliderController.view]; [UIView animateWithDuration:0.25 animations:^{ sliderController.view.alpha = 1;
} completion:^(BOOL finished) { [sliderController didMoveToParentViewController:self]; }]; ... oder im Kode Samstag, 5. Oktober 13
Kommunikation Samstag, 5. Oktober 13
Kommunikation •Delegate •Blocks •KVO Samstag, 5. Oktober 13
Kommunikation •Delegate •Blocks •KVO Zu viel? Samstag, 5. Oktober 13
Interface Builder Samstag, 5. Oktober 13
Samstag, 5. Oktober 13
Samstag, 5. Oktober 13
@interface MyCell : UITableViewCell @property (weak) IBOutlet UISlider *slider; @property
(weak) IBOutlet UISwitch *switch; @end Samstag, 5. Oktober 13
Benutzerdefinierte Objekte im Nib Samstag, 5. Oktober 13
Samstag, 5. Oktober 13
Samstag, 5. Oktober 13
Samstag, 5. Oktober 13
Outlets funktionieren auch Samstag, 5. Oktober 13
@interface NSObject(UINibLoadingAdditions) - (void)awakeFromNib; @end Samstag, 5. Oktober 13
Demo Samstag, 5. Oktober 13
Testen Samstag, 5. Oktober 13
Getrennte Data Source ✓ Samstag, 5. Oktober 13
Kategorie für eine Zelle ✓ Samstag, 5. Oktober 13
View Controller x Samstag, 5. Oktober 13
- (void)testNibLoading; { id mockNavController = [self autoVerifiedMockForClass: [UINavigationController class]];
PhotosViewController *photosViewController = [[PhotosViewController alloc] init]; id photosViewControllerMock = [self autoVerifiedPartialMockForObject: photosViewController]; [[[photosViewControllerMock stub] andReturn:mockNavController] navigationController]; Samstag, 5. Oktober 13
Werkzeuge •Dateien nach Länge sortieren •Bibliothekenkenntniss •Refactoring: AppCode Samstag, 5.
Oktober 13
Werkzeuge •Data Source extrahieren •View Controller Containment •Mehr im Modell,
mehr in Views Samstag, 5. Oktober 13
Über mich •@chriseidhof •http://www.objc.io •http://www.uikonf.com •
[email protected]
Samstag, 5. Oktober 13
Fragen? Samstag, 5. Oktober 13
Vielen Dank Samstag, 5. Oktober 13
Samstag, 5. Oktober 13
Hier ist das Ende Letzte Folie Macoun ⌘ Samstag, 5.
Oktober 13