我必须用try / finally包围对象创建/发布吗?

时间:2009-01-13 16:25:40

标签: objective-c delphi

在Delphi中,这是正常的:

ob = TObject.create;
try
  //code
finally
  ob.free;
end;

我想知道Obj-c中是否有相似之处。

4 个答案:

答案 0 :(得分:3)

你可以这样做,但例外往往在Objective-C中有高成本。它们在32位和64位ABI之间的性能存在一些差异,以及Objective-C异常和C ++异常之间的交互。

另一种方法是创建对象,使其自动释放,并在方法结束前保留它们。

SomeClass *object = [[[SomeClass alloc] init] autorelease];

/* deadly code here */

return [object retain];

这种方式即使您的代码遇到异常,下次自动释放池耗尽时(通常在事件循环结束时)也会释放对象,假设异常不是致命的并导致程序崩溃。

Apple有一些关于Obj-C异常的documentation 最后,Leopard的the release notes讨论了64位ABI的变化。

答案 1 :(得分:1)

没有。 Objective-C确实支持异常,你很少在Cocoa中看到它们(NSError是Apple的目标)但是每次初始化或释放一个对象时你绝对不会使用它们。

答案 2 :(得分:1)

我当然不是Obj-C的专家,但事实上它提供了(人们在Delphi中提出的问题)复合try / catch / finally,这使你可以选择像Delphi一样使用它进行防御性编程: / p>

@try {
   // protected block
} 
@catch (id theException) {
  // do smthing with theException
} 
@finally {
  // clean up code 
}

我认为,如果程序员更频繁地使用@finally,那么他们的开发中会有更少的错误。

答案 3 :(得分:1)

然而,好的答案...... 我有待纠正,但我的理解是@try {} @finally {}在概念上有所不同,因此应用于@try {} @catch {} @finally {},如果你不引发任何异常,那么开销最小,但是当引发异常时(应该是定义,“异常而不是规则”),它们用于保护被包装的资源,进一步留下@catch处理程序处理食物链以处理处理异常的逻辑方面。

作为一个例子,这里是一个我经常使用的构造,当我必须返回一个自动释放的值时,它会将大量无关的数据自动调用到调用者池中,如果它不是@ try / @ finally / drain / autorelease你在这里看到了什么。

+(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); 
}