64

If I want to pass nothing for an Objective-C block, what keyword should I use, NULL or nil? I'm asking this because an Objective-C block is an Objective-C object (as I know), but represented as a function pointer.

NULL and nil both indicate a 0x0 pointer, however they are different semantically. So I'm concerned about this.

jscs
  • 63,694
  • 13
  • 151
  • 195
eonil
  • 83,476
  • 81
  • 317
  • 516

1 Answers1

83

Blocks are not represented as function pointers. They're represented as blocks, and this is denoted by the ^ symbol in their declaration. Down under the hood, the only resemblance is the call syntax. Otherwise, they are both very, very different.

It is often useful to call methods on them. For instance, if you don't use garbage collection, you need to call the copy method on blocks if you want to keep them for later. With the advent of automatic retain count, this is even the only way to copy a block, since ARC pointer cast rules prevent you from using the Block_copy macro.

NULL is, depending on your compiler, either just 0 or (void*)0. This would work for any kind of pointer. However, because of the language rules of Objective-C, you'll get a warning if you try to send a message to a type that can't cast directly to id (and an error if you use ARC).

Since it can be useful to send messages to blocks, you should use nil for them.


[EDIT] Let's be clear that using either nil or NULL will result in exactly the same binary code. Your choice of the constant should probably be based on whether you consider blocks to be Objective-C objects or not. This was a bigger deal back in the days when you had to write your own retain and release calls, but now ARC does all the memory management work for you.

If you've used blocks before ARC was a thing, you probably think that they're Objective-C objects. If not, then you probably don't think/realize that they are. There are still a few relics of their identity in the language (for instance, you can have a __weak or __unsafe_unretained pointer to a block), but for the most part, the difference is negligible. Pick one and try to stick with it. I like to think of my blocks as Objective-C objects.

zneak
  • 134,922
  • 42
  • 253
  • 328
  • 13
    +1, for example the UIView class method for animation can have a parameter `completion` which is hinted as `(void (^)(BOOL finished))completion` and the documentation say: may be NULL. So I am not sure passing nil is the intended use. Please shed some light on this. – Nick Weaver Apr 23 '11 at 19:39
  • 14
    @Nick Weaver You can use `NULL` for any Objective-C type as well. The sole reason `nil` is preferred is that it satisfies the compiler in that `nil` is of type `id`, and it's valid to send a message to `id`, while it's not to send a message to a void pointer (it emits a warning). Since blocks are objects, there is no good reason to not use `nil` for them too. – zneak Apr 23 '11 at 20:29
  • Thanks for answer. It was my mistake about *function pointer*. I originally wanted to talk *function pointer form* :) But I was so sleepy... – eonil Apr 24 '11 at 03:12
  • 1
    Calling `-invoke` on a block is a [bad idea](https://devforums.apple.com/message/540071) as it's undocumented, implementation-specific behaviour that is subject to change. – Aidan Steele Sep 27 '11 at 03:10
  • ...and may not be portable. – i_am_jorf Jan 04 '13 at 00:42
  • @zneak, you mention sending messages to a block as the main reason they diverge from being like a c function despite the appearance. Can you give an example when blocks receive messages, vs being invoked regularly using ()? – Glen T Oct 30 '14 at 14:17
  • It's true that doing something like `[NULL copy]` would give you an error or warning, however since the method parameter would essentially be casted to a block type when the message is received, the actually call is more something like `[(void (^)(void))NULL copy]` which will not cause any compiler issues. I do think that using `nil` is a bit more appropriate semantically, although using `NULL` should technically work perfectly fine as well. – Matej Bukovinski Nov 07 '14 at 13:56