#objective-c #syntax #objective-c-blocks
#objective-c #синтаксис #objective-c-блоки
Вопрос:
Если я хочу ничего не передавать для блока 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
для них.
[РЕДАКТИРОВАТЬ] Давайте проясним, что использование nil
или NULL
приведет к точно такому же двоичному коду. Ваш выбор константы, вероятно, должен основываться на том, считаете ли вы блоки объектами Objective-C. Это было более сложной задачей в те дни, когда вам приходилось писать свои собственные вызовы retain
и release
, но теперь ARC выполняет всю работу по управлению памятью за вас.
Если вы использовали блоки до появления ARC, вы, вероятно, думаете, что они являются объектами Objective-C. Если нет, то вы, вероятно, не думаете / осознаете, что это так. В языке все еще есть несколько остатков их идентичности (например, у вас может быть указатель на блок __weak
или __unsafe_unretained
), но по большей части разница незначительна. Выберите один и постарайтесь придерживаться его. Мне нравится думать о своих блоках как об объектах Objective-C.
Комментарии:
1. 1, например, метод класса UIView для анимации может иметь параметр,
completion
который обозначается как(void (^)(BOOL finished))completion
, и в документации сказано: может быть NULL. Поэтому я не уверен, что передача nil является предполагаемым использованием. Пожалуйста, пролейте немного света на это.2. @Nick Weaver Вы также можете использовать
NULL
для любого типа Objective-C. Единственная причина, по которойnil
является предпочтительным, заключается в том, что он удовлетворяет компилятору в том, чтоnil
имеет типid
, и он допустим для отправки сообщенияid
, в то время как он не предназначен для отправки сообщения указателю void (он выдает предупреждение). Поскольку блоки являются объектами, нет веской причины не использоватьnil
и для них тоже.3. Спасибо за ответ. Это была моя ошибка с указателем на функцию . Изначально я хотел поговорить о форме указателя на функцию 🙂 Но мне так хотелось спать…
4. Вызов
-invoke
блока — плохая идея , поскольку это недокументированное поведение, зависящее от конкретной реализации, которое может быть изменено.5. … и может быть не переносимым.