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
220
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
340
CocoaPods: The dependency manager for Objective-C projects
barbosa
0
59
Parse
barbosa
0
130
Introduction to Object
barbosa
0
55
git-flow: a successful branching model
barbosa
4
94
Git: The fast version control system
barbosa
0
240
Clean Code
barbosa
0
130
Other Decks in Technology
See All in Technology
株式会社ログラス - 会社説明資料【エンジニア】/ Loglass Engineer
loglass2019
4
65k
S3アクセス制御の設計ポイント
tommy0124
3
210
「全員プロダクトマネージャー」を実現する、Cursorによる仕様検討の自動運転
applism118
22
12k
JTCにおける内製×スクラム開発への挑戦〜内製化率95%達成の舞台裏/JTC's challenge of in-house development with Scrum
aeonpeople
0
270
AWSで始める実践Dagster入門
kitagawaz
1
750
使いやすいプラットフォームの作り方 ー LINEヤフーのKubernetes基盤に学ぶ理論と実践
lycorptech_jp
PRO
1
180
サラリーマンの小遣いで作るtoCサービス - Cloudflare Workersでスケールする開発戦略
shinaps
2
470
スタートアップこそ全員で Platform Engineering スピードと持続性を両立する文化の作り方
anizozina
1
340
Snowflake×dbtを用いたテレシーのデータ基盤のこれまでとこれから
sagara
0
140
Rustから学ぶ 非同期処理の仕組み
skanehira
1
160
Oracle Base Database Service 技術詳細
oracle4engineer
PRO
10
75k
機械学習を扱うプラットフォーム開発と運用事例
lycorptech_jp
PRO
0
710
Featured
See All Featured
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
PRO
23
1.4k
Build your cross-platform service in a week with App Engine
jlugia
231
18k
Stop Working from a Prison Cell
hatefulcrawdad
271
21k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
35
3.1k
The Power of CSS Pseudo Elements
geoffreycrofte
77
6k
Building an army of robots
kneath
306
46k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
15
1.7k
StorybookのUI Testing Handbookを読んだ
zakiyama
31
6.1k
Git: the NoSQL Database
bkeepers
PRO
431
66k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
PRO
188
55k
Music & Morning Musume
bryan
46
6.8k
KATA
mclloyd
32
14k
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