80

I'd like to store objective-c block in a property for later use. I wasn't sure how to do it so I googled a bit and there is very little info about the subject. But I've managed to find the solution eventually and I've thought that it might be worth sharing for other newbies like me.

Initially I've thought that I would need to write the properties by hand to use Block_copy & Block_release.

Fortunately I've found out that blocks are NSObjects and - copy/- release is equivalent to Block_copy/Block_release. So I can use @property (copy) to auto generate setters & getters.

Piotr Czapla
  • 25,734
  • 24
  • 99
  • 122
  • 1
    Possible duplicate of [Can I use Objective-C blocks as properties?](http://stackoverflow.com/questions/3935574/can-i-use-objective-c-blocks-as-properties) This question is more recent than the one there. – Richard J. Ross III Mar 12 '12 at 14:28
  • 1
    Full example code, UP-TO-DATE, explained simply for beginners: http://stackoverflow.com/a/20760583/294884 – Fattie Mar 20 '14 at 06:11
  • 1
    For new readers, this extremely old question is now happily extremely passé. You just say **@property (copy)void (^doStuff)(void);** with nothing more or less than copy. nowadys this is explained crystal-clearly (including the why) in a number of places in the apple doco. it couldn't be simpler; that's the whole answer. Indeed the whole issue is of only historic value since you now just use Swift. – Fattie Apr 03 '15 at 15:13

3 Answers3

137

Edit: updated for ARC

typedef void(^MyCustomBlock)(void);

@interface MyClass : NSObject

@property (nonatomic, copy) MyCustomBlock customBlock;

@end

@implementation MyClass

@end

MyClass * c = [[MyClass alloc] init];
c.customBlock = ^{
  NSLog(@"hello.....");
}

c.customBlock();
Dave DeLong
  • 242,470
  • 58
  • 448
  • 498
  • 5
    Anyone know why for blocks you should use (nonatomic, copy) and not (nonatomic,retain)? Typically retain is used and I can't find anywhere that explains why to use copy for blocks. – Steve Potter Feb 07 '12 at 21:28
  • 30
    Yes Dave, really. I can search also and saw those too. Explanations were vague like you use copy "to make them actually survive the stack frame." I figured that retaining the object would also do that. None explained how blocks are stack allocated. However, a comment did link to an article - http://cocoawithlove.com/2009/10/how-blocks-are-implemented-and.html that explained it well. See under "Blocks are slightly weird objects". So thank you! – Steve Potter Feb 10 '12 at 21:12
  • Dave -- I'm not really sure one should use "nonatomic" particularly. (FWIW - not necessarily correct!!! - the latest greatest Apple doco says you should use "copy" - end of story.) It's difficult to see that performance could matter, and since your post here is pretty much the world's only reference on the matter, perhaps it's a dangerous thing to have out there. Any thoughts on this obscure issue? Thanks! – Fattie Jan 24 '14 at 06:38
  • 2
    @JoeBlow you only need atomicity if you're worried about getting and setting the value of the property simultaneously from multiple queues. Otherwise it doesn't matter. – Dave DeLong Feb 11 '14 at 16:30
  • But Dave, the only possible reason to use "nonatomic" (today) is if (incredibly, for some bizarre reason) you are writing code that you WANT to NOT be safe (for some bizarre reason) if the code is ever used with multiple threads, multiple queues etc. Using "nonatomic" is, essentially, just wrong today. Why would you possibly, ever, want to deliberately make code unsafe? {Sure, set aside absolutely obscure scientific computing situations, etc.} Your word is Law, DDL, I just do whatever you say on here :) But I don't follow you here .. teach me – Fattie Feb 11 '14 at 18:43
  • 3
    I/we use `nonatomic` everywhere. It should have been default IMO. `atomic` makes for a larger binary, lower performance (locks on all accessors) and it appears to promise thread-safety - when usually that has to be solved at a higher level than property accessors. – Steven Kramer Aug 29 '14 at 21:37
  • @DaveDeLong What do you think of this answer, which says that, in ARC, a strong reference to a block type is equivalent to Block_copy? http://stackoverflow.com/questions/16426382/what-is-the-main-difference-using-copy-and-strong-ownership-qualifiers-in-pr Would you recommend using strong or copy in this case? – sethfri Jan 02 '15 at 21:37
104

Alternatively, without the typedef

@property (copy, nonatomic) void (^selectionHandler) (NSDictionary*) ;

Steven Kramer
  • 8,473
  • 2
  • 37
  • 43
  • 20
    To clarify, as the syntax is so opaque, this is a block property named "selectionHandler" that takes an NSDictionary* argument and returns void. – Christopher Pickslay Mar 30 '12 at 19:24
  • I don't think it is so hard to read, but I agree that it looks nicer with the typedef. I tend to write a bunch of typedefs for the parameters I want to usually pass: PFObjectBlock, PFStringBlock, PFArrayBlock, PFErrorBlock, etc. – Besi Jul 20 '12 at 13:34
  • would id, SEL, IMP allow further simplifications? – dklt Sep 20 '12 at 03:00
9

You can find a very good explanation of this in WWDC 2012 session 712 starting in page 83. The correct way of saving a block under ARC is the following:

@property(strong) my_block_type work;

Be careful with the retain cycles. A good way to solve is set the block to nil when you do not need it anymore:

self.work = nil;
Jorge Perez
  • 1,606
  • 1
  • 13
  • 4