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
61
git-flow: a successful branching model
barbosa
4
97
Git: The fast version control system
barbosa
0
240
Clean Code
barbosa
0
130
Other Decks in Technology
See All in Technology
生成AIを活用した音声文字起こしシステムの2つの構築パターンについて
miu_crescent
PRO
1
100
Tebiki Engineering Team Deck
tebiki
0
24k
小さく始めるBCP ― 多プロダクト環境で始める最初の一歩
kekke_n
1
360
あたらしい上流工程の形。 0日導入からはじめるAI駆動PM
kumaiu
5
760
OCI Database Management サービス詳細
oracle4engineer
PRO
1
7.3k
使いにくいの壁を突破する
sansantech
PRO
1
120
Digitization部 紹介資料
sansan33
PRO
1
6.8k
コスト削減から「セキュリティと利便性」を担うプラットフォームへ
sansantech
PRO
3
1.3k
Deno・Bunの標準機能やElysiaJSを使ったWebSocketサーバー実装 / ラーメン屋を貸し切ってLT会! IoTLT 2026新年会
you
PRO
0
300
オープンウェイトのLLMリランカーを契約書で評価する / searchtechjp
sansan_randd
3
650
Data Hubグループ 紹介資料
sansan33
PRO
0
2.7k
クレジットカード決済基盤を支えるSRE - 厳格な監査とSRE運用の両立 (SRE Kaigi 2026)
capytan
6
2.6k
Featured
See All Featured
30 Presentation Tips
portentint
PRO
1
210
SEO in 2025: How to Prepare for the Future of Search
ipullrank
3
3.3k
Six Lessons from altMBA
skipperchong
29
4.1k
Discover your Explorer Soul
emna__ayadi
2
1.1k
Music & Morning Musume
bryan
47
7.1k
職位にかかわらず全員がリーダーシップを発揮するチーム作り / Building a team where everyone can demonstrate leadership regardless of position
madoxten
57
50k
RailsConf 2023
tenderlove
30
1.3k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
666
130k
Large-scale JavaScript Application Architecture
addyosmani
515
110k
Why Your Marketing Sucks and What You Can Do About It - Sophie Logan
marketingsoph
0
72
Side Projects
sachag
455
43k
Unlocking the hidden potential of vector embeddings in international SEO
frankvandijk
0
170
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