使用 ARC 在块内设置 NSError
我希望使用项目中的块内设置 NSError 指针 自动引用计数。以下是我的代码的简化版本:
- (BOOL)frobnicateReturningError:(NSError **)error
{
NSArray *items = [NSArray arrayWithObjects:@"One", @"Two", @"Three", nil];
__block Frobnicator *blockSelf = self;
[items enumerateObjectsUsingBlock:^(id item, NSUInteger idx, BOOL *stop) {
[blockSelf doSomethingWithItem:item error:error];
}];
}
可以编译,但给定的 error
可能会被修改 doSomethingWithItem
我尝试为该块创建一个本地 NSError 修改,然后用于设置原始 error
枚举(我没有显示):
- (BOOL)frobnicateReturningError:(NSError **)error
{
NSArray *items = [NSArray arrayWithObjects:@"One", @"Two", @"Three", nil];
__block Frobnicator *blockSelf = self;
__block NSError *blockError = nil;
[items enumerateObjectsUsingBlock:^(id item, NSUInteger idx, BOOL *stop) {
[blockSelf doSomethingWithItem:item error:&blockError];
}];
}
编译失败,出现以下错误:
将非本地对象的地址传递给__autoreleasing参数进行写回
谷歌搜索此错误仅返回来自 Clang 源代码本身的结果。
一种似乎有效但有点丑陋的解决方案是有一个内部和外部错误指针:
- (BOOL)frobnicateReturningError:(NSError **)error
{
NSArray *items = [NSArray arrayWithObjects:@"One", @"Two", @"Three", nil];
__block Frobnicator *blockSelf = self;
__block NSError *outerError = nil;
[items enumerateObjectsUsingBlock:^(id item, NSUInteger idx, BOOL *stop) {
NSError *innerError = nil;
[blockSelf doSomethingWithItem:item error:&innerError];
outerError = innerError;
}];
}
从块内设置 NSError 的正确方法是什么?
I wish to set an NSError pointer from within a block in a project using
automatic reference counting. What follows is a simplified version of my code:
- (BOOL)frobnicateReturningError:(NSError **)error
{
NSArray *items = [NSArray arrayWithObjects:@"One", @"Two", @"Three", nil];
__block Frobnicator *blockSelf = self;
[items enumerateObjectsUsingBlock:^(id item, NSUInteger idx, BOOL *stop) {
[blockSelf doSomethingWithItem:item error:error];
}];
}
This compiles but given error
may be modified bydoSomethingWithItem
I tried creating a local NSError for the block to
modify, which would then be used to set the original error
after
the enumeration (which I haven't shown):
- (BOOL)frobnicateReturningError:(NSError **)error
{
NSArray *items = [NSArray arrayWithObjects:@"One", @"Two", @"Three", nil];
__block Frobnicator *blockSelf = self;
__block NSError *blockError = nil;
[items enumerateObjectsUsingBlock:^(id item, NSUInteger idx, BOOL *stop) {
[blockSelf doSomethingWithItem:item error:&blockError];
}];
}
This fails to compile with the following error:
passing address of non-local object to __autoreleasing parameter for write-back
Googling for this error only returns results from the Clang source code itself.
One solution that seems to work but is a bit ugly is to have an inner and outer error pointer:
- (BOOL)frobnicateReturningError:(NSError **)error
{
NSArray *items = [NSArray arrayWithObjects:@"One", @"Two", @"Three", nil];
__block Frobnicator *blockSelf = self;
__block NSError *outerError = nil;
[items enumerateObjectsUsingBlock:^(id item, NSUInteger idx, BOOL *stop) {
NSError *innerError = nil;
[blockSelf doSomethingWithItem:item error:&innerError];
outerError = innerError;
}];
}
What is the correct way to set an NSError from within a block?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
注意:从 2020 年起,不再需要此解决方法。
尝试一下:
至于为什么需要这样做,我仍在尝试自己掌握。当我这样做时,我会更新这个答案。 :)
Note: As of 2020, this workaround is no longer necessary.
Try this:
As for exactly why this is necessary, I'm still trying to get a grasp on that myself. I'll update this answer when I do. :)
如“LLVM 有什么新功能?”@ 14:55 所示,有两种技术可以解决隐式自动释放的 NSError 问题。
最简单的修复是使用 __strong
第二个修复是使用 __block
As seen on "What's new in LLVM?" @ 14:55, there are two techniques to address the issue with the NSError which is implicitly autoreleasing.
Easiest fix is to use __strong
Second fix is to use __block