Чтение онлайн

на главную - закладки

Жанры

iOS. Приемы программирования

Нахавандипур Вандад

Шрифт:

— (void) doCalculation{

/* Здесь происходят вычисления. */

}

— (void) calculationThreadEntry{

@autoreleasepool {

NSUInteger counter = 0;

while ([[NSThread currentThread] isCancelled] == NO){

[self doCalculation];

counter++;

if (counter >= 1000){

break;

}

}

}

}

— (BOOL) application:(UIApplication *)application

didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{

/* Начинаем поток. */

[NSThread detachNewThreadSelector:@selector(calculationThreadEntry)

toTarget: self

withObject: nil];

self.window = [[UIWindow alloc] initWithFrame:

[[UIScreen mainScreen] bounds]];

self.window.backgroundColor = [UIColor whiteColor];

[self.window makeKeyAndVisible];

return YES;

}

Программист должен создать поток вручную, а потом придать ему требуемую структуру (точку входа, автоматически высвобождаемый пул и основной цикл потока). Когда мы пишем аналогичный код с помощью GCD, нам на самом деле приходится сделать не так уж много. Мы просто помещаем наш код в блоковый объект и направляем этот блок в GCD для выполнения. Где именно будет выполняться данный код — в главном потоке или в каком-нибудь другом, — зависит именно от нас. Вот пример:

dispatch_queue_t queue =

dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

size_t numberOfIterations = 1000;

dispatch_async(queue, ^(void) {

dispatch_apply(numberOfIterations, queue, ^(size_t iteration){

/* Здесь выполняется операция. */

});

});

В этой главе будет рассказано обо всем, что нужно знать о GCD. Здесь вы научитесь писать современные многопоточные приложения для iOS и Mac OS X, помогающие достичь впечатляющей производительности на таких многоядерных устройствах, как iPad 2.

Мы довольно много будем работать с диспетчерскими очередями, поэтому необходимо досконально разобраться с теми концепциями, которые лежат в их основе. Диспетчерские очереди бывают трех типов.

 Главная очередь — занимается выполнением всех задач из главного потока, и именно здесь Cocoa и Cocoa Touch требуют от программиста вызывать все методы, относящиеся к пользовательскому интерфейсу. Пользуйтесь функцией dispatch_get_main_queue, помогающей управлять главной очередью.

 Параллельные очереди — это очереди, которые можно получать из GCD для выполнения синхронных или асинхронных задач. В нескольких параллельных очередях могут одновременно выполняться несколько задач, причем с завидной легкостью. Представляете, больше никакого управления потоками, ур-р-ра! Пользуйтесь функцией dispatch_get_global_queue, помогающей управлять параллельными очередями.

 Последовательные очереди — всегда выполняют поставленные в них задачи по принципу «первым пришел — первым обслужен» (First In First Out, FIFO). При этом не имеет значения, являются эти задачи синхронными или асинхронными. Такой принцип работы означает, что последовательная очередь может выполнять в любой момент только один блок кода. Однако такие очереди не применяются в главном потоке, поэтому отлично подходят для решения задач, которые должны выполняться в строгом порядке и не блокировать при этом главный поток. Чтобы создать последовательную очередь, пользуйтесь функцией dispatch_queue_create.

Существуют два механизма отправки задач в диспетчерские очереди:

блочные объекты (см. раздел 7.1);

• функции C.

Блочные объекты позволяют наиболее эффективно использовать GCD и его огромный потенциал. Некоторые функции GCD были расширены таким образом, чтобы программист мог использовать функции C вместо блочных объектов. Однако в действительности лишь небольшое подмножество GCD-функций допускают замену объектов функциями C, поэтому перед дальнейшим изучением материала обязательно ознакомьтесь с разделом о блочных объектах (разделом 7.1).

Функции C, предоставляемые различным GCD-функциям, должны относиться к типу dispatch_function_t. Вот как этот тип определяется в библиотеках Apple:

typedef void (*dispatch_function_t)(void *);

Итак, если мы хотим, например, создать функцию под названием myGCDFunction, потребуется реализовать ее следующим образом:

void myGCDFunction(void * paramContext){

/* Вся работа выполняется здесь */

}

