7

是否有可能(如果是的话,安全)创建/使用一个将双指针作为参数的块?

例如:

- (void)methodWithBlock:(void (^)(NSError **error))block;


其他背景、研究和问题:

  • 我正在使用ARC。
  • 当我声明上面的方法并尝试调用它时,XCode 会自动完成我的方法调用,如下所示:这里是[self methodWithBlock:^(NSError *__autoreleasing *error) {}]; 什么__autoreleasing意思,为什么要添加它?我认为它与ARC有关。
  • 如果这可能且安全的,指针是否仍然可以在块中被取消引用,就像在其他任何地方一样?
  • 一般来说,执行我所描述的操作与简单地将双指针作为方法参数(例如- (void)methodWithDoublePointer:(NSError **)error;)传递之间的重要区别是什么?应该考虑哪些特殊考虑(如果有的话)(再次假设这是可能的)?
4

3 回答 3

4

是的,指针总是只是指针。您只需要确保在发送消息之前取消引用它(假设为 objc 对象)。

另请注意,指针可能为零。在尝试取消引用它或你有什么之前,请务必检查它。

正如@verec 提到的,如果您使用 ARC,您应该将参数声明为 __autoreleasing

根据文档

__autoreleasing 用于表示通过引用 (id *) 传递并在返回时自动释放的参数。

记住 id 是一个指向对象的指针,所以说对象**

将指针传递给指向方法或块的指针之间没有区别。

于 2013-10-21T21:26:21.703 回答
2

答案是“是”和“不是”...

在基本级别上,将指针传递给块的指针与将它们传递给方法没有什么不同。并且,通常的附带条件是您的指针必须有效,这是完全可以的。

然而,这在__autoreleasing这里非常重要,并且与 ARC 和pass-by-writeback 相关联。是否使用该块将按预期工作将取决于上下文,因为编译器在传递类型参数NSError * __autoreleasing *作为 pass-by-writeback 实现的一部分时经常使用隐藏变量。

如果 pass-by-writeback 不是您需要的,或者不合适,您可能希望将您的块声明为采用不同的类型,例如NSError * __strong *. 阅读这个答案,它解释了幕后发生的事情,这应该可以帮助您确定在您的上下文中块声明是否是好的。

总之(a)声明块很好,但是(b)你需要了解它是如何被调用的,并且可能需要更改签名。

于 2013-10-22T02:32:46.780 回答
0

警告:未经测试

为了论证,让我们从以下开始:

typedef NSError * NSErrorPtr ;

- (void) foo: (NSErrorPtr *) errPtr {
    *errorPtr = [NSError new] ;
}

errPtr 既没有声明为 __weak 也没有声明为 __strong。

因此,根据 ARC 的说法,即使它的内容是在foo发布的责任范围内分配的,它也必须驻留在某个地方。

在哪里?

请注意,这不是双指针本身的属性。但是你的配置模式。

考虑:

int ** arrayOfarrayOfInts = {
    {1, 2, 3, 4}    
,   {5, 6, 7, 8}
} ;

- (void) incrementElement: (int **) elem {
    ++(**elem) ;
}

- (void) bumpFirstColByOne {
    for (int i = 0 ; i < 2 ; ++ i) {
       int * arrayOfInt = arrayOfarrayOfInts[i] ;
       int ** second = &arrayOfInt[0] ;
       [self incrementElement: second] ;
    }
}

这里不需要 __autoreleasing,因为没有进行分配...

于 2013-10-21T21:51:02.653 回答