pyobjc-docs / pyobjc-core / Doc / advanced / referencecounting.rst

Reference counting

The `Cocoa libraries`_, and most (if not all) other class libraries for Objective-C use explicit reference counting to manage memory. The methods retain, release and autorelease are used to manage these reference counts. You won't have to manage reference counts in Python, the bridge does all that work for you (but see Notes on supported APIs and classes on Mac OS X for some advanced issues).

The only reasons reference counts are mentioned at all are to tell you about ignoring them, and more importantly to introduce you to some issues w.r.t. reference counting.

It turns out that Cocoa uses a primitive form of weak references. Those are not true weak references as in Python, but use-cases where an object stores a reference to another object without increasing the reference count for that other object. The bridge cannot solve the issues this introduces for you, which means that you get hard crashes when you're not careful when dealing with those weak references.

The basic rule to deal with weak references is: make sure objects stays alive as long as someone might have a weak reference to them. Due to the way the bridge works, this means that you must make sure that you don't create weak references from Objective-C to a plain Python object. The Python object stays alive, but the proxy object as seen by the Objective-C code is actually an autoreleased object that will be cleaned up unless the Objective-C code increases its reference count.

The document `Notes on supported APIs and classes on Mac OS X`_ contains information about classes that work with weak references. The most important are notification centers and NSOutlineView, to be exact: the outline view stores weak references to the objects return by the method outlineView:child:ofItem: of its data source. The easiest way to avoid crashes with outline views is to make sure that you model for the view uses subclasses of NSObject to represent the nodes in the outline view.

Another gotcha is that obj.setDelegate_() often does not retain the delegate, so a reference should be maintained elsewhere.