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
230
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Diet View Controllers
Cocoatalk given at CocoaHeads - Barra da Tijuca
Gustavo Barbosa
November 05, 2014
More Decks by Gustavo Barbosa
See All by Gustavo Barbosa
Arquitetura de Apps em Cenários Offline
barbosa
2
370
CocoaPods: The dependency manager for Objective-C projects
barbosa
0
65
Parse
barbosa
0
140
Introduction to Object
barbosa
0
74
git-flow: a successful branching model
barbosa
4
100
Git: The fast version control system
barbosa
0
250
Clean Code
barbosa
0
140
Other Decks in Technology
See All in Technology
連合学習と機密コンピューティング
lycorptech_jp
PRO
0
120
アンオフィシャルな、オフィシャルからのお願い
wyamazak_devrel
0
110
自宅LLMの話
jacopen
1
590
2026TECHFRESH畢業分享會 - Lightning Talk - 資料也要 CI/CD? 用 Airbyte 自動化資料同步
line_developers_tw
PRO
0
1.1k
スキルと MCP ツール、責務をどう分けるか? AI が迷わないインターフェース設計の戦略
cdataj
1
1.1k
Oracle AI Database@Google Cloud:サービス概要のご紹介
oracle4engineer
PRO
6
1.5k
新しいVibe Codingと”自走”について
watany
6
330
失敗を経て、Harness Engineering で 大切にしたいことを考える / Learning from Failure: What Matters in Harness Engineering
bitkey
PRO
1
370
RAG を使わないという選択肢
tatsutaka
1
250
Bucharest Tech Week 2026 - Reinventing testing practices in the AI era
edeandrea
PRO
1
160
RSA暗号を手計算したくなること、ありますよね?? (20260615_orestudy6_rsa)
thousanda
0
430
人材育成分科会.pdf
_awache
4
260
Featured
See All Featured
A Tale of Four Properties
chriscoyier
163
24k
sira's awesome portfolio website redesign presentation
elsirapls
0
280
<Decoding/> the Language of Devs - We Love SEO 2024
nikkihalliwell
1
240
jQuery: Nuts, Bolts and Bling
dougneiner
66
8.5k
Kristin Tynski - Automating Marketing Tasks With AI
techseoconnect
PRO
0
270
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
4.3k
The Cost Of JavaScript in 2023
addyosmani
55
10k
Intergalactic Javascript Robots from Outer Space
tanoku
273
27k
Everyday Curiosity
cassininazir
0
230
Speed Design
sergeychernyshev
33
1.8k
WCS-LA-2024
lcolladotor
0
630
Leveraging Curiosity to Care for An Aging Population
cassininazir
1
270
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