我正在尝试在我的课程中实现一些错误处理。我不认为我对如何处理错误有充分的理解,但我注意到人们建议,将函数中的错误声明为(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”,我试图理解它实际意味着什么,但到目前为止所有的解释对我来说都不是很有用,因为我在这个领域很新......我希望你能帮助我!
修改
好的,我想我已经找到了错误。现在我知道是什么导致了它,但我不知道为什么。我写了一个简单的示例应用程序,它提取“错误访问” - 错误发生的主要来源:
- (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];
//}
}
显然激活autoreleasepool,使得err变量在被外部函数(AppFinishLaunching ...)读取之前就被释放了。现在为什么会发生这种情况呢?我知道“@autoreleasepool”在使用后释放变量。在原始的上下文中,我有一个while循环,这就是我这样做的原因。这只是出于理解的原因。 那么@“autoreleasepool”如何运作?实际上命令会发生什么(* __ autorelease *)。
我想在修复之前我必须完全理解它的概念。 NSError(* __ autorelease *)错误是否为ARC定义了一个“指向要自动释放的对象的指针(如果是,何时)”的指针?
答案 0 :(得分:2)
好的,我想在两个有用的网站的帮助下弄明白了:
http://blog.pioneeringsoftware.co.uk/2012/03/06/out-parameters-when-arcing
和
(不幸的是,第二个是德语: - ))
无论如何,基本概念如下:
通过引用定义变量,如:
(NSError ** err) or (NSError *__autoreleasing * err)
始终让ARC将其重写为:
(NSError *__autoreleasing * err)
并重写
*err = [[NSError alloc] initWithDomain:@"nonesense"
code:0
userInfo:errInfo]
到
*err = .....]retain] autorelease];
所以错误对象被标记为autorelease。
现在正如文档中所述:
在自动释放池块的末尾,在块中接收到自动释放消息的对象被发送释放消息 - 对象在块中发送自动释放消息时接收释放消息
所以从1和2基本上发生的是,当取消注释@autoreleasepool块时,错误正在
中创建 giveErrornow:(NSError *__autoreleasing *)err
函数,从autoreleasepool中调用,因此* errtest在被用于
之前被释放和释放 NSLog(@"Filled NSError? : %@",errtest)
是的,所以基本上就是这样。在处理参数时似乎是一个普遍问题,并且可以更改有问题的代码,例如:
- (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{
NSError *tempErr;
BOOL retVal;
@autoreleasepool {
retVal = [self giveErrornow:&tempErr];
}
*err = tempErr;
return retVal;
}
欢迎您留下任何有关此问题的评论。如果我能正确理解问题,我会感到很高兴。
答案 1 :(得分:1)
最后,我能够找出原因并加以解决。就我而言,在 autorelease 块内分配的AndyApp.template
对象被释放,这导致崩溃。我已经创建了一个error(NSError
)对象的副本,并将其分配给了外部代码块,它解决了我的问题。
NSError