KEMBAR78
Objective-C Is Not Java | PDF
Objective-C Is Not Java
  Chris Adamson • @invalidname
         CodeMash 2013
What This Is


• A guide to writing idiomatic Obj-C code
  • Easier to write
  • Easier to maintain
• Based on current real-world conventions
What This Is Not



• An advocacy piece for Objective-C
• A slam on your favorite language
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
Start with a Demo
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
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.
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:]
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
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)
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
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
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
CMHSession.h
#import <Foundation/Foundation.h>

@interface CMHSession : NSObject

@property (copy) NSString *speakerName;
@property (copy) NSString *title;
@property (copy) NSString *abstract;
@property (copy) NSString *room;
@property (strong) NSDate *start;
@property (copy) NSString *technology;
@property (copy) NSURL *url;

@property (copy) NSString *userComments;
@property (assign) NSInteger *userScore;

-(id) initWithJSONDictionary: (NSDictionary*) dict;

@end
@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
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)
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()
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
NSArray+BoundsChecking.h


  #import <Foundation/Foundation.h>
  
  @interface NSArray (BoundsChecking)
  -(id) firstObject;
  @end
NSArray+BoundsChecking.m

 #import "NSArray+BoundsChecking.h"
 
 @implementation NSArray (BoundsChecking)
 -(id) firstObject {
 
 if ([self count] == 0) {
 
 
 return nil;
 
 }
 
 return [self objectAtIndex:0];
 }
 @end
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>
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…
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.
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;
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
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
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:
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
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…
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?) šŸ™
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()
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

 });
});
Speaking of C




 Available on iBooks
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;
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];
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
Apple’s Favorite Patterns

• MVC (you all know this šŸ™†)
• Target-Action
• Key-Value Coding
• Delegation
• Completion Handler
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
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ā€)
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.
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
A look inside our demo
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
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ā€]
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
Learn More!




Available on iBooks   Available at pragprog.com

Objective-C Is Not Java

  • 1.
    Objective-C Is NotJava Chris Adamson • @invalidname CodeMash 2013
  • 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 IsNot • An advocacy piece for Objective-C • A slam on your favorite language
  • 4.
    Scope • Covering Objective-Cas 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
  • 5.
  • 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 • allocallocates 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 classeshave 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 iscalled 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 doesnot 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
  • 14.
    CMHSession.h #import <Foundation/Foundation.h> @interface CMHSession: NSObject @property (copy) NSString *speakerName; @property (copy) NSString *title; @property (copy) NSString *abstract; @property (copy) NSString *room; @property (strong) NSDate *start; @property (copy) NSString *technology; @property (copy) NSURL *url; @property (copy) NSString *userComments; @property (assign) NSInteger *userScore; -(id) initWithJSONDictionary: (NSDictionary*) dict; @end
  • 15.
    @implementation • Method implementationsgo 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 • Likea 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 youto 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
  • 19.
    NSArray+BoundsChecking.h #import<Foundation/Foundation.h> @interface NSArray (BoundsChecking) -(id) firstObject; @end
  • 20.
    NSArray+BoundsChecking.m #import "NSArray+BoundsChecking.h" @implementation NSArray (BoundsChecking) -(id) firstObject { if ([self count] == 0) { return nil; } return [self objectAtIndex:0]; } @end
  • 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-Cuses 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 instancevariable 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 • Forproperty 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 forC, 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 • Allaccess 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 • Putwork 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 queueand 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 }); });
  • 33.
    Speaking of C Available on iBooks
  • 34.
    Apple still lovesC • 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 arepointers • 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 onFrameworks • 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
  • 37.
    Apple’s Favorite Patterns •MVC (you all know this šŸ™†) • Target-Action • Key-Value Coding • Delegation • Completion Handler
  • 38.
    Target-Action • Indicates howan 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 • Allowsaccess 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 meansof 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 • Ablock 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
  • 42.
    A look insideour demo
  • 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 DieHard • 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
  • 46.
    Learn More! Available oniBooks Available at pragprog.com