双指针作为Objective-C块参数

时间:2013-10-21 21:20:29

标签: objective-c objective-c-blocks

是否可以(如果是这样,安全)创建/使用以双指针作为参数的块?

例如:

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


其他背景,研究和问题:

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

3 个答案:

答案 0 :(得分:4)

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

还要注意指针可能是零。在尝试取消引用它或你有什么之前总是检查它。

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

根据the docs

  

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

记住id是一个指向对象的指针,这就是说对象**

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

答案 1 :(得分:2)

答案是肯定的和否...

在基类级别传递指向块指针的指针与将它们传递给方法没有什么不同;并且,通常的条件是你的指针必须有效,完全没问题。

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

如果pass-by-writeback不是您需要的或不适合的,您可能希望声明阻止采用其他类型,例如NSError * __strong *。阅读this answer,它解释了幕后发生的事情,它可以帮助您确定在您的上下文块声明是否合适。

总结(a)声明阻止是好的,但是(b)你需要了解它是如何被调用的,可能需要更改签名。

答案 2 :(得分: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因为没有进行分配......