Параметр paramContext относится к контексту, который GCD позволяет передавать C-функциям при диспетчеризации задач к этим функциям. Вскоре мы подробно об этом поговорим.

Блочные объекты, передаваемые GCD-функциям, не всегда имеют одинаковую структуру. Некоторые должны принимать параметры, другие — нет, но ни один блочный объект, передаваемый GCD, не возвращает значения.

В любой момент в ходе жизненного цикла приложения вы можете одновременно задействовать несколько диспетчерских очередей. В системе есть только одна основная очередь, но вы сами можете создать сколько угодно последовательных диспетчерских очередей (конечно, в разумных пределах) для любых функций, которые, возможно, понадобится реализовать в вашем приложении. Кроме того, можно получить несколько параллельных очередей и направить им ваши задачи. Задачи можно передавать диспетчерским очередям двумя способами: как блоковые объекты и как функции языка C, о чем рассказано ранее.

Блоковые объекты — это пакеты с кодом, которые в Objective-C обычно имеют форму методов. Блоковые объекты вместе с GCD образуют гармоничную среду, в которой можно создавать высокопроизводительные многопоточные приложения для iOS и Mac OS X. Вы можете спросить: «А что же такого особенного в блоковых объектах и GCD?» Ответ прост: больше никаких потоков! Все, что от вас требуется, — поместить код в блоковые объекты и перепоручить GCD выполнение этого кода.

Вероятно, важнейшая разница между блоковыми объектами и традиционными указателями на функции заключается в том, что блоковые объекты копируют значения локальных переменных, доступ к которым происходит внутри блокового объекта, и сохраняют эти копии для локального использования. Если значения этих переменных изменяются вне области видимости блокового объекта, вы тем не менее можете быть уверены в том, что в блоковом объекте сохранилась собственная копия переменной. Вскоре мы обсудим эти вопросы подробнее.

Поделиться:
Популярные книги

На границе империй. Том 10. Часть 6

INDIGO
Вселенная EVE Online
Фантастика:
боевая фантастика
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 10. Часть 6

Менталист. Трансформация

Еслер Андрей
4. Выиграть у времени
Фантастика:
фэнтези
альтернативная история
7.28
рейтинг книги
Менталист. Трансформация

Бастард Императора. Том 13

Орлов Андрей Юрьевич
13. Бастард Императора
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Бастард Императора. Том 13

Уникум

Поселягин Владимир Геннадьевич
1. Уникум
Фантастика:
альтернативная история
4.60
рейтинг книги
Уникум

Тьма чернее ночи

Коннелли Майкл
7. Гарри Босх
Детективы:
триллеры
7.64
рейтинг книги
Тьма чернее ночи

Офицер-разведки

Поселягин Владимир Геннадьевич
2. Красноармеец
Фантастика:
боевая фантастика
попаданцы
5.00
рейтинг книги
Офицер-разведки

Сфирот

Прокофьев Роман Юрьевич
8. Стеллар
Фантастика:
боевая фантастика
рпг
6.92
рейтинг книги
Сфирот

Черный Маг Императора 13

Герда Александр
13. Черный маг императора
Фантастика:
попаданцы
аниме
сказочная фантастика
фэнтези
5.00
рейтинг книги
Черный Маг Императора 13

Товарищ "Чума" 6

lanpirot
6. Товарищ "Чума"
Фантастика:
городское фэнтези
попаданцы
альтернативная история
5.00
рейтинг книги
Товарищ Чума 6

Сопротивление

Осадчук Алексей Витальевич
11. Последняя жизнь
Фантастика:
аниме
фэнтези
попаданцы
7.33
рейтинг книги
Сопротивление

Последний Паладин. Том 8

Саваровский Роман
8. Путь Паладина
Фантастика:
боевая фантастика
попаданцы
5.00
рейтинг книги
Последний Паладин. Том 8

Лондон

Резерфорд Эдвард
The Big Book
Проза:
историческая проза
6.67
рейтинг книги
Лондон

Запрети любить

Джейн Анна
1. Навсегда в моем сердце
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Запрети любить

Инженер Петра Великого 3

Гросов Виктор
3. Инженер Петра Великого
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Инженер Петра Великого 3