Double pointer as parameter of Objective-C block

Is it possible (and if so, safe) to create / use a block that takes a double pointer as an argument?

For example:

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


Additional context, research and questions:

  • I am using ARC.
  • When I declare the above method and try to call it, Xcode automatically ends my method call as follows: [self methodWithBlock:^(NSError *__autoreleasing *error) {}]; What does __autoreleasing mean here and why is it being added? I guess this has something to do with ARC.
  • If this is possible and safe, can the pointer still be dereferenced in the block, as elsewhere?
  • In general, what are the important differences between what I am describing and simply passing a double pointer as a method parameter (for example, - (void)methodWithDoublePointer:(NSError **)error; )? What special considerations, if any, should be taken into account (again, assuming this is possible at all)?
+7
objective-c objective-c-blocks
source share
3 answers

The answers are yes and no ...

At a basic level, passing pointers to pointers to blocks is no different from passing them to methods; and, with the usual caveat that your pointers must be valid, everything is in order.

However, __autoreleasing very significant here and is tied to ARC and __autoreleasing . Whether the use of the block will work, as expected, will depend on the context, since the compiler often uses hidden variables when passing parameters of the NSError * __autoreleasing * type as part of the write-through implementation.

If forwarding is not needed or suitable for you differently, you can declare that you are blocking it as another type, for example NSError * __strong * . Read this answer , which explains what happens under the hood, which should help you decide if the block declaration is good in your context.

In conclusion (a) the declaration of the block is fine, but (b) you need to understand how it can be called and you might need to change the signature.

+2
source share

yes, pointers are always just pointers. you only need to make sure that you dereference it before sending it a message (assuming an objc object).

Also keep in mind that the pointer can be zero. always check it before trying to dereference it or what you have.

As mentioned in @verec, if you use ARC, you must declare the parameter as __autoreleasing

according to documents

__ autoreleasing is used to indicate arguments that are passed by reference (id *) and are auto-implemented upon return.

remember id is a pointer to an object, so it says the object **

there is no difference between passing pointers to pointers to methods or blocks.

+4
source share

warning: unverified

For the argument, let's start with:

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

errPtr is not declared by __weak or __strong.

So, according to ARC, although its contents are allocated within foo , the responsibility for releasing it must be somewhere.

Where?

Note that this is not a property of double pointers as such. But your distribution pattern.

consider the following issues:

 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] ; } } 

There is no need for __autoreleasing because distribution does not occur ...

0
source share

All Articles