iOS. Приемы программирования
Шрифт:
• Объекты операций обязаны выполнять «уведомление наблюдателей об изменениях в свойствах наблюдаемого объекта» (KVO, Key-Value Observing) на различных ключевых путях, в частности isFinished, isReady и isExecuting. В одной из следующих глав мы обсудим механизм KVO, а также KVC — механизм для доступа к полям объекта по именам этих полей.
• Если вы планируете создавать подкласс от NSOperation и выполнять специальную реализацию для операции, вам следует создать собственный автоматически высвобождаемый пул в методе main, относящемся к операции. Данный метод вызывается из метода start. Эти вопросы мы подробнее рассмотрим далее в этой главе.
• Всегда сохраняйте ссылки
Потоки и таймеры — это объекты, являющиеся подклассами от NSObject. Для порождения потока выполняется больше работы, чем для создания таймеров, а настройка цикла потока — более сложная задача, чем обычное слушание таймера, запускающего селектор. Когда приложение работает в операционной системе iOS, система создает для этого приложения как минимум один поток. Этот поток называется главным (Main Thread). Все потоки и таймеры должны добавляться в цикл исполнения (Run Loop). Цикл исполнения, как понятно из его названия, — это цикл, в ходе которого могут происходить разные события, например запуск таймера или выполнение потока. Обсуждение циклов исполнения выходит за рамки этой главы, но иногда я буду упоминать такой цикл.
Цикл исполнения — это, в сущности, обычный цикл, у которого есть начальная точка, условие завершения и серия событий, которые необходимо обработать в ходе этого цикла. Поток или таймер прикрепляются к циклу исполнения, и, в сущности, именно они заставляют цикл исполнения работать.
Главный поток приложения — это тот поток, который обрабатывает события пользовательского интерфейса. Если вы выполняете в главном потоке долговременную задачу, то быстро станет заметно, что интерфейс перестает отвечать на запросы или реагирует медленно. Во избежание этого можно создавать отдельные потоки и/или таймеры, каждый из которых выполняет собственную задачу (даже если она сравнительно долговременная). Но при этом главный поток не будет блокироваться.
7.1. Создание блоковых объектов
Постановка задачи
Необходимо иметь возможность писать собственные блоковые объекты либо использовать блоковые объекты с классами из iOS SDK.
Решение
Просто необходимо понимать базовую разницу между синтаксисом блоковых объектов и синтаксисом классических функций языка C. Эта разница рассматривается в подразделе «Обсуждение» данного раздела.
Обсуждение
Блоковые объекты могут быть либо встраиваемыми, либо записываемыми как отдельные блоки кода. Начнем с объектов второго типа. Предположим, у нас есть метод языка Objective-C, принимающий два целочисленных значения типа NSInteger и возвращающий разницу двух этих значений в форме NSInteger. Разница получается в результате вычитания одного значения из другого:
Очень просто, правда? Теперь преобразуем этот код Objective-C в классическую функцию языка C, обеспечивающую такую же функциональность. Это еще
Как видите, синтаксис функции на C значительно отличается от синтаксиса аналогичной функции на языке Objective-C. Теперь рассмотрим, как можно написать ту же функцию в виде блокового объекта:
Прежде чем перейти к детальному описанию синтаксиса блоковых объектов, приведу еще несколько примеров. Предположим, что у нас есть функция на языке C, принимающая параметр типа NSUInteger (беззнаковое целое число) и возвращающая строку типа NSString. Вот как данная функция реализуется на C:
Чтобы научиться форматировать строки с применением системонезависимых указателей формата на языке Objective-C, ознакомьтесь с String Programming Guide in the iOS Developer Library (Руководство по программированию строк в библиотеке разработчика iOS). Адрес документа на сайте Apple: https://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/Strings/Articles/formatSpecifiers.html.
Блоковый объект, эквивалентный данной функции языка C, показан в примере 7.1.
Пример 7.1. Образец блокового объекта, определенного в виде функции
Простейший независимый блоковый объект — это блоковый объект, возвращающий void и не принимающий никаких параметров:
Блоковые объекты инициируются точно так же, как и функции на языке C. Если у них есть какие-либо параметры, то вы передаете их так, как и в функции C. Любое возвращаемое значение можно получить точно так же, как и возвращаемое значение функции на языке C. Вот пример: