Objective-C Notes

This is my notes when learning Objective-C. OC stands for Objective-C hereafter.

Prepare

Install XCode with command line tools. (I feel OC very different on other OS ... even no Foundation?)

1

sudo xcode-select -switch /Applications/Xcode.app/Contents/Developer

As an IDE hater ...

12

alias occ='gcc -framework Foundation'

occ *.m

Comparing to C++:

#import is the #pragma once version of #include, but tend to compile faster since #include still need compiler to read the same header.

-framework is an improvement over the traditional trinity: -I, -L, -l.

Method invocation syntax is supposed to make me uncomfortable for a while.

OC method lookup is slower than C++ vtable queries, but most pointers are cached (right) after a lookup, so it's faster than vtable. Cached pointers are still a little bit slower than C++ if C++ knows the target method at compile time. It's like run time optimization vs compile time optimization between the two. However however, since recent C++ compilers are doing more dynamic optimizations, they are not so different in fact ...

@public, @private, @protected sections only for instance variables, inheritance (always like C++ public) can not be tagged with these scope modifiers.

@try, @catch, @throw, @finally for exception handling

12345678910

@try{

@throw[[MyExceptionalloc]init];

}@catch(MyException*e){

...

}@catch(NSException*e){

...

@throw// here means re-throw

}@finally{

...

}

@synchronized modifier for your thread-critical section.

@encode returns const char*. It's for the purpose of interoperability. @encode(X) can be applied to data types, protocols, classes, methods. It's a good way to see the internal representation. Format in [3].

@selector is "a pointer to a method", its type is SEL. Handy for generic algorithms.

123

SELsel=@selector(readDocumentation:);

[orespondsToSelector:sel]

[operformSelector:selwithObject:a];

Create selector from string:

1

NSSelectorFromString(@"haha");

@defs copies the instance variables of a class.

123

structInterfaceAsStruct{

@defs(AnInterface);

}*interfaceAsStruct;

Methods

1234

// decl / impl

-(return_type)msg1:(type1)param1msg2:(type21)param21,(type22)param22

// invoke

[omsg1:param1msg2:param21,param22]

- for instance method.

+ for class method.

self for current object, the hidden parameter, can be changed.

super for parent class.

NO this.

A method call

1

[myWebViewsearchFor:myStringdirection:YEScaseSensitive:NOwrap:YES]

is converted at runtime to this function call:

12

objc_msgSend(myWebView,searchFor:direction:caseSensitive:wrap:,

myString,YES,NO,YES)

Memory Management

initializer:

should return self or nil. A call to super init and nil check is necessary.

method name should init with init

12345678

-(id)initWhatEver...{

// use [[[self class] alloc] init] for dynamic class here

if(self=[superinit]){

...

returnself;

}

returnnil;

}

destructor:

1234

-(void)dealloc{

...

[superdealloc];

}

alloc initializes all the bits to 0, so the pointers are set to nil. init is NOT optional.

12

Klass*obj1=[[Klassalloc]init];

[objrelease]

to use reference counting:

12345

NSAutoreleasePool*pool=[[NSAutoreleasePoolalloc]init];

// ...

[pooldrain];

// ...

[poolrelease];

autorelease is like shared_ptr in Boose but not auto_ptr in STL. The nearest pool on stack is used.

if 2. fails valueForUndefinedKey is called, else an exception is thrown.

Dictionary

1234

iddict=[[NSDictionaryalloc]initWithObjectsAndKeys:

@"k1","v1",

@"k2","v2"];

[dictobjectForKey:@"k1"];

Using immutable dictionary

123

iddict=[[NSMutableDictionaryalloc]initWithCapacity:5];

[dictsetObject:@"obj"forkey:@"obj"]

[dictremoveObjectForKey:@"key"];

Grand Central Dispatch

Block type void (^block)(size_t).

Typedef typedef int (^BT)();.

Block syntax 1 ^{ ... }.

Block syntax 2 ^(p1, p2){ ... }.

Captured variables are read-only

Use __block to declare block-accessible vars

123

__blockinti=1;

BTbt=^{returni++;};

bt();

Protocol Message Qualifiers

in, out, inout, bycopy, byref, oneway

oneway is asynchronous, the result is not immediately expected, hence it must return void.

1

-(onewayvoid)giveMeMoney:(bycopyoutid*)anObject;

inout by default, except const qualifiers.

"Value" Classes

Many classes are designed to contain a hidden cluster of sub-classes, exposing only factory methods.

If an object that is an NSValue that holds a "POD", then it's immutable and no need to hand-release it.

Delegate And Outlet And Action

Being delegated class or protocol:

12

-(id)delegate;

-(void)setDelegate:(id)newDelegate;

Deleted

A Data Source is a delegate that provides data.

An outlet is a property of an object that references another object. The reference is archived through Interface Builder. The connections between the containing object and its outlets are reestablished every time the containing object is unarchived from its nib file. The containing object holds an outlet declared as a property with the type qualifier of IBOutlet and a weak option.

123456789

@interfaceAppController : NSObject{

NSArray*keywords;// can ignore

}

@property(weak)IBOutletNSArray*keywords;

@end

@implementedAppController

@synthesizekeywords;

@end

With some compiler magic, you can create your property without declaring the instance variable when targeting 64-bit.

IBAction is equal to void, but hints XCode to make it connectable in Interface Builder.

Log

Grouping Methods In XCode Jumpbar

An Interface-Builder-Centralised View

When a xib or nib file is unarchived, objects declared in it are allocated and connected like a dependency-injection container. We replace void with IBAction in -(void)action(id)sender, to make it an action, so that interface builder knows it and thus connectable.

Any object can be added into the nib file, especially delegates / controllers. If a control has a delegate attribute (outlet), you can drag and connect to a delegate that have been added into the nib. If an object, especially a controller, needs to visit controls declared in the nib, declare outlets in the controller and connect them.