The document provides an overview of writing idiomatic Objective-C code. It discusses key Objective-C concepts like classes, methods, memory management with ARC, properties, protocols, threading with GCD, blocks, and common design patterns used in Apple's frameworks like MVC, target-action, KVC, and delegation. It emphasizes adopting Apple's conventions for naming, file organization, and other practices to write code that fits with Cocoa frameworks.
2. What This Is
• A guide to writing idiomatic Obj-C code
• Easier to write
• Easier to maintain
• Based on current real-world conventions
3. What This Is Not
• An advocacy piece for Objective-C
• A slam on your favorite language
4. Scope
• Covering Objective-C as used in OS X / iOS
SDKs
• Obj-C is effectively owned by Apple
• Language versions are now tied to releases of
Xcode
• We are not concerned with Obj-C use outside
of Apple ecosystem, nor advocating it
• No history lesson today
6. Classes and Objects
• There is no root class, just the C pointer id
typedef struct objc_class *Class;
typedef struct objc_object {
Class isa;
} *id;
• Can call any method on id
• That said, effectively everything in the SDK
subclasses NSObject
7. Methods / messages
• Call a method on an object with []
•[foo bar];
•[foo bar: 1 withBaz: 2];
• Method calls are really message dispatches
• OK for foo to be nil. Not OK if foo’s class
doesn’t understand bar or bar:withBaz:
• 🙅 Don’t check variables for nil.
8. New objects
• alloc allocates memory for a new object, init
sets up its state. Always do both.
NSMutableArray *mutableSessions =
[[NSMutableArray alloc] init];
• [Class new] is equivalent to [[Class
alloc] init]. 🙅 Nobody uses it.
• Some classes have convenience initializers:
[NSURL URLWithString:] instead of
[[NSURL alloc] initWithString:]
9. Initializers
• Some classes have many initializers for
different purposes
• NSString — initWithData:encoding:,
initWithUTF8String:, etc.
• Designated initializer — the initializer that sets
the most state; other initializers can call this
with default values
10. End-of-life
• dealloc is called when an object is being
destroyed. Override for needed cleanup, end
with [super dealloc]
• 🙆 Can actually count on this, unlike Java’s
finalize()
• Not as big a deal as it used to be (see ARC,
later)
11. Class files
• Typically, you create two files
• Header (.h) for anything pubic. Contains the
Obj-C @interface directive
• Implementation (usually .m) for anything
private. Contains @implementation.
• 🙍 No equivalent of Java protected (i.e.,
only accessible by subclasses) or C++
friendly
12. Importing headers
• C’s #include copies all of a file (usually a .h)
into a compile. Obj-C’s #import is similar, but
avoids copying same file twice.
• 🙆 Always prefer #import in Obj-C code
• “Class.h” looks in current directory,
<Framework/Class.h> searches paths.
• @class is a forward declaration, used to break
circular dependencies in headers
13. Namespaces
• Objective-C does not have namespaces. 🙍
• Accepted practice is class naming convention:
• Apple prefixes classes with 2 uppercase
letters (NS, UI, CA, SK, AV, etc.)
• Your classes should use a 3-letter prefix
• Xcode project creation now prompts for this
15. @implementation
• Method implementations go here, in .m file
• Public methods (from .h) and private
• Private methods used to have to be in order
you called them (caveat on next slide), but
that doesn’t matter with LLVM multi-pass
compile
16. Class Extension
• Like a second @interface, but in the .m file
(and therefore only visible within that file)
• Obj-C’s equivalent to the C forward
declaration
• Not visible to subclasses 🙍
• Mostly used now for private properties (see
later slide)
17. Class Extension
@interface CMHSessionNotesViewController ()
- (IBAction)handleDoneTapped:(id)sender;
@property (weak, nonatomic) IBOutlet UITextView *notesView;
@end
@implementation CMHSessionNotesViewController
- (IBAction)handleDoneTapped:(id)sender {
// method implementation goes here
}
@end
Note: The @interface mus! be named ClassName()
18. Categories
• Allow you to add methods to classes you don’t
own (including Apple’s!)
• Cannot add state (instance variables,
properties)
• Often added to NSString, collections
• By convention, file name is ClassName
+CategoryName
21. Protocols
• List of methods, similar to Java interface
• Group methods together under the
@required and @optional directives.
• Classes declare their implementation of
protocol with <> after declaring subclass
@interface CMHSessionListViewController : UIViewController
<UITableViewDataSource, UITableViewDelegate>
22. Memory Management
• Obj-C uses reference counting, not garbage
collection 🙅
• Any object you create (alloc, copy) must
eventually be release’d.
• To keep an object around, call retain, then
release when done.
• This mostly doesn’t matter anymore, because…
23. Automatic Reference
Counting
• LLVM understands the retain/release rules,
and applies them for you. You no longer write
retain/release.
• It’s still not GC. Objects freed immediately
when reference count equals zero
• Can be enabled at the project or file level
• 🙆 Everyone’s using it now.
24. Properties
• An instance variable combined with getter/
setter methods, all built for you by the
compiler.
• Declaration also specifies threading, memory
management, and writability
• Accessed via the dot operator, not brackets
self.speakerName = [dict valueForKey:@"SpeakerName"];
cell.speakerLabel.text = session.speakerName;
25. Property attributes
• readonly / readwrite
• nonatomic — Concurrent access OK. Used
for UIKit (which should only ever be called
from main thread)
• strong / weak — Whether this object retains
the property, thereby keeping it from being
freed
• Also assign (for primitives), copy
26. Property naming
• For property foo, synthesized ivar is _foo,
getter is foo, setter is setFoo:
• @synthesize directive lets you specify/
rename property variable or methods.
• 🙅 Never use get in a method name
• 💁 For BOOLs, use adjectiv" or #erbsNou$
style, e.g., editable or allowsEditing
27. Other Naming Conventions
• Method names should imply their argument
• What does [sort: YES] mean?
• How about [sort: @”name”] ?
• Aren’t these better as [sortAscending:
YES] , [sortByProperty:@”name”] ?
• Callbacks often start with who’s calling:
tableView:didSelectRowAtIndexPath:
28. Grand Central Dispatch
• Threads are good on multi-core, but how many
threads are ideal?
• The OS is in the best position to know, so
let it decide
• Organize work into discrete blocks, give it to
the system and let it figure out how to run it
29. Blocks
• Closures for C, or function pointers that
capture their enclosing scope
• Start with ^ character, then return types,
parameter list, and code in {…}.
• Commonly used as “completion handlers”
for long-running operations (network,
media, etc.)
• Example to follow…
30. UIKit Threading
• All access to UIKit must be on the main
thread (sound like AWT/Swing, anyone?)
• UI events will come from this thread.
Network callbacks often won’t.
• Long-running tasks must not be on main
thread, or they’ll block the UI (sound like
AWT/Swing, anyone?) 🙍
31. GCD Recipes
• Put work on other threads with C function
dispatch_async(), which takes a GCD
queue and a block to execute
• To get off main thread, get queue with
dispatch_get_global_queue()
• To get o$ main thread, use
dispatch_get_main_queue()
32. Off main queue and back on
dispatch_async(dispatch_get_global_queue
(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
^{
// perform long-running task
dispatch_async(dispatch_get_main_queue(), ^{
// update the ui
});
});
34. Apple still loves C
• Utility routines that don’t need to be tied to a class are
often C functions: e.g, NSLog()
• High-performance frameworks are in C
• Constants may be enums in a typedef
enum {
NSOrderedAscending = -1,
NSOrderedSame,
NSOrderedDescending
};
typedef NSInteger NSComparisonResult;
35. All objects are pointers
• All Obj-C object declarations take *, because
they’re pointers
• Except for type id, which is already a pointer
• ** means “pointer to object”, used when
populating as a side effect
NSError *jsonErr = nil;
id jsonObject = [NSJSONSerialization JSONObjectWithData:jsonData
options:0
error:&jsonErr];
36. A Slide on Frameworks
• Apple’s stuff is packaged as “frameworks” (not
“libraries”), in .framework bundles
• Framework = executable library + headers +
documentation + resources (graphics, sound,
localizations, etc.)
• The bigs: UIKit, Foundation
• Not easy to create your own with Xcode
38. Target-Action
• Indicates how an event (like a button tap) is to
be handled. Sender is provided with:
• Action: a method signature as a @selector
• Target: object to call the method on
• Method signature must be known in advance.
UIKit most commonly uses
-(IBAction) action:(id) sender
39. Key-Value Coding
• Allows access into nested object structures as a
dot-separated string (e.g., “user.name” in a
tweet returned by Twitter API)
• Each key segment is fetched by
valueForKey:, which looks for property or
ivar of that name (or could be overridden)
• Used for sorting collections, also with “magic”
key path members (“@avg.value”,
“@min.date”)
40. Delegation
• Common means of extending a class’
functionality, by making defined callbacks to
one object that you write.
• Methods usually collected in a protocol
• You declare that your object implements the
protocol, then set it as the delegate
property of the other class
• 🙅 We don’t subclass much in iOS. This is why.
41. Completion Handler
• A block to be completed when a long-running
task (animation, network access) completes.
• Parameters to the block may provide results
of the task
• For anything else you need, remember that
everything in scope prior to the block’s
creation is available inside the block
43. Modern Obj-C habits
• Only use .h for public stuff
• All private stuff (properties, methods) can
now go in a class extension in the .m
• Prefer private properties to instance variables
• Get off the main thread; blocks are cheap
44. Old Habits Die Hard
• Obj-C literals in Xcode 4.4
• Arrays: @[…] instead of [NSArray
arrayWithObjects:…]
• Dictionaries @{ name1:value1,
name2:value2, …} instead of
[NSDictionary
dictionaryWithValuesAndKeys:…]
• Accessors: array[i], dict[“key”]
45. Final Thoughts
• Obj-C / Cocoa have consistent idioms you’ll see
in Apple’s frameworks.
• Adopt them, emulate them, don’t fight them
• Like any language, Obj-C has its share of good
and bad.
• Unfamiliar != bad