Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Double pointer as Objective-C block parameter

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

For instance:

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


Additional context, research, and questions:

  • I'm using ARC.
  • When I declare the method above and attempt to call it, XCode autocompletes my method invocation as follows: [self methodWithBlock:^(NSError *__autoreleasing *error) {}]; What does __autoreleasing mean here and why is it being added? I presume it has something to do with ARC.
  • If this is possible and safe, can the pointer still be dereferenced in the block as it would be anywhere else?
  • In general, what are the important differences between doing what I'm describing, and simply passing a double pointer as a method parameter (e.g. - (void)methodWithDoublePointer:(NSError **)error;)? What special considerations, if any, should be taken into account (again assuming this is possible at all)?
like image 881
George WS Avatar asked Oct 21 '13 21:10

George WS


2 Answers

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

Also be aware that the pointer may be nil. always check it before trying to dereference it or what have you.

As @verec mentioned if you are using ARC you should declare the parameter as __autoreleasing

according to the docs

__autoreleasing is used to denote arguments that are passed by reference (id *) and are autoreleased on return.

remember id is a pointer to an object so that is saying object**

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

like image 178
Brad Allred Avatar answered Oct 31 '22 18:10

Brad Allred


The answers are both Yes & No...

At a base level passing pointers to pointers to blocks is no different than passing them to methods; and, with the usual proviso that your pointers must be valid, is perfectly OK.

However that __autoreleasing is very significant here and is tied up with ARC and pass-by-writeback. Whether using the block will work as expected will be dependent on context as the compiler often uses hidden variables when passing parameters of type NSError * __autoreleasing * as part of the pass-by-writeback implementation.

If pass-by-writeback is not what you need, or is unsuitable, you may wish to declare you block as taking a different type, such as NSError * __strong *. Read this answer which explains what happens under the hood, that should help you decide whether in your context the block declaration is good.

In summary (a) declaring the block is fine, but (b) you need to understand how it may be called and may need to change the signature.

like image 40
CRD Avatar answered Oct 31 '22 19:10

CRD