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
Cocoa Touch: The Good, The Bad and The Ugly
Search
Chris Eidhof | @chriseidhof
December 16, 2013
Programming
2
190
Cocoa Touch: The Good, The Bad and The Ugly
This is a talk I gave at Alt Tech Talks London, as a try out for MCE.
Chris Eidhof | @chriseidhof
December 16, 2013
Tweet
Share
More Decks by Chris Eidhof | @chriseidhof
See All by Chris Eidhof | @chriseidhof
Dutch FP Day 2015
chriseidhof
2
380
Tiny Networking in Swift
chriseidhof
2
19k
Functional Swift - Brooklyn
chriseidhof
3
1.2k
Functional Swift - SF
chriseidhof
6
26k
Functional Swift
chriseidhof
6
1.3k
Functional Swift
chriseidhof
1
150
Functional Programming in Swift
chriseidhof
40
19k
Lighter View Controllers
chriseidhof
4
200
Parsing with Blocks
chriseidhof
2
230
Other Decks in Programming
See All in Programming
Select API from Kotlin Coroutine
jmatsu
1
190
生成AIで日々のエラー調査を進めたい
yuyaabo
0
630
Elixir で IoT 開発、 Nerves なら簡単にできる!?
pojiro
1
150
生成AIコーディングとの向き合い方、AIと共創するという考え方 / How to deal with generative AI coding and the concept of co-creating with AI
seike460
PRO
1
320
Java on Azure で LangGraph!
kohei3110
0
160
deno-redisの紹介とJSRパッケージの運用について (toranoana.deno #21)
uki00a
0
130
地方に住むエンジニアの残酷な現実とキャリア論
ichimichi
2
640
CursorはMCPを使った方が良いぞ
taigakono
0
150
Kotlin エンジニアへ送る:Swift 案件に参加させられる日に備えて~似てるけど色々違う Swift の仕様 / from Kotlin to Swift
lovee
1
250
型付きアクターモデルがもたらす分散シミュレーションの未来
piyo7
0
800
F#で自在につくる静的ブログサイト - 関数型まつり2025
pizzacat83
0
310
たった 1 枚の PHP ファイルで実装する MCP サーバ / MCP Server with Vanilla PHP
okashoi
1
150
Featured
See All Featured
Automating Front-end Workflow
addyosmani
1370
200k
GraphQLの誤解/rethinking-graphql
sonatard
71
11k
Building Applications with DynamoDB
mza
95
6.5k
Fantastic passwords and where to find them - at NoRuKo
philnash
51
3.3k
Large-scale JavaScript Application Architecture
addyosmani
512
110k
Done Done
chrislema
184
16k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
231
53k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
PRO
20
1.3k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
161
15k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
248
1.3M
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
8
660
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
252
21k
Transcript
None
Cocoa Touch The Good, The Bad and The Ugly Chris
Eidhof
Cocoa Touch The Ugly, The Good and The Bad Chris
Eidhof
commit c416c1d259bddaa74833e6df5acd770f85622293 Author: Chris Eidhof <
[email protected]
> Date: Wed Jan 7
11:54:34 2009 +0100 Empty project
None
None
I thought I was a pretty good programmer
I knew PHP, Ruby and Haskell
How hard can it be?
None
The ugly
Example code @interface HiscoreTableViewCell : UITableViewCell { IBOutlet UIImageView *badge;
IBOutlet UILabel *badgeTitle; IBOutlet UILabel *name1; IBOutlet UILabel *name2; IBOutlet UILabel *name3; IBOutlet UILabel *position1; IBOutlet UILabel *position2; IBOutlet UILabel *position3; IBOutlet UILabel *score1; IBOutlet UILabel *score2; IBOutlet UILabel *score3; }
Example code (continued) @property (nonatomic,readonly) UIImageView* badge; @property (nonatomic,readonly) UILabel
*badgeTitle; @property (nonatomic,readonly) UILabel *name1; @property (nonatomic,readonly) UILabel *name2; @property (nonatomic,readonly) UILabel *name3; @property (nonatomic,readonly) UILabel *position1; @property (nonatomic,readonly) UILabel *position2; @property (nonatomic,readonly) UILabel *position3; @property (nonatomic,readonly) UILabel *score1; @property (nonatomic,readonly) UILabel *score2; @property (nonatomic,readonly) UILabel *score3;
Example code (continued) @synthesize badge; @synthesize badgeTitle; @synthesize name1; @synthesize
name2; @synthesize name3; @synthesize position1; @synthesize position2; @synthesize position3; @synthesize score1; @synthesize score2; @synthesize score3;
There's more
//TODO: as of here, it is completely broken if ([gameView
superview] != nil) { [[SoundBoard sharedSoundBoard] startMenuTune]; [menuViewController viewWillAppear:YES]; [gameViewController viewWillDisappear:YES]; [gameView removeFromSuperview]; [gameViewController viewDidDisappear:YES]; [menuViewController viewDidAppear:YES]; } else {
NSURL *cgiUrl = [NSURL URLWithString:POST_SCORE_URL]; NSMutableURLRequest *p = [NSMutableURLRequest requestWithURL:cgiUrl];
[p setTimeoutInterval:4]; [p setHTTPMethod:@"POST"]; [p setHTTPBody:requestData]; NSURLResponse *response = nil; NSError *error = nil; NSData *responseData = [NSURLConnection sendSynchronousRequest:p returningResponse:&response error:&error];
Memory Management 1. Add an instance variable 2. Add a
property 3. Add a synthesize 4. Add a dealloc call
Memory Management 1. Add an instance variable 2. Add a
property 3. Add a synthesize 4. Add a dealloc call
Memory Management
Animations [UIView beginAnimations:@"GameOver" context:NULL]; [UIView setAnimationDuration:0.3]; [UIView setAnimationRepeatCount:2]; [UIView setAnimationRepeatAutoreverses:YES];
// Call animateOtherStuff when the animation is done [UIView setAnimationDelegate:self]; [UIView setAnimationDidStopSelector: @selector(afterGameOverAnimation:finished:context:)];
Animations 2013 [UIView animateWithDuration:0.3 animations:^{ timesUp.alpha = 1; } completion:^(BOOL
finished) { [self.milkGlass removeFromSuperview]; }]
None
The Good
If there's only one thing you'll remember Write code for
the person after you
▸ Write a lot of code ▸ Work with other
people ▸ Write articles ▸ Read books and code
Write a lot of code ▸ Lots of production code
▸ Lots of throwaway code
Throwaway code
Collaborate ▸ With people who are better than you ▸
Or who aren't better than you
Write Forces you to think.
Absolute Knowledge
Perceived Knowledge
Strive to become better
Ship
Frameworks
2013 ▸ Use ARC ▸ Use properties
Core Data
What prevents me from using Core Data at this point
is my concern for scalability and performance. It’s possible I’m just being thick-headed. — Brent Simmons, 27 Sep 2013
So last weekend I switched from SQLite/FMDB to Core Data.
This may come as a surprise. — Brent Simmons, 05 Oct 2013
None
Core Data ▸ Relationships ▸ Batching ▸ NSFetchedResultsControlle r ▸
Speed of use
Code style
My model was the NSURLConnectionDelegate Model should not know about
the webservice
Using NSDictionary everywhere Create value objects
Value Objects @interface Person : NSObject @property (nonatomic,copy,readonly) NSString* name;
@property (nonatomic,strong,readonly) NSDate* birthDate; @property (nonatomic,readonly) NSUInteger numberOfKids; - (instancetype)initWithName:(NSString*)name birthDate:(NSDate*)birthDate numberOfKids:(NSUInteger)numberOfKids; @end
Immutable Objects Use lots of them.
Deep code paths - (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex { if (alertState
== submitScore && game.score > 0) { // 20 lines if (result != nil && [resultKeys containsObject:@"position"] && [resultKeys containsObject:@"neededPoints"] && [resultKeys containsObject:@"deviceHighscore"] && [resultKeys containsObject:@"personalHighscore"]) { // 10 lines if (position == 1) {
Deep code paths Pull out things into separate, well-named methods
Building everything in code Use Interface Builder
Writing fast code Write clear code, only optimize after measuring.
None
Tips and Tricks
Initializers [[HiscoresViewController alloc] initWithNibName:@"HiscoresView" bundle:nil]
Initializers // In HiscoresViewController.m - (id)init { self = [super
initWithNibName:@"HiscoresView" bundle:nil]; if (self) { } return self; }
Use constants if (buttonIndex == 0)
Use constants if (buttonIndex == StartButton)
Pull out variable names if ([game state] == running ||
self.trainingMode)
Pull out variable names BOOL shouldPauseGame = [game state] ==
running || self.trainingMode; if (shouldPauseGame)
Pulling out protocols For example: UITableViewDataSource
@interface FetchedResultsControllerDataSource : NSObject <UITableViewDataSource, NSFetchedResultsControllerDelegate>
- (NSInteger)numberOfSectionsInTableView:(UITableView*)t { return self.fetchedResultsController.sections.count; }
- (NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)sectionIndex { id<NSFetchedResultsSectionInfo> section; section = self.frc.sections[sectionIndex]; return
section.numberOfObjects; }
- (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)ip { id object = [self objectAtIndexPath:indexPath]; id
cell = [tableView dequeueReusableCellWithIdentifier:ruI forIndexPath:ip]; [self.delegate configureCell:cell withObject:object]; return cell; }
Write small files I aim for a 100 line limit
Write small files 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
Write small files find . -name "*.m" -exec wc -l
"{}" \; | sort -n
Keep your view controllers light This is the least reusable
code you'll write
Use protocols instead of inheritance
None
The Bad
None
None
About me ▸ @chriseidhof ▸ http://www.objc.io ▸ http://chris.eidhof.nl
Questions?