When programming with Monobjc, you have to take care of the memory management for both the .NET and the Objective-C runtimes. For the .NET runtime, usual rules applies. As for the Objective-C runtime, you have to follow the Cocoa memory management model.

In order for the bridge to work properly, it relies on the Objective-C reference counting memory model. As long as an object is retained (its reference count is greater or equals to one), it is usable. When its reference count is equals to zero, the object is destroyed. A variant of this behavior is to mark an object as "autoreleased"; this means that at the end of the life of the memory pool (i.e. NSAutoreleasePool), all the objects will be destroyed.

For more information about the Objective-C memory management, refer to the Memory Management Programming Guide for Cocoa.

Ownership

You "create" an object using a method whose name begins with "alloc" or "new" or contains "copy" (for example, Alloc, NewObject, or MutableCopy). If you explictly create an object, then it is your responsability to release it, either by calling "release" or "autorelease" methods.

The following listing gives you some examples:

// ...
NSButton button = new NSButton(frame); // <-- The button is explicitly created
// ...
button.Release(); // <-- As we have created the button, we must release it
// ...

// ...
CALayer layer = CALayer.Layer; // <-- The instance is autoreleased. No need to release it.
// ...

// ...
NSString str = NSString.String; // <-- The instance is autoreleased
str.Retain(); // <-- If we retain the instance...
// ...
str.Release(); // <-- ...we must release for the balance
// ...

Safe Memory Management

Monobjc provides safe methods for the memory management. They can be used with null reference which is useful when the reference may be null.

private NSEvent lastMouseDownEvent

public NSEvent LastMouseDownEvent
{
    get { return this.lastMouseDownEvent; }
    set
    {
        NSEvent oldValue = this.lastMouseDownEvent;
        this.lastMouseDownEvent = value.SafeRetain<NSEvent>(); // This won't crash even if the reference is null
        oldValue.SafeRelease(); // This won't crash even if the reference is null
    }
}

Rules of Thumb

This is the basic rules to follow are:

  • "You acquire ownership of an object if you create it using a method whose name begins with "Alloc" or "New" or contains "Copy" (for example, Alloc, NewObject, or MutableCopy), or if you send it a retain message. You are entitled for relinquishing ownership of objects you own using "release" or "autorelease". Any other time you receive an object, you MUST not release it."
  • "As a corollary of the first rule, if you need to store a received object as a property in an instance variable, you must retain or copy it. (This is not true for weak references, but these cases are rare). A received object is normally guaranteed to remain valid within the method it was received in (exceptions include multithreaded applications and some other exotic cases). That method may also safely return the object to its invoker."
  • "autorelease" just means "send a release message later" (see also NSAutoreleasePool).