хранение блоков в массиве

<p>в objective-c я знаю, что блоки считаются объектами, поэтому мне было интересно, можно ли их хранить в массиве. возникает вопрос, являются ли блоки первоклассными объектами или они просто обрабатываются как объекты ради передачи их между объектами? если они являются объектами первого класса, то не должны ли они храниться в массивах?</p>

<blockquote> <p><strong> редактировать: не вдаваясь в подробности, в arc теперь вы можете добавлять блоки в коллекции, как и любой другой объект </strong> (см. обсуждение).</p> </blockquote><p>я оставил оригинальный ответ без изменений, так как он содержит некоторые интересные технические детали.</p><hr><blockquote> <p>возникает вопрос, являются ли блоки первоклассными объектами или они просто обрабатываются как объекты ради передачи их между объектами? если они являются объектами первого класса, то не должны ли они храниться в массивах?</p> </blockquote><p>блоки - это объекты objective-c, которые очень похожи на любой другой объект nso, с несколькими ключевыми отличиями:</p><ul> <li> <p>блоки всегда генерируются компилятором. они эффективно "alloc/init" редактируются во время выполнения, поскольку выполнение проходит через объявление блоков.</p> </li> <li> <p>блоки изначально создаются в стеке. block\_copy () или метод <code>copy</code> <em> должны использоваться </em> для перемещения блока в кучу, если блок должен пережить текущую область (см. точку arc ниже).</p> </li> <li> <p>у блоков на самом деле нет вызываемого api помимо управления памятью.</p> </li> <li> <p>чтобы поместить блок в коллекцию, <strong> его сначала нужно скопировать </strong>. <strike>всегда. в том числе под arc.</strike> <em> (см. комментарии.) </em> если вы этого не сделаете, существует риск того, что выделенному стеку блоку будет <code>autoreleased</code>, и ваше приложение позже будет аварийно завершено.</p> </li> <li> <p>копирование блока на основе стека также скопирует все захваченное состояние. если вы делаете несколько копий блока, более эффективно скопировать его один раз, а затем скопировать копию (потому что копирование копии просто увеличивает количество сохраняемых элементов, поскольку блоки являются неизменяемыми).</p> </li> <li> <p>в arc возвращение блока из метода или функции "просто работает"; оно будет автоматически скопировано в кучу, и возвращение будет автоматически освобожденным блоком (компилятор может оптимизировать автоматическое освобождение при определенных обстоятельствах). даже с arc вам все равно нужно скопировать блок, прежде чем поместить его в коллекцию.</p> </li> </ul><p>я написал пару постов в блогах, в которых содержится <a href="http://www.friday.com/bbum/2009/08/29/basic-blocks/">введение в блоки</a> и некоторые <a href="http://www.friday.com/bbum/2009/08/29/blocks-tips-tricks/">советы и рекомендации</a> . вы можете найти их интересными.</p><p>и да, добавление их в словари весьма полезно. я написал пару кусочков кода, где я помещал блоки в словари как обработчики команд, где ключом было имя команды. очень кстати.</p>

<p>да, блоки действительно являются объектами, и вы можете поместить их в массивы:</p><pre><code>nsmutablearray *arr = [nsmutablearray new]; [arr addobject:^(){nslog(@"my block");}]; void (^ myblock)() = [arr objectatindex:0]; myblock(); </code></pre><p>это поместит "мой блок" в консоль.</p>