【发布时间】:2012-08-10 21:00:19
【问题描述】:
我正在尝试在我的班级中实现一些错误处理。我认为我对处理错误的工作原理并不完全了解,但我注意到人们建议将函数中的错误声明为 (NSError *__autoreleasing *error),所以我这样做了。我在通过函数传递错误时遇到问题。
会出现以下问题: 分解它似乎如下问题:(对不起,实际代码太长,但我试图提取希望对问题最重要的部分!我希望我的代码范围包含问题)
假设你有 ObjectA 的方法:
-(NSString *) do1: (NSString *) withstuff error:(NSError *__autoreleasing *)error{
//...
//error happens
*error = [[NSError alloc] initwithDomain: domain code: blah userinfo: infodict];
return nil;
}
-(BOOL) do2error:(NSError *__autoreleasing *)error{
NSString *doesntmatter = [self do1: @"whatever" error: error];
if (doesntmatter == nil){
return NO;
}
}
现在在另一个类(AppDelegate 对象)中,我调用以下代码:
ObjectA* ob1 = [[ob1 alloc] init];
NSError *errorBoom = nil;
if ([ob1 do2error:&errorBoom] == NO){
NSLog(@"error: %@",errorBoom); //---> bad access error
}
好像 errorBoom 不再可用了?那是因为“__autoreleasing”,我试图理解它的实际含义,但到目前为止所有的解释对我来说都不是很有用,因为我在这个领域很新......我希望你能帮助我!
编辑:
好的,我想我找到了错误。现在我知道是什么原因造成的,但我不知道具体原因。我写了一个简单的示例应用程序,它提取了“Bad Access”-Error 发生的主要来源:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions (NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
NSError *errtest = nil;
BOOL testBool = [self messaroundwitherr:&errtest];
NSLog(@"Filled NSError? : %@",errtest); //<--Causes Bad Access.
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
-(BOOL) giveErrornow:(NSError *__autoreleasing *)err {
NSMutableDictionary *errInfo = [[NSMutableDictionary alloc] init];
[errInfo setObject:@"I feel like giving you an error!" forKey:NSLocalizedDescriptionKey];
*err = [[NSError alloc] initWithDomain:@"nonesense"
code:0
userInfo:errInfo];
return NO;
}
-(BOOL) messaroundwitherr:(NSError *__autoreleasing *)err{
//@autoreleasepool { --> uncommenting that causes the error
return [self giveErrornow: err];
//}
}
显然激活自动释放池,使得 err 变量在能够从外部函数(AppFinishLaunching...)读取它之前被释放。现在为什么会发生这种情况?我知道“@autoreleasepool”在使用后会释放变量。在原始上下文中,我有一个 while 循环,这就是我这样做的原因。这里只是出于理解的原因。 那么@"autoreleasepool" 是如何工作的呢?命令 (*__autorelease *) 实际发生了什么。
我想在修复它之前我必须完全理解它的概念。 NSError (*__autorelease *) err 是否为 ARC 定义了“指向将要自动释放的对象的指针(如果是,何时)”?
【问题讨论】:
-
如果你去掉
__autoreleasing限定符,只使用NSError **怎么办? -
@nielsbot 我认为在 ARC 中使用指向指针的指针时不指定生命周期限定符是错误的。
-
您是否尝试过对
domain使用字符串文字,对infodict使用nil?您可能会将某些内容传递给已释放的错误对象。我还看到过看似无关的错误会导致代码每次都在同一行中断的情况。尝试运行分析器并修复所有警告。 -
__autoreleasing 与 ARC 有关,它是正确的。我看到的唯一问题是,在
do1:error:中,他应该在取消引用之前检查error是否为 nil,但这不是他所感叹的问题。我猜在一些没有发布的代码中还有其他事情发生。 -
我认为我的 NSError 对象做得很好,我检查了一下。似乎整个 errorBoom 不再可用了。 _autorelease 是做什么的?我想也许它导致错误对象在此期间被释放,而 NSLog 尚未执行?
标签: objective-c nserror