In Delphi, is normal do this:
ob = TObject.create;
try
//code
finally
ob.free;
end;
I wonder if that is similar in Obj-c.
In Delphi, is normal do this:
ob = TObject.create;
try
//code
finally
ob.free;
end;
I wonder if that is similar in Obj-c.
You could do it that way, but exceptions tend to have a high cost in Objective-C. There are some differences in their performance between the 32-bit and 64-bit ABIs, as well as the interaction between Objective-C exceptions and C++ exceptions.
An alternative is to create your objects such that they are autoreleased and only retain them before your method ends.
SomeClass *object = [[[SomeClass alloc] init] autorelease];
/* deadly code here */
return [object retain];
This way even if your code experiences an exception your object will be released the next time the autorelease pool is drained (usually at the end of the event loop), assuming that the exception is not fatal and causes your program to crash.
Apple has some documentation about Obj-C exceptions and the release notes for Leopard towards the end discuss the changes in the 64-bit ABI.
No. Objective-C does support exceptions and you see them in Cocoa infrequently (NSError is the direction Apple is headed) but you definitely wouldn't use them every time you initialize or release an object.
I'm certainly no expert in Obj-C but the fact that it provides (what people have asked in Delphi) the compound try/catch/finally, gives you the choice to use that to program defensively like in Delphi:
@try {
// protected block
}
@catch (id theException) {
// do smthing with theException
}
@finally {
// clean up code
}
And I would argue that if programmers used the @finally more often, there would be less bugs in their developments.
good answers, however... I stand to be corrected, but it is my understanding that @try {} @finally {} is different in concept and therefore application to @try {} @catch {} @finally {}, in that if you don't raise any exceptions there is minimal overhead, however when exceptions are raised (which should be by definition, the "exception rather than the rule"), they serve to protect the resource being wrapped, leaving a @catch handler further up the food chain to deal with logic side of dealing with the exception.
as an example, here is a construct i often use when i have to return an autoreleased value that would autorealease a lot of extraneous data into the callers pool, if it were not for the @try/@finally/drain/autorelease construct you see here.
+(NSArray *) arrayOfUrlPrefixAssociatedUrlArraysFromUnsortedArrayOfUrlStrings:(NSArray *)urlStrings {
NSArray *arrayResult = nil;
NSAutoreleasePool *wader = [[NSAutoreleasePool alloc] init];
@try {
NSMutableDictionary *result = [NSMutableDictionary dictionary];
for (NSString *urlString in urlStrings) {
BOOL addedToPrior = NO;
for (NSString *prefix in result.allKeys) {
if ([urlString hasPrefix:prefix]) {
[(NSMutableArray *) [result objectForKey:prefix] addObject:urlString];
addedToPrior = YES;
break;
}
}
if (!addedToPrior) {
[result setObject:[NSMutableArray arrayWithObject:urlString] forKey:[self urlPrefixFromUrlString:urlString]];
}
}
arrayResult = [[NSArray alloc] initWithArray:[result allValues]];
}
@finally {
[wader drain];
}
return (arrayResult?[arrayResult autorelease]:nil);
}