Cocoa From Scratch

It’s 2008: You’re reading Objective-C tutorials on Cocoa Dev Central, Lucida Grande is the system font and ARC doesn’t exist yet.

You want to write a nice, native Cocoa application. Where do you start?

int main(int argc, char **argv) {
    printf("Hello %s\n", argv[1]);
}
$ clang main.c
$ ./a.out world
Hello world

argv[0] is the program name, so the first argument starts at argv[1].

C is great and all, but what if we want to start interacting with OS X? We can do more interesting stuff with libraries.

Libraries

Libraries on OS X come in two flavours, static and dynamic.

Static library archives

// foo.c
int add(int a, int b) {
    return a + b;
}
$ clang -c foo.c

We’ve successfully compiled our code into an object file, a.k.a. machine code that Mach based kernels can understand. The -c flag passed to clang tells it to only compile it: by default it will also try to link it too, but we’re going to do that by hand.

$ objdump -d foo.o

foo.o:  file format Mach-O 64-bit x86-64

Disassembly of section __TEXT,__text:
_add:
       0:   55  pushq   %rbp
       1:   48 89 e5    movq    %rsp, %rbp
       4:   89 7d fc    movl    %edi, -4(%rbp)
       7:   89 75 f8    movl    %esi, -8(%rbp)
       a:   8b 75 fc    movl    -4(%rbp), %esi
       d:   03 75 f8    addl    -8(%rbp), %esi
      10:   89 f0   movl    %esi, %eax
      12:   5d  popq    %rbp
      13:   c3  retq

objdump -d disassembles the object file so we can look inside. Here, foo.o has one symbol exported: _add. Now say we want to reuse this function in an executable. Without having the object file, we can compile our executable as long as we tell the compiler what this function looks like via a header file.

// foo.h
int add(int a, int b);

// main.c
#include <stdio.h>
#include "foo.h"

int main() {
    printf("%i\n", add(10, 32));
};
$ clang -c main.c 
$ objdump -d main.o

main.o: file format Mach-O 64-bit x86-64

Disassembly of section __TEXT,__text:
_main:
       0:   55  pushq   %rbp
       1:   48 89 e5    movq    %rsp, %rbp
       4:   48 83 ec 10     subq    $16, %rsp
       8:   bf 0a 00 00 00  movl    $10, %edi
       d:   be 20 00 00 00  movl    $32, %esi
      12:   e8 00 00 00 00  callq   0 <_main+0x17>
      17:   48 8d 3d 16 00 00 00    leaq    22(%rip), %rdi
      1e:   89 c6   movl    %eax, %esi
      20:   b0 00   movb    $0, %al
      22:   e8 00 00 00 00  callq   0 <_main+0x27>
      27:   31 f6   xorl    %esi, %esi
      29:   89 45 fc    movl    %eax, -4(%rbp)
      2c:   89 f0   movl    %esi, %eax
      2e:   48 83 c4 10     addq    $16, %rsp
      32:   5d  popq    %rbp
      33:   c3 

Check out how it’s loading in 10 and 32 into the registers before calling the mysterious <_main+0x17>. This is where _add should be, but we haven’t included it into the program yet. We do this by linking it:

$ ld foo.o main.o /usr/lib/libc.dylib
$ ./a.out
42

The command above links the foo object file, main object file, as well as the C standard library that contains the printf function that we use. (It’s a dynamic library - we’ll see more of them shortly) Now if we run objdump -d a.out, we can see that foo.o has been copied into a.out, and our <_main+0x17> has been replaced with <_add>.

_add:
    1f50:   55  pushq   %rbp
    1f51:   48 89 e5    movq    %rsp, %rbp
    1f54:   89 7d fc    movl    %edi, -4(%rbp)
    1f57:   89 75 f8    movl    %esi, -8(%rbp)
    1f5a:   8b 75 fc    movl    -4(%rbp), %esi
    1f5d:   03 75 f8    addl    -8(%rbp), %esi
    1f60:   89 f0   movl    %esi, %eax
    1f62:   5d  popq    %rbp
    1f63:   c3  retq

_main:
    1f70:   55  pushq   %rbp
    1f71:   48 89 e5    movq    %rsp, %rbp
    1f74:   48 83 ec 10     subq    $16, %rsp
    1f78:   bf 0a 00 00 00  movl    $10, %edi
    1f7d:   be 20 00 00 00  movl    $32, %esi
    1f82:   e8 c9 ff ff ff  callq   -55 <_add>
    1f87:   48 8d 3d 38 00 00 00    leaq    56(%rip), %rdi
    1f8e:   89 c6   movl    %eax, %esi
    1f90:   b0 00   movb    $0, %al
    1f92:   e8 0d 00 00 00  callq   13
    1f97:   31 f6   xorl    %esi, %esi
    1f99:   89 45 fc    movl    %eax, -4(%rbp)
    1f9c:   89 f0   movl    %esi, %eax
    1f9e:   48 83 c4 10     addq    $16, %rsp
    1fa2:   5d  popq    %rbp
    1fa3:   c3  retq

What if we want to further expand our rich suite of arithmetic functions in our library, and include a sub function, compiled into another object file?

// sub.c
int sub(int a, int b) {
    return a - b;
}

// foo.h
int add(int a, int b);
int sub(int a, int b);

// main.c 
#include <stdio.h>
#include "foo.h"

int main() {
    int x = sub(42, 12);
    printf("%i\n", add(3, x));
};

We could compile and then link together all the different object files like fools:

$ ld main.o foo.o sub.o /usr/lib/libc.dylib

But if we had a large library with lots of object files, this would be a pain. Let’s create a library archive instead:

$ ar rc foo.a foo.o sub.o
$ ld foo.a main.o /usr/lib/libc.dylib
$ ./a.out
33

Congratulations, you’ve just created and linked your first static library! Instead of jumping through the whole clang -c & ld malarkey, you can just tell clang to link it for you with the library:

$ mv foo.a libfoo.a
$ clang -L. -lfoo main.c

-L. tells clang to look for libraries inside the current directory, ., and -lfoo tells it to load the library called libfoo. You’ll see this lib prefix all over the place, especially inside /usr/lib/.

dylibs

Often we don’t want to copy over the library code into our executable. If every app on OS X did that then you would find yourself with a lot of duplicate functions from Cocoa. Instead we can use a dynamic library, where our executable just points to the library containing the Mach-O code whenever it needs to call a function.

$ clang foo.c sub.c -dynamiclib -o libfoo.dylib
$ clang -L -lfoo main.c
$ ./a.out
33

Now if you run objdump -d a.out, you’ll notice _add and _sub are nowhere to be found. Try running a.out from another directory:

$ cd ../
$ ./dylib-experiments/a.out 
dyld: Library not loaded: libfoo.dylib
  Referenced from: /Users/luke/Source/./dylib-experiments/a.out
  Reason: image not found
Abort trap: 6

dyld, the tool that manages loading dynamic libraries, can’t find our library since it’s not in the immediate directory. However we can give it a hint by setting an environment variable:

$ export DYLD_LIBRARY_PATH=dylib-experiments
$ ./dylib-experiments/a.out 
33

Frameworks

A framework is like a library but can contain additional header files, extra resources and documentation. They are also a type of bundle, a feature carried over from NeXTSTEP. (More info on that later)

CoreFoundation

Take the humble CoreFoundation for example:

#include <CoreFoundation/CoreFoundation.h>

int main(int argc, char **argv) {
  CFStringRef str = CFStringCreateWithCString(NULL, argv[1], kCFStringEncodingUTF8);
  printf("Hello %s\n", CFStringGetCStringPtr(str, kCFStringEncodingUTF8));
}

The first parameter of CFStringCreateWithCString is a CFAllocator (whatever that is), but thankfully we can leave it as NULL to use the default one if we don’t want to deal with it. You’ll see this happening with some other CoreFoundation APIs.

Anyway, we’ll need to link the CoreFoundation framework when we compile this time.

clang -framework CoreFoundation main.c
./a.out "Core Foundation"
Hello Core Foundation

OK cool, but why did we need Core Foundation for that? Let’s do something a bit more interesting.

  CFLocaleRef locale = CFLocaleCopyCurrent();
  CFNumberFormatterRef formatter = CFNumberFormatterCreate(NULL, locale, kCFNumberFormatterSpellOutStyle);
  CFNumberRef number = CFNumberFormatterCreateNumberFromString(NULL, formatter, str, NULL, kCFNumberFormatterParseIntegersOnly);

  int value;
  CFNumberGetValue(number, kCFNumberSInt64Type, &value);

  printf("%i\n", value);
}
./a.out "one hundred and sixty-three"
163

Try changing up the locale.

CFLocaleRef locale = CFLocaleCreate(NULL, CFSTR("zh_CN"));
./a.out 九万二千
92000

CoreFoundation isn’t just for working with strings, it provides a host of powerful APIs for working with locales, formatting, dates/times and more.

To be safe we should analyze our code.

$ clang --analyze cf.c
main.c:4:21: warning: Potential leak of an object stored into 'str'
  CFStringRef str = CFStringCreateWithCString(NULL, argv[1], kCFStringEn...
                    ^
main.c:6:24: warning: Potential leak of an object stored into 'locale'
  CFLocaleRef locale = CFLocaleCopyCurrent();
...
main.c:11:3: warning: A CFNumber object that represents a 64-bit integer is used
      to initialize a 32-bit integer; 32 bits of the CFNumber value will
      overwrite adjacent storage
  CFNumberGetValue(number, kCFNumberSInt64Type, &value);

Oh right, this is C so we need to keep track of memory ourselves. We’ll need to release anything we create otherwise we will end up leaking memory.

CFRelease(str);
CFRelease(locale);
CFRelease(formatter);
CFRelease(number);

Clang also helpfully pointed out that we were trying to get a 64 bit integer from CFNumberRef into a 32 bit int, so let’s fix that.

CFNumberGetValue(number, kCFNumberSInt32Type, &value);
$ clang --analyze main.c
>

Perfect. Now let’s try out some more frameworks, like Core Services which lets us interact with OS X[^1]. We can use it to open URLs in the user’s default browser:

[^1] It’s still 2008

#include <CoreFoundation/CFURL.h>
#include <CoreServices/CoreServices.h>

int main(int argc, char **argv) {

  CFMutableStringRef str = CFStringCreateMutable(NULL, 0);
  CFStringAppend(str, CFSTR("https://duckduckgo.com?q="));
  
  for(int i = 1; i < argc; i++) {
    CFStringRef query = CFStringCreateWithCString(NULL, argv[i], kCFStringEncodingUTF8);
    CFStringAppend(str, query);
    CFStringAppend(str, CFSTR("+"));
    CFRelease(query);
  }
  
  CFURLRef url = CFURLCreateWithString(NULL, str, NULL);
  LSOpenCFURLRef(url, 0);

  CFRelease(str);
  CFRelease(url);

  return 0;
}
$ clang -o search -framework CoreFoundation -framework CoreServices search.c
$ ./search little bites of cocoa

Cool. Repeatedly running these clang commands is starting to get tedious, we should make a makefile.

make

search: search.c
    clang -o search -framework CoreFoundation -framework CoreServices search.c

This rule says that if we want to make the file search, we will need the file (dependency) search.c. The indented line below specifies how we make it, although you can have multiple lines. The analogy here is kind of like a recipe:

$ make search
clang -o search -framework CoreFoundation -framework CoreServices search.c
$ ./search makefile tutorial

But what if we want to compile something other than search.c? Let’s make this more general.

%: %.c
    clang -o $@ -framework CoreFoundation -framework CoreServices $<

% is a wildcard (think *), and inside the rules $@ and $< get replaced with the destination and dependency respectively.

$ make main
clang -o main -framework CoreFoundation -framework CoreServices main.c

Nice and reusable. A nice thing is that if we run make main again and none of the dependencies have changed (i.e. main.c), make won’t bother rebuilding it.

$ make main
make: `main' is up to date.

Objective-C

Time to write some Objective-C.

#include <objc/objc-runtime.h>
#include <stdio.h>

char* implementation(id self, SEL _cmd, int x) {
  if (x > 5)
    return "Hello world!";
  else
    return "Goodbye world!";
}

int main() {
  Class cls = objc_allocateClassPair(objc_getClass("NSObject"), "Foo", 0);
  objc_registerClassPair(cls);

  class_addMethod(cls, sel_getUid("bar"), (IMP)implementation, "*@:i");

  id obj = objc_msgSend((id)cls, sel_getUid("alloc"));
  obj = objc_msgSend(obj, sel_getUid("init"));
  
  char* result = (char*)objc_msgSend(obj, sel_getUid("bar"), 42);
  printf("%s\n", result);
}
$ clang -o objc -lobjc objc.c
$ ./objc
Hello world!

Wait what? This probably isn’t what you expected when you think of Objective-C. However, it shows us how Objective-C’s runtime, libobjc, works behind the scenes. It highlights some key things about Objective-C:

  1. Objective-C is really dynamic - we can create classes and methods on the fly with objc_registerClassPair and objc_addMethod
  2. It mostly works by sending messages to and from objects with objc_msgSend (you might have seen this guy in a crash log before)
  3. It uses selectors to refer to methods on objects, here we get them with sel_getUid
  4. Methods are defined by IMPs (implementations) which can just be function pointers

There’s a lot going on here so let’s take a deeper dive into some of the methods.

objc_allocateClassPair and objc_registerClassPair create a new class that subclasses a given class. We give it a name too. The 0 at the end for is how many extra bytes we want for ivars (instance variables), which we don’t have any of. It returns a Class.

class_addMethod takes a class and adds a method to it. You need to specify the selector (SEL) for it, which is kind of like a name for it. sel_getUid gives us one from a string. The implementation (IMP) is a function pointer, and in Objective-C all methods need to take in an object and a selector as the first two arguments. The first one is an object (id), and it’s self - that self keyword you’ve been using has actually been a parameter all this time, just like in Python. On the other hand _cmd is not so common. It contains the selector of the method that is being called, which may seem kind of pointless. However, one of the wierd advantages of Objective-C being super dynamic is that you can “swizzle” methods and swap out their implementations, and the _cmd parameter lets you know what the original method that was being called before you hijacked it. The last parameter is the type signature, which we specify with this encoded string thing. The first character is the return type, and * represents char*. Every character after that is an argument. @ is an object for self, : is a selector for _cmd and i is our humble int, x.

objc_msgSend takes an object and sends a message to it at a selector, along with any arguments. It’s what happens when you call a method like [obj bar:42];.

You might have noticed when call a class method like alloc, we pass in a Class but just cast it to an object, id. That’s because in Objective-C, classes are objects.

We could have written something in actual Objective-C like this:

objc.m

#import <objc/NSObject.h>
#import <stdio.h>

@interface Foo: NSObject
- (char*)bar:(int)x;
@end

@implementation Foo
- (char*)bar:(int)x {
    if (x > 5)
        return "Hello world!";
    else
        return "Goodbye world!";
}
@end

int main() {
    Foo *obj = [Foo alloc];
    char* result = [obj bar:42];
    printf("%s\n", result);
}

Compile it in the same way you did with C:

$ clang -o objc -lobjc objc.m
$ ./objc
Hello world!

The C code that we wrote doesn’t exactly do the same thing as the Objective-C code. If we look at the assembly generated when we compile it, we can see that it still calls objc_msgSend from the runtime library:

$ clang -S objc.m
callq   *_objc_msgSend@GOTPCREL(%rip)

The main difference between this and the C version is that the C version creates the classes and methods on the fly, but here it actually lays out the classes and selectors at compile time:

...
.section    __TEXT,__objc_methname,cstring_literals
L_OBJC_METH_VAR_NAME_:                  ## @OBJC_METH_VAR_NAME_
.asciz  "bar"

.section    __TEXT,__objc_methtype,cstring_literals
L_OBJC_METH_VAR_TYPE_:                  ## @OBJC_METH_VAR_TYPE_
.asciz  "*16@0:8"
.section    __TEXT,__objc_classname,cstring_literals
L_OBJC_CLASS_NAME_:                     ## @OBJC_CLASS_NAME_
.asciz  "Foo"

.section    __DATA,__objc_const
.p2align    3               ## @"\01l_OBJC_METACLASS_RO_$_Foo"
...

You may have spotted that at the top of the Objective-C code we use #import. It does the same thing as #include but won’t include files more than once, so we don’t have to worry about recursive includes. We also no longer need to import the runtime headers since we’re no longer directly calling objc_msgSend, but instead we need to import the headers for NSObject.
If you’ve written Objective-C before, you’ve probably inherited from NSObject all over the place without ever having to explicitly import it. That’s usually because importing an Objective-C framework such as Foundation will include it for you. Speaking of which, have you ever wondered why we always inherit from NSObject?

NSObject

NSObject is a root class in Objective-C, meaning that it has no superclass, and most of the time we build classes on top of it by subclassing it. However we can also create our own root classes - we could have skipped NSObject and just written this instead:

@interface Foo
- (char*)bar;
@end

Or when using objc_allocateClassPair we could have passed in NULL for the parent class. If you try to compile this, clang will give you a warning but it will still work:

objc.m:4:12: warning: class 'Foo' defined without specifying a base class [-Wobjc-root-class]
@interface Foo
           ^
objc.m:4:15: note: add a super class to fix this problem
@interface Foo
              ^
               : NSObject 

The shit hits the fan when we try to run it:

$ ./objc
objc[6045]: +[Foo alloc]: unrecognized selector sent to instance 0x106bc30f8 (no message forward handler is installed)

As it turns out NSObject provides lots of boilerplate methods like alloc and init, as well as the methods described in NSObjectProtocol. NSObjectProtocol describes a bunch of functions that the runtime needs to query information about your class, stuff like what selectors it responds to, what its subclass is and so on. So if your root class doesn’t implement this, be prepared for snarky error messages from the runtime and a generally bad time.

objc[52822:942545] *** NSForwarding: warning: object 0x10c0f2100 of class 'Foo' does not implement methodSignatureForSelector: -- trouble ahead
objc[52822:942545] *** NSForwarding: warning: object 0x10c0f2100 of class 'Foo' does not implement doesNotRecognizeSelector: -- abort

You can implement this yourself but its not a great idea unless you really know what you’re doing. Hence why we usually let NSObject take care of this.

Now that we know CoreFoundation and Objective-C, lets try working with the two together:

#include <CoreFoundation/CoreFoundation.h>

int main(int argc, char **argv) {
    CFStringRef str = CFStringCreateWithCString(NULL, argv[1], kCFStringEncodingUTF8);
    printf("Hello %s\n", CFStringGetCStringPtr(str, kCFStringEncodingUTF8));
    return 0;
}

Hold on. This is exactly the same code as the one we did in C. Objective-C is a superset of C, so any valid C code will still compile fine:

$ clang -o cf -framework Framework cf.m
$ ./cf again
Hello again

But none of this takes advantage of Objective-C. And thats where Foundation comes in.

Foundation

Foundation, the sequel to CoreFoundation and the prequel to Cocoa, is the Objective-C framework that provides all of those NS classes you know and love. Most of these NS classes build on top of the underlying CoreFoundation structs that we saw earlier, by providing Objective-C classes and methods for them.

#import <Foundation/Foundation.h>

int main(int argc, char **argv) {
    NSString *str = [[NSString alloc] initWithUTF8String: argv[1]];
    printf("Hello %s\n", [str UTF8String]);
}

We’re going to be working with Foundation for a bit so let’s update our makefile:

%: %.m
    clang -g -o $@ -framework Foundation $<
$ make foundation
clang -g -o foundation -framework Foundation foundation.m
$ ./foundation Foundation
Hello Foundation

In case you’re still curious here’s how we can do it directly through the Objective-C runtime:

#include <objc/objc-runtime.h>
#include <stdio.h>

int main() {
    Class cls = objc_getClass("NSString");
    id obj = objc_msgSend((id)cls, sel_getUid("alloc"));
    obj = objc_msgSend(obj, sel_getUid("initWithUTF8String:"), "Hello world!");

    printf("%s\n", (char*)objc_msgSend(obj, sel_getUid("UTF8String")));
}

The classes in Foundation are interchangable with their corresponding CoreFoundation types - You can cast a CFStringRef to a NSString, and vice-versa. You can even swap CFRelease and [NSObject release]. This is called toll-free bridging:

#import <Foundation/Foundation.h>

int main() {
    CFDateRef date = CFDateCreate(kCFAllocatorDefault, 210678000);
    NSDate *newDate = [NSDate dateWithTimeInterval:60 sinceDate:(NSDate*)date];
    printf("%s\n", [[newDate description] UTF8String]);
    [(id)date release];
}
$ make bridging
clang -g -o bridging -framework Foundation bridging.m
$ ./bridging   
2007-09-05 09:41:00 +0000

NSLog

On the side, if you’ve programmed in Objective-C before, you may have noticed we’ve been avoiding NSLog. This is because I personally find its purpose is for logging error messages, not for debugging or user facing output. You also get some extra garbage in the output and it ends up being written to the system console which is a bit overkill for our purposes.

Memory management

Let’s make the Objective-C experience more authentic: Remember when I said ARC didn’t exist yet? If you’ve been compiling the Objective-C code examples from the year 2010 or beyond, its probably been turned on by default. There’s a flag we can set to disable it:

%: %.m
clang -o $@ -framework Foundation -fno-objc-arc -g $<

The -g flag was also added to have the compiler output .dysmb symbols: these will be helpful when using external tools to debug and investigate our code later on. Now let’s start leaking memory!

#import <Foundation/Foundation.h>

NSMeasurement* measureString(NSString *string) {
    double length = [string length];
    NSUnit *unit = [NSUnitLength yards];
    return [[NSMeasurement alloc] initWithDoubleValue:length unit:unit];
}

int main() {
    NSMeasurementFormatter *formatter = [[NSMeasurementFormatter alloc] init];
    [formatter setUnitOptions:NSMeasurementFormatterUnitOptionsNaturalScale];

    NSString *shortString = @"s";
    NSString *longString = @"e x t r a   i r o n i c   s t r i n g";

    printf("%s\n", [[formatter stringFromMeasurement:measureString(shortString)] UTF8String]);
    printf("%s\n", [[formatter stringFromMeasurement:measureString(longString)] UTF8String]);
}
$ make noArc
clang -g -o noArc -fno-objc-arc -framework Foundation noArc
$ ./noArc  
36 in
111 ft

Check out those cool new measurement APIs! Alas, we are leaking the NSMeasurements we alloc inside measureString. We can check for leaks using Instruments, which comes with Xcode.

$ instruments -t Leaks noArc
Instruments Trace Complete: /Users/luke/Repos/cocoa/objc/instrumentscli0.trace

The -t flag specifies which template we want to use to record diagnostic information. Here we choose the Leaks template, for memory leaks. We then just pass it something we want to run. Instruments will go ahead and run our executable, collecting data and leaving it in the form of a .trace file. Let’s open it:

$ open instrumentscli0.trace
Looks fine
Looks fine

There’s not much to see here. Everything seems to look fine, and the program only ran for less than a second. But we’re still leaking memory. It’s just that once the program finished, the operating system deallocated whatever memory it had leaked in the first place. It becomes a problem after a program has been running for a while, when it’s accumulated lots of individual leaks, hence why you see it more in long lived applications, rather than in command line executables. We can change our program to act more like the former:

for (int i = 0; i < 1000; i++) {
    printf("%s\n", [[formatter stringFromMeasurement:measureString(shortString)] UTF8String]);
    printf("%s\n", [[formatter stringFromMeasurement:measureString(longString)] UTF8String]);
    [NSThread sleepForTimeInterval: 0.05];
}
$ instruments -t Leaks noArc
Instruments Trace Complete: /Users/luke/Repos/cocoa/objc/instrumentscli1.trace
$ open /Users/luke/Repos/cocoa/objc/instrumentscli1.trace
Uh oh
Uh oh

Now we’re talking. Around 2000 leaked objects, all NSMeasurements.

Thanks to the -g flag, Instruments is able to give us lots of helpful information about where the leaks might have happened in our code. We can double click on the stack frame on the right to jump right to the line of code that a particular leak happened:

Spotted
Spotted

Instruments has lots of wild tools and features for debugging, like a side-by-side dissaembly viewer and even an instruction set reference built right in. But that’s for another day.

So how come we’re leaking memory anyway? With Core Foundation, any “ref” type we created we needed to call CFRelease on, once we were finished with it. In Objective-C, any object we allocate ourselves with alloc, we need to release with release once we’re done.

for (int i = 0; i < 1000; i++) {
    NSMeasurement *shortMeasurement = measureString(shortString);
    NSMeasurement *longMeasurement = measureString(longString);

    printf("%s\n", [[formatter stringFromMeasurement:shortMeasurement] UTF8String]);
    printf("%s\n", [[formatter stringFromMeasurement:longMeasurement] UTF8String]);

    [shortMeasurement release];
    [longMeasurement release];

    [NSThread sleepForTimeInterval: 0.05];
}

If we trace this with instruments again:

Leaks plugged
Leaks plugged

Leaks are gone! Let’s look at some trickier scenarios

Instance variables

@interface Counter: NSObject {
    int count;
}
- (int)count;
- (void)setCount:(int)value;
@end

We want to store a variable in Counter, so we give it an ivar (instance variable) count. Just like in other object-orientated languages, we can encapsulate it by providing getter and setter methods.

@implementation Counter
- (int)count {
    return count;
}
- (void)setCount:(int)value {
    count = value;
}
@end

Now we can use it like this:

Counter *c = [[Counter alloc] init];
[c setCount:42];
[c count]; // 42

This is such a common pattern, Objective-C has some syntactic sugar for it: Whenever we have a pair of methods called foo and setFoo:, we can also use dot syntax to call them instead:

int main() {
    Counter *c = [[Counter alloc] init];
    c.count = 42;
    printf("%i\n", c.count);
}

In traditional Objective-C fashion, let’s superfluously turn our humble int into an object, NSNumber:

@interface Counter: NSObject {
    NSNumber *count;
}
- (NSNumber*)count;
- (void)setCount:(NSNumber*)value;
@end

Changing the getter is easy:

- (NSNumber*)count {
    return count;
}

And the setter too, right?

- (void)setCount:(NSNumber*)value {
    count = value;
}

Congratulations, we’ve leaked memory! count is now an object, so we have to start thinking about how it’s allocated and deallocated. We’re not releasing the old value so everytime this is called we end up leaving an old NSNumber lying around. Let’s fix this:

- (void)setCount:(NSNumber*)value {
    [count release];
    count = value;
}

Great! Don’t worry, this will work when count is nil since Objective-C lets you call methods on nil perfectly fine (I don’t know if this is a good thing or not). Now to try it out.

NSNumber *n = [[NSNumber alloc] initWithFloat: 1234.5678];
[c setCount:n];
[n release];

Here we’re being good citizens by making sure to release whatever we alloc. But hold on - if we try to access c.count now it will be deallocated, since we released it. This can cause memory exceptions: it may work when we run it since the memory might still be intact, but we can’t rely on it. We can try to catch it by compiling the program with Address Sanitizer:

$ clang -o counter -framework Foundation -fno-objc-arc -fsanitize=address -g  counter.m
$ ./stopwatch
ASAN:DEADLYSIGNAL
=================================================================
==3628==ERROR: AddressSanitizer: SEGV on unknown address 0x7fff1d800018 (pc 0x7fff577f3e9d bp 0x7ffeec445670 sp 0x7ffeec4455f8 T0)
==3628==The signal is caused by a READ memory access.
#0 0x7fff577f3e9c in objc_msgSend (libobjc.A.dylib:x86_64h+0x6e9c)
#1 0x7fff5841b014 in start (libdyld.dylib:x86_64+0x1014)
...

We could simply not call [n release], but then this just gets confusing because it breaks the rule that we’re responsible for deallocating any memory we allocate in the first place. What we need to do is transfer ownership: basically, we want to give responsibility of the NSNumber’s memory to Counter. We do this with retain:

- (void)setCount:(NSNumber*)value {
    [value retain];
    [count release];
    count = value;
}

What it does is it increments the object’s reference count by one:

Reference counting

Each object has a reference count: - Calling alloc allocates it and starts its reference count off at 1 - Calling retain increases the reference count by 1 - Calling release decreases the recerence count by 1

Whenever its reference count reaches 0, it is deallocated, which is why so far we’ve been deallocating objects by calling release on it just once. By retaining value we increase the reference count by 1 to 2, so that when we release it from outside it drops back to 1, preventing it from being deallocated.

We have to be careful to call [value retain] before we call [count release], because if count and value both point to the same object then we could inadvertently deallocate it by releasing it down to 0. But rather than worrying about this, we can use [value autorelease] which will defer calling release until the current autorelease pool is released.

- (void)setCount:(NSNumber*)value {
    [count autorelease];
    count = [value retain];
}

retain also returns self which can be used to make our setter a bit more succint. But what’s an autorelease pool?

It marks whenever we should “drain” (release) all of the objects that have been marked for release with autorelease:

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// do stuff here
[pool release];

Checking what happens currently when don’t release the pool:

for (int i = 0; i < 10; i++) {
    c.count = c.count;
    printf("%lu\n", [c.count retainCount]);
}
$ ./counter                                                                                   
2
3
4
5
6
7
8
9
10
11

We can see the reference count keeps on going up because it never gets released. When its wrapped in an NSAutoreleasePool though:

for (int i = 0; i < 10; i++) {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    c.count = c.count;
    [pool release];
    printf("%lu\n", [c.count retainCount]);
}
$ ./counter                                                                                   
1
1
1
1
1
1
1
1
1
1

It gets released. There’s a nice syntax for this by the way:

for (int i = 0; i < 10; i++) {
    @autoreleasepool {
        c.count = c.count;
    }
    printf("%lu\n", [c.count retainCount]);
}

Usually we don’t need to worry about autorelease pools though - In a full Cocoa application NSRunLoop will automatically call it every frame, but we will get to that later.

For now, you might be thinking this is all a huge pain just to create a single instance variable, and you’re right. Why not let the compiler generate all this stuff for us? The @property keyword will synthesize the ivar, getter and setter for us all at once:

@interface Counter: NSObject
@property (retain) NSNumber *count;
@end

@implementation Counter
@end

int main() {
    @autoreleasepool {
        Counter *c = [[[Counter alloc] init] autorelease];
        NSNumber *n = [[[NSNumber alloc] initWithFloat: 42.123] autorelease];
        c.count = n;
        printf("%s\n", [[c.count description] UTF8String]);
    }
}

Nice! We’re also specifying that we want the setter to retain whatever’s passed to it with the (retain) part.

But we’re not just done yet - what happens when Counter gets deallocated itself?

NSNumber *n;
@autoreleasepool {
    Counter *c = [[[Counter alloc] init] autorelease];
    n = [[[NSNumber alloc] initWithFloat: 42.123] autorelease];
    c.count = n;
}
printf("%lu\n", [n retainCount]);
1

Since c now owns n we’re responsible for releasing the reference we have to it inside Counter. We do this by overriding dealloc which gets called whenever its deallocated:

@implementation Counter

- (void)dealloc {
    [_count release];
    [super dealloc];
}
@end

When using @property, clang will default to naming the ivar _foo, but you can also choose what it will be named with @synthesize. Finally, if you try to access n afterwards Address Sanitizer will trap, so we know it’s been successfully deallocated!

Now lets throw away everything we just learnt:

@interface Counter: NSObject
@property (retain) NSNumber *count;
@end

@implementation Counter
@end

int main() {
    Counter *c = [[Counter alloc] init];
    NSNumber *n = [[NSNumber alloc] initWithFloat: 42.123];
    c.count = n;
    printf("%s\n", [[c.count description] UTF8String]);
}

Remove that cursed flag:

%: %.m
clang -o $@ -framework Foundation -g $<

Fast-forward to 2009: Automatic Reference Counting (ARC) is here! It takes care of all of that memory management headache for us. When its enabled, calls to retain and release are automatically inserted by the compiler. It’s enabled by default: Turning it off is a very bad idea™. Everything from here on in will be with ARC.

Cocoa

Now we have all that cleared out the way, lets talk about what you came here for. Cocoa is the framework that powers OS X development. But as it turns out, Cocoa is acutally three smaller frameworks stacked on top of each other in a trench coat:

If you take a look at the Cocoa framework under /System/Library/Cocoa.framework, it’s only 39KB. Compare it to Foundation’s hefty 18.6MB, or AppKit which weighs in at a whopping 63.3MB as of 10.14.

AppKit

Let’s make our first application. An application so basic, it doesn’t even need full Cocoa, just AppKit:

#import <AppKit/AppKit.h>

int main(int argc, char *argv[]) {
  [NSApplication sharedApplication];
  [NSApp run];
}

We instantiate the application for our process by calling sharedApplication and then kick it off with [NSApp run]. NSApp is just a shortcut for reading [NSApplication sharedApplication]:

__kindof NSApplication *NSApp;
$ clang -o basic -framework AppKit basic.m
$ ./basic

And now we have an app running! But there’s nothing in the dock.

By default applications have an NSApplicationActivationPolicyProhibited activation policy, which means that they can’t create windows or have menu bars. We need to set this to the regular policy which does allow us. While we’re at it, lets also automatically activate the app so it is front and center when we launch it.

#import <AppKit/AppKit.h>

int main(int argc, char *argv[]) {
  [NSApplication sharedApplication];
  [NSApp setActivationPolicy: NSApplicationActivationPolicyRegular];
  [NSApp activateIgnoringOtherApps: YES];  
  [NSApp run];
}
Menu bar
Menu bar

Now how do we get out?

  NSMenu *menuBar = [[NSMenu alloc] init];
  [NSApp setMainMenu: menuBar];

  NSMenuItem *appMenuItem = [[NSMenuItem alloc] init];
  [menuBar addItem: appMenuItem];

  NSMenu *appMenu = [[NSMenu alloc] initWithTitle: @"Cocoa from Scratch"];
  [appMenuItem setSubmenu: appMenu];

  NSMenuItem *quitMenuItem = [[NSMenuItem alloc] initWithTitle: @"Quit"
                                                        action: @selector(terminate:)
                                                 keyEquivalent: @"q"];
  [appMenu addItem: quitMenuItem];
Quit
Quit

We can programatically create menus with the NSMenu and NSMenuItem classes. The main menu bar is an NSMenu itself, as well as all its other submenus.

The signature of -[NSMenuItem initWithTitle:action:keyEquivalent:] looks like this:

- (instancetype)initWithTitle:(NSString *)string 
                       action:(SEL)selector 
                keyEquivalent:(NSString *)charCode;

You may notice SEL from earlier, the type for efficiently referencing Objective-C methods. In the code above we used @selector(terminate:) to create one for us, which in this case references a method on NSApplication.

Windows

 NSWindow *window = [[NSWindow alloc] initWithContentRect: NSMakeRect(0, 0, 200, 200)
                        styleMask: 0
                          backing: NSBackingStoreBuffered
                            defer: YES];
[window setTitle: @"NSWindow from Scratch"];
[window cascadeTopLeftFromPoint: NSMakePoint(20, 20)];

[window makeKeyAndOrderFront: nil];

cascadeTopLeftFromPoint: positions the window from the top left of the screen with a bit of offset, which is nicer than our default absolute bottom left of (0, 0).

The NSWindow initializer has some strange looking stuff going on. Let’s break it down:

My eyes!
My eyes!

The result is fairly spartan. What about the just NSWindowStyleMaskTitled on its own?

Much better.
Much better.

And if we throw on some extra flags:

NSWindowStyleMask mask = NSWindowStyleMaskTitled
  | NSWindowStyleMaskClosable
  | NSWindowStyleMaskMiniaturizable
  | NSWindowStyleMaskResizable;
Just like Interface Builder used to make
Just like Interface Builder used to make

It starts to look pretty good! We get the traffic lights, resizing and even full-screen.

Controls

Some basic controls are NSTextField and NSButton:

NSTextField *textField = [NSTextField labelWithString: @"The time"];

TimeHandler *timeHandler = [[TimeHandler alloc] initWithTextField:textField];

NSButton *button = [NSButton buttonWithTitle: @"Get the Time"
                      target: timeHandler
                      action: @selector(updateTime)];

[[window contentView] addSubview: button];
[[window contentView] addSubview: textField];

Note that unlike UIKit, there is no such class as NSLabel, NSTextField can act as both a readonly label and an editable field by setting specific properties. labelWithString: is a shortcut to create an NSTextField with these properties.

Our TimeHandler class looks like this:

@interface TimeHandler: NSObject 
@property (retain) NSTextField *textField;
- (void)updateTime;
@end
@implementation TimeHandler

- (id)initWithTextField:(NSTextField*)textField {
  self.textField = textField;
  [super init];
  return self;
}

- (void)updateTime {
  NSDate *currentDate = [NSDate date];
  [[self textField] setStringValue: [currentDate description]];
}

@end

If we build and run this, we get this:

Overlapping views
Overlapping views

Yikes, the views overlap. Now we could position them by hand ourselves with, setFrame:, but this is a pain.

It’s now 2011, and we’re now running shiny OS X Lion. There’s a hip new technology called “Auto Layout” and it allows us to define or UI with constraints:

[button setTranslatesAutoresizingMaskIntoConstraints: NO];
[textField setTranslatesAutoresizingMaskIntoConstraints: NO];

[button.leadingAnchor constraintEqualToAnchor: window.contentView.leadingAnchor constant: 20].active = YES;
[textField.leadingAnchor constraintEqualToAnchor: button.trailingAnchor constant: 20].active = YES;
[window.contentView.trailingAnchor constraintGreaterThanOrEqualToAnchor: textField.trailingAnchor constant: 20].active = YES;


[button.topAnchor constraintEqualToAnchor: window.contentView.topAnchor constant: 20].active = YES;
[textField.topAnchor constraintEqualToAnchor: button.topAnchor constant: 0].active = YES;
[window.contentView.bottomAnchor constraintGreaterThanOrEqualToAnchor: textField.bottomAnchor constant: 20].active = YES;
Auto Layout
Auto Layout

We can resize the window and it’ll stop before it cuts off the views. There’s also the visual format language:

NSDictionary *views = @{ @"button": button, @"textField": textField };
NSArray<NSLayoutConstraint*>* hConstraints = [NSLayoutConstraint constraintsWithVisualFormat: @"|->=20-[button]-20-[textField]->=20-|"
                                              options: NSLayoutFormatAlignAllCenterY
                                              metrics: @{}
                                            views: views];
[NSLayoutConstraint activateConstraints: hConstraints];

NSArray<NSLayoutConstraint*>* vConstraints = [NSLayoutConstraint constraintsWithVisualFormat: @"V:|-[button]->=20-|"
                                              options: 0
                                              metrics: @{}
                                            views: views];
[NSLayoutConstraint activateConstraints: vConstraints];

Bundles

If you right click on any OS X application, you’ll see an option to “Show Package Contents”.

Show Package Contents
Show Package Contents
$ tree -L 2 Photos.app
Photos.app
└── Contents
    ├── Info.plist
    ├── Library
    ├── MacOS
    ├── PkgInfo
    ├── PlugIns
    ├── Resources
    ├── XPCServices
    ├── _CodeSignature
    └── version.plist

.apps are actually directories, but OS X hides the contents as if they were a single file because they are bundles. Frameworks, plugins, screensavers and more are all bundles too. Check out the NSBundle Foundation class for more information.