Objective c 在块崩溃中分配NSError的调用方法
我想了解为什么这会导致Objective c 在块崩溃中分配NSError的调用方法,objective-c,cocoa,automatic-ref-counting,objective-c-blocks,Objective C,Cocoa,Automatic Ref Counting,Objective C Blocks,我想了解为什么这会导致EXC\u BAD\u ACCESS错误而崩溃。它从方法调用返回,但随后在[self-runmethodthatsassignserror:&error]上立即崩溃 我知道,但它不能解释发生了什么,而且已经很老了 - (void)checkError { NSError *error; [self runMethodThatAssignsError:&error]; // crashes after returning NSLog(@"suc
EXC\u BAD\u ACCESS
错误而崩溃。它从方法调用返回,但随后在[self-runmethodthatsassignserror:&error]
上立即崩溃
我知道,但它不能解释发生了什么,而且已经很老了
- (void)checkError {
NSError *error;
[self runMethodThatAssignsError:&error]; // crashes after returning
NSLog(@"success");
}
- (BOOL)runMethodThatAssignsError:(NSError **)error {
[@[@1] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
*error = [NSError errorWithDomain:@"1" code:7 userInfo:@{}];
}];
return NO;
}
在Instruments中运行示例代码时,似乎
-[NSArray EnumerateObjectsSusingBlock:
正在自动释放池中包装其块。由于默认情况下,NSError**
指针被隐式假定为\uu自动删除
,因此NSError
对象在分配给*error
时会自动删除,并因此被-[NSArray enumerateobjects susingblock:
的自动删除池获取
有两种方法可以解决这个问题。第一种方法是在块外使用局部变量,使ARC保留该变量,直到枚举完成:
- (BOOL)runMethodThatAssignsError:(NSError **)error {
__block NSError *_error = nil;
[@[@1] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
_error = [NSError errorWithDomain:@"1" code:7 userInfo:@{}];
}];
if (error) *error = _error;
return NO;
}
或者,您可以将error
参数声明为\uu strong
,这将首先防止NSError
被放入自动释放池。请注意,只有当此方法的客户端始终使用ARC时,才应执行此操作,因为否则可能会导致错误泄漏,因为客户端不希望必须释放错误,因为此方法是非常规的
- (BOOL)runMethodThatAssignsError:(NSError * __strong *)error {
[@[@1] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
if (error) *error = [NSError errorWithDomain:@"1" code:7 userInfo:@{}];
}];
return NO;
}
\uuu block n错误*blockError=nil;[@[@1]enumerateObjectsUsingBlock:^(id-obj,NSUInteger-idx,BOOL*stop){blockError=[nSErrorWithDomain:@“1”代码:7用户信息:@{};}];if(blockError)*error=blockError;返回N0代码>?@Larme是的,这是个问题,这总是必需的吗?没办法吗?如果是这样的话,为什么?仅供参考-在事先确保错误不是零之前,切勿执行*错误=…
。永远不要取消对nil指针的引用
在enumerateObjectsUsingBlock:
之前,然后尝试在块内设置其值,编译器应警告您(编译错误或警告)请求\u块
。所以我想说这里也是一样。@rmaddy从技术上讲,对NSError**
指针的检查应该是NULL
,而不是nil
nil
应该用于对象指针(即NSError*
),而不是指向对象指针的指针,尽管实际上它们都具有相同的值。我推荐第一种方法。使用NSError*\uu strong*
是非常不传统的。显然,这是有记录的,块内分配的值将在执行块后被释放。使用retain显式维护这些值。
-