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
Diet View Controllers
Search
Gustavo Barbosa
November 05, 2014
Technology
0
230
Diet View Controllers
Cocoatalk given at CocoaHeads - Barra da Tijuca
Gustavo Barbosa
November 05, 2014
Tweet
Share
More Decks by Gustavo Barbosa
See All by Gustavo Barbosa
Arquitetura de Apps em Cenários Offline
barbosa
2
350
CocoaPods: The dependency manager for Objective-C projects
barbosa
0
62
Parse
barbosa
0
130
Introduction to Object
barbosa
0
58
git-flow: a successful branching model
barbosa
4
96
Git: The fast version control system
barbosa
0
240
Clean Code
barbosa
0
130
Other Decks in Technology
See All in Technology
田舎で20年スクラム(後編):一個人が企業で長期戦アジャイルに挑む意味
chinmo
1
120
DATA SUMMIT 2025 生成 AI 時代におけるデータ分析基盤の在り方:オンプレミスからのクラウド移行とモダンデータスタックの実現
coldairflow
0
100
_第4回__AIxIoTビジネス共創ラボ紹介資料_20251203.pdf
iotcomjpadmin
0
170
First-Principles-of-Scrum
hiranabe
1
150
さくらのクラウド開発ふりかえり2025
kazeburo
2
1.3k
LayerX QA Night#1
koyaman2
0
300
Introduce marp-ai-slide-generator
itarutomy
0
170
AI駆動開発ライフサイクル(AI-DLC)の始め方
ryansbcho79
0
280
モダンデータスタックの理想と現実の間で~1.3億人Vポイントデータ基盤の現在地とこれから~
taromatsui_cccmkhd
2
290
AWSに革命を起こすかもしれない新サービス・アップデートについてのお話
yama3133
0
540
なぜ あなたはそんなに re:Invent に行くのか?
miu_crescent
PRO
0
240
20251203_AIxIoTビジネス共創ラボ_第4回勉強会_BP山崎.pdf
iotcomjpadmin
0
170
Featured
See All Featured
How to build a perfect <img>
jonoalderson
1
4.8k
Balancing Empowerment & Direction
lara
5
830
The browser strikes back
jonoalderson
0
280
Collaborative Software Design: How to facilitate domain modelling decisions
baasie
0
110
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
JAMstack: Web Apps at Ludicrous Speed - All Things Open 2022
reverentgeek
1
300
Speed Design
sergeychernyshev
33
1.5k
Applied NLP in the Age of Generative AI
inesmontani
PRO
3
2k
The SEO identity crisis: Don't let AI make you average
varn
0
43
A brief & incomplete history of UX Design for the World Wide Web: 1989–2019
jct
1
270
Dominate Local Search Results - an insider guide to GBP, reviews, and Local SEO
greggifford
PRO
0
27
Lightning talk: Run Django tests with GitHub Actions
sabderemane
0
96
Transcript
Diet View Controllers
We need to talk...
None
MODEL VIEW CONTROLLERS
MASSIVE VIEW CONTROLLERS
MISUSED VIEW CONTROLLERS
MISTREATED VIEW CONTROLLERS
Um belo dia...
XCODE > NEW > PROJECT
Eu preciso de... UM dataSource PARA MINHA UITableView
Eu preciso de... UNS dados VINDOS DO servidor
Eu preciso de... ALGO PARA validar MEUS UITextFields
Eu preciso de... um CLLocationManagerDelegate
Eu preciso de... uma última coisinha BEM PEQUENA
None
THE 900-LINE PROBLEM
"Using #pragma mark is indicative of a failure to adhere
to the Single Responsibility Principle and is a signpost for poor code." -- Brad Grzesiak, Bendyworks
None
1. DATASOURCES E DELEGATES
- (NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section { return photos.count; } - (UITableViewCell *)tableView:(UITableView
*)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { PhotoCell *cell = [tableView dequeueReusableCellWithIdentifier:PhotoCellIdentifier forIndexPath:indexPath]; Photo *photo = [self photoAtIndexPath:indexPath]; cell.label.text = photo.name; return cell; } - (Photo *)photoAtIndexPath:(NSIndexPath *)indexPath { return photos[indexPath.row]; }
@interface ArrayDataSource <UITableViewDataSource> @property (nonatomic, strong) NSArray *items; @property (nonatomic,
strong) NSString *cellIdentifier; @property (nonatomic, copy) void(^cellConfigurationBlock)(id cell, id item); - (instancetype)initWithItems:(NSArray *)items cellIdentifier:(NSString *)cellIdentifier cellConfigurationBlock:(void(^)(id cell, id item))cellConfigurationBlock; @end
@implementation ArrayDataSource - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.items.count; }
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { id cell = [tableView dequeueReusableCellWithIdentifier:self.cellIdentifier forIndexPath:indexPath]; if (self.cellConfigurationBlock) { id item = [self itemAtIndexPath:indexPath]; self.cellConfigurationBlock(cell, item); } return cell; } - (id)itemAtIndexPath:(NSIndexPath *)indexPath { return self.items[indexPath.row]; } @end
configurationBlock = ^(PhotoCell *cell, Photo *item) { cell.label.text = item.name;
}; _dataSource = [[ArrayDataSource alloc] initWithItems:self.photos cellIdentifier:@"PhotoCellIdentifier" cellConfigurationBlock:configurationBlock]; _tableView.dataSource = _dataSource;
2. LÓGICAS DE DOMÍNIO
VIEWCONTROLLER - (Folder *)getRootFolder:(Folder *)folder { if (folder.parent == nil)
return folder; return [self getRootFolder:folder]; }
FOLDER+EXTENSIONS - (Folder *)rootFolder { if (self.parent == nil) return
self; return [self rootFolder]; }
FOLDER @property (nonatomic, readonly) Folder *rootFolder; - (Folder *)rootFolder {
if (self.parent == nil) return self; return self.parent.rootFolder; }
3. LÓGICAS DE SERVIÇO
VIEWCONTROLLER AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; [manager GET:@"http://example.com/profiles.json" parameters:nil success:^(AFHTTPRequestOperation
*operation, id responseObject) { NSLog(@"JSON: %@", responseObject); } failure:^(AFHTTPRequestOperation *operation, NSError *error) { NSLog(@"Error: %@", error); }];
STORES OU REPOSITORIES
CANDIDATOS À STORE WEB SERVICES DATABASES FILESYSTEM LOCATION/MOTION SERVICES CAMERA
PROFILE STORE - (void)fetchAllProfilesWithCallback:(void(^)(NSArray *, NSError *))callbackBlock { [_manager GET:[self
urlForPath:@"profiles.json"] parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) { NSArray *objects = // serialize from responseObject if (callbackBlock) callbackBlock(objects, nil); } failure:^(AFHTTPRequestOperation *operation, NSError *error) { if (callbackBlock) callbackBlock(@[], error); }]; }
PROFILE STORE [[ProfileStore store] fetchAllProfilesWithCallback:^(NSArray *objects, NSError *error){ [_loadingView removeFromSuperview];
if (error) { // log or show error message } else { _tableView.dataSource.items = objects; [_tableView reloadData]; } }];
PROFILE+REPOSITORY + (void)allProfilesWithCallback:(void(^)(NSArray *, NSError *)); + (void)profileForId:(NSUInteger)identifier callback:(void(^)(Profile *,
NSError *)); - (void)deleteWithCallback:(void(^)(NSError *)); - (void)saveWithCallback:(void(^)(NSError *));
4. HIERARQUIA DE VIEWS
None
+ (UIAppearance *)appearance; [UIActivityIndicatorView appearance].color = [UIColor blueColor];
@implementation MyCustomView - (void)awakeFromNib { [super awakeFromNib]; // Customization self.layer.cornerRadius
= 3.0f; self.layer.borderWidth = 1.0f; self.layer.borderColor = [UIColor yellowColor].CGColor; self.layer.masksToBounds = YES; } @end
OBJECTIVE-C IB_DESIGNABLE @interface EllipseView : UIView @property (nonatomic, retain) IBInspectable
UIColor *fillColor; @end
SWIFT @IBDesignable class StarView : UIView { @IBInspectable var starColor:UIColor
required init(coder aDecoder: NSCoder) { starColor = UIColor.yellowColor(); super.init(coder: aDecoder) } override init(frame: CGRect) { starColor = UIColor.yellowColor(); super.init(frame: frame) } }
5. CHILD VIEW CONTROLLERS
None
None
[self addChildViewController:otherViewController]
VIEWCONTROLLER LIFECYCLE - (void)viewDidLoad; - (void)viewWillAppear:(BOOL)animated; - (void)viewDidAppear:(BOOL)animated; - (void)viewWillDisappear:(BOOL)animated;
- (void)viewDidDisappear:(BOOL)animated;
ORIENTATION CHANGES - (void)willRotateToInterfaceOrientation:duration:
STATUS BAR - (UIViewController *)childViewControllerForStatusBarHidden; - (UIViewController *)childViewControllerForStatusBarStyle;
6. INTENTIONS
VIEWCONTROLLER @interface ViewController() <UITextFieldDelegate> @property (nonatomic, weak) IBOutlet UITextField *textField;
@end
VIEWCONTROLLER - (void)viewDidLoad { [super viewDidLoad]; self.person = [[Person alloc]
init]; self.person.name = @"John"; [self updateTextField]; } - (void)updateTextField { self.textField.text = self.person.name; }
VIEWCONTROLLER - (IBAction)reverse:(id)sender { self.person.name = self.textField.text.reversedString; [self updateTextField]; }
- (IBAction)uppercase:(id)sender { self.person.name = self.textField.text.uppercaseString; [self updateTextField]; }
VIEWCONTROLLER - (BOOL)textFieldShouldReturn:(UITextField *)textField { [textField resignFirstResponder]; return NO; }
INTENTION @implementation DismissOnEnterIntention - (BOOL)textFieldShouldReturn:(UITextField *)textField { [textField resignFirstResponder]; return
NO; } @end
INTENTION @interface PersonContainer : NSObject @property (nonatomic, strong) Person *person;
@end @interface UppercaseIntention : NSObject @property (nonatomic, weak) IBOutlet UITextField *textField; @property (nonatomic, weak) IBOutlet PersonContainer *personContainer; @end
@implementation UppercaseIntention - (IBAction)uppercase:(id)sender { self.person.name = self.textField.text.uppercaseString; [self updateTextField];
} - (void)updateTextField { self.textField.text = self.personContainer.person.name; } @end
None
OUTRAS LEITURAS ▸ https://bendyworks.com/single- responsibility-principle-ios/ ▸ http://jaythrash.com/blog/2014/08/25/ building-better-viewcontrollers/ ▸ http://chris.eidhof.nl/posts/intentions.html
▸ http://www.objc.io/issue-1/lighter-view- controllers.html
@GUSTAVOCSB