Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RAII in Objective-C pattern?

I find myself writing code like this to achieve exception safe code:

Container* container = [Container new];
@try {
    while(someCondition) {
        ElementType* value = [someObject createObjectFromStorage];
        [container add:value]; // container retains object
        [value release];
    }

    [_container release];
    _container = [container retain];
} @finally {
    [container release];
}

Is there some other, and more succinct pattern to follow in Objective-C?

like image 939
Jörgen Sigvardsson Avatar asked Jan 18 '23 02:01

Jörgen Sigvardsson


1 Answers

If you're just looking to make sure you've released your objects, autorelease is probably sufficient. You might also look into the new Automatic Reference Counting option in Xcode 4.2.

Objective-C does not, in general, lend itself to RAII because all Objective-C objects are allocated on the heap. This means that the lifetime of objects is not explicitly tied to any particular stack frame, and thus you cannot rely on the object being deallocated at the end of the method that allocated it.

You should also be aware that the Cocoa frameworks use exceptions only to indicate programmer error, not anticipated error conditions. From Apple's "Exception Programming Guide" documentation:

Important: You should reserve the use of exceptions for programming or unexpected runtime errors such as out-of-bounds collection access, attempts to mutate immutable objects, sending an invalid message, and losing the connection to the window server. You usually take care of these sorts of errors with exceptions when an application is being created rather than at runtime.

If you have an existing body of code (such as third-party library) that uses exceptions to handle error conditions, you may use the code as-is in your Cocoa application. But you should ensure that any expected runtime exceptions do not escape from these subsystems and end up in the caller’s code. For example, a parsing library might use exceptions internally to indicate problems and enable a quick exit from a parsing state that could be deeply recursive; however, you should take care to catch such exceptions at the top level of the library and translate them into an appropriate return code or state.

In fact, because exceptions are intended to be used only for exceptional cases, by default the newly introduced Automatic Reference Counting will intentionally leak objects when throwing an exception:

The standard Cocoa convention is that exceptions signal programmer error and are not intended to be recovered from. Making code exceptions-safe by default would impose severe runtime and code size penalties on code that typically does not actually care about exceptions safety. Therefore, ARC-generated code leaks by default on exceptions, which is just fine if the process is going to be immediately terminated anyway. Programs which do care about recovering from exceptions should enable the option.

Programming with the Cocoa frameworks will go much better if you adhere to the idioms of that framework. That means using exceptions only for programmer errors and handling anticipated runtime errors with NSError. Most Cocoa programmers never worry about writing exception-safe code, because their code doesn't throw exceptions in the first place. You may do well to follow suit.

like image 142
BJ Homer Avatar answered Jan 28 '23 07:01

BJ Homer