Какой правильный, нуль или NULL, чтобы отметить "no Objective-C block"?

Если я хочу ничего не передавать для блока Objective-C, какое ключевое слово использовать, NULL или nil? Я спрашиваю об этом, потому что блок Objective-C является объектом Objective-C (как я знаю), но представлен как указатель функции.

NULL и nil оба указывают указатель 0x0, однако они различны семантически. Поэтому я беспокоюсь об этом.

Ответ 1

Блоки не представлены как указатели на функции. Они представлены как блоки, и это обозначается символом ^ в их объявлении. Внизу под капотом единственное сходство - синтаксис вызова. В противном случае они оба очень разные.

Часто бывает полезно называть методы на них. Например, если вы не используете сбор мусора, вам нужно вызвать метод copy на блоках, если вы хотите сохранить их позже. С появлением автоматического удержания счета это даже единственный способ скопировать блок, поскольку правила управления указателями ARC не позволяют использовать макрос Block_copy.

NULL, в зависимости от вашего компилятора, либо просто 0, либо (void*)0. Это будет работать для любого указателя. Однако из-за языковых правил Objective-C вы получите предупреждение, если попытаетесь отправить сообщение типу, который не может быть напрямую передан в id (и ошибка, если вы используете ARC).

Так как может быть полезно отправлять сообщения блокам, вы должны использовать nil для них.


[EDIT] Пусть будет ясно, что использование либо nil, либо NULL приведет к точному тому же двоичному коду. Вероятно, ваш выбор константы должен основываться на том, считаете ли вы, что блоки являются объектами Objective-C или нет. Это была большая сделка в те времена, когда вам приходилось писать собственные вызовы retain и release, но теперь ARC делает все управление памятью для вас.

Если вы использовали блоки перед ARC, вы, вероятно, думаете, что это Objective-C объекты. Если нет, то вы, вероятно, не думаете/не осознаете, что они есть. Есть еще несколько реликтов их идентичности в языке (например, вы можете иметь указатель __weak или __unsafe_unretained для блока), но по большей части разница незначительна. Выберите один и попытайтесь придерживаться его. Мне нравится думать о моих блоках как о объектах Objective-C.