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

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

Жанры

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

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

Шрифт:

self.window.backgroundColor = [UIColor whiteColor];

[self.window makeKeyAndVisible];

return YES;

}

Если активизировать метод класса currentThread, относящийся к классу NSThread, то выяснится, что блоковые объекты или функции C, направляемые вами в главную очередь, действительно работают в главном потоке:

— (BOOL) application:(UIApplication *)application

didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{

dispatch_queue_t mainQueue = dispatch_get_main_queue;

dispatch_async(mainQueue, ^(void) {

NSLog(@"Current thread = %@", [NSThread currentThread]);

NSLog(@"Main thread = %@", [NSThread mainThread]);

});

self.window = [[UIWindow alloc] initWithFrame:

[[UIScreen mainScreen] bounds]];

self.window.backgroundColor = [UIColor whiteColor];

[self.window makeKeyAndVisible];

return YES;

}

Вывод данного кода будет примерно таким:

Current thread = <NSThread: 0x4b0e4e0>{name = (null), num = 1}

Main thread = <NSThread: 0x4b0e4e0>{name = (null), num = 1}

Итак, мы изучили, как с помощью GCD решаются задачи, связанные с пользовательским интерфейсом. Перейдем к другим темам — в частности, поговорим о том, как выполнять задачи параллельно, используя параллельные очереди (см. разделы 7.5 и 7.6), и как при необходимости смешивать создаваемый код с кодом пользовательского интерфейса.

7.5. Синхронное решение с помощью GCD задач, не связанных с пользовательским интерфейсом

Постановка задачи

Необходимо выполнять синхронные задачи, в которых не участвует код, связанный с пользовательским интерфейсом.

Решение

Воспользуйтесь функцией dispatch_sync.

Обсуждение

Иногда необходимо решать задачи, никак не связанные с пользовательским интерфейсом, либо осуществлять процессы, которые взаимодействуют и с пользовательским интерфейсом, но в то же время заняты решением долговременных задач. Например, вам может понадобиться загрузить изображение, а после загрузки отобразить его для пользователя. Процесс загрузки совершенно не связан с пользовательским интерфейсом.

Любая задача, не связанная с пользовательским интерфейсом, позволяет применять глобальные параллельные очереди, которые предоставляет GCD. Они могут выполняться как синхронно, так и асинхронно. Но синхронное выполнение не означает, что программа дожидается, пока выполнится определенный фрагмент кода, а потом продолжает работу. Это лишь означает, что параллельная очередь дождется выполнения вашей задачи и только потом перейдет к выполнению следующего блока кода, стоящего в очереди. Когда вы ставите в параллельную очередь блоковый объект, ваша собственная программа всегда продолжает работу, не дожидаясь, пока выполнится код, стоящий в очереди. Дело в том, что параллельные очереди (как понятно из их названия) выполняют свой код в неглавных потоках. (Из этого правила есть исключение: когда задача передается в параллельную или последовательную очередь посредством функции dispatch_sync, система iOS при наличии такой возможности запускает задачу в текущем потоке. А это может быть и главный поток в зависимости от актуальной ветви кода. Это специальная оптимизация, запрограммированная в GCD, и вскоре мы обсудим ее подробнее.)

Если вы отправляете синхронную задачу в параллельную очередь и в то же время отправляете синхронную задачу в другую параллельную очередь, то две эти синхронные задачи будут выполняться асинхронно друг относительно друга, так как относятся к двум разным параллельным очередям. Этот нюанс важно понимать, поскольку иногда необходимо гарантировать, что задача B начнет выполняться только после того, как завершится задача А. Чтобы обеспечить такую последовательность, эти две задачи нужно синхронно отправлять в одну и ту же очередь.

Синхронные задачи в диспетчерской очереди можно выполнять с помощью функции dispatch_sync. Все, что от вас требуется, — снабдить эту функцию описателем той очереди, в которой должна выполняться задача, а также блоком кода, который должен выполниться в данной очереди.

Рассмотрим пример. Данная функция выводит на консоль числа от 1 до 1000, всю последовательность подряд, и при этом не блокирует основной поток. Мы можем создать блоковый объект, выполняющий подсчет за нас, и синхронно (дважды) вызвать этот же блоковый объект:

void (^printFrom1To1000)(void) = ^{

NSUInteger counter = 0;

for (counter = 1;

counter <= 1000;

counter++){

NSLog(@"Counter = %lu — Thread = %@",

(unsigned long)counter,

[NSThread currentThread]);

}

};

Итак, попробуем активизировать этот блоковый объект с помощью GCD:

— (BOOL) application:(UIApplication *)application

didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{

dispatch_queue_t concurrentQueue =

dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

dispatch_sync(concurrentQueue, printFrom1To1000);

dispatch_sync(concurrentQueue, printFrom1To1000);

// Точка переопределения для дополнительной настройки

// после запуска приложения

[self.window makeKeyAndVisible];

return YES;

}

Запустив этот код, вы заметите, что счетчик работает в главном потоке даже при том, что вы поставили эту задачу на выполнение в параллельную очередь. Оказывается, что это явление — специальная оптимизация GCD. Функция dispatch_sync будет использовать актуальный поток, то есть поток, который вы задействуете при направлении задачи в очередь, всякий раз, когда это возможно. В этом и заключается упомянутая оптимизация. Вот что об этом пишет Apple в справке по GCD: «В целях оптимизации работы данная функция активизирует блок кода в актуальном потоке всякий раз, когда это возможно».

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

Двойник Короля 5

Скабер Артемий
5. Двойник Короля
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Двойник Короля 5

Врубель

Коган Дора Зиновьевна
Жизнь в искусстве
Документальная литература:
биографии и мемуары
5.00
рейтинг книги
Врубель

#Бояръ-Аниме. Газлайтер. Том 13

Володин Григорий Григорьевич
13. История Телепата
Фантастика:
боевая фантастика
аниме
попаданцы
фэнтези
5.00
рейтинг книги
#Бояръ-Аниме. Газлайтер. Том 13

Креститель

Прозоров Александр Дмитриевич
6. Ведун
Фантастика:
фэнтези
8.60
рейтинг книги
Креститель

Кодекс Охотника. Книга XXXII

Винокуров Юрий
32. Кодекс Охотника
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Кодекс Охотника. Книга XXXII

Морской волк. 1-я Трилогия

Савин Владислав
1. Морской волк
Фантастика:
альтернативная история
8.71
рейтинг книги
Морской волк. 1-я Трилогия

Кодекс Охотника. Книга X

Винокуров Юрий
10. Кодекс Охотника
Фантастика:
фэнтези
попаданцы
аниме
6.25
рейтинг книги
Кодекс Охотника. Книга X

Война

Валериев Игорь
7. Ермак
Фантастика:
боевая фантастика
альтернативная история
5.25
рейтинг книги
Война

Кодекс Охотника. Книга XXXVIII

Винокуров Юрий
38. Кодекс Охотника
Фантастика:
фэнтези
боевая фантастика
попаданцы
юмористическое фэнтези
5.00
рейтинг книги
Кодекс Охотника. Книга XXXVIII

Чужак

Листратов Валерий
1. Ушедший Род
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Чужак

Газлайтер. Том 40

Володин Григорий Григорьевич
40. История Телепата
Фантастика:
альтернативная история
аниме
попаданцы
5.00
рейтинг книги
Газлайтер. Том 40

Законы Рода. Том 8

Мельник Андрей
8. Граф Берестьев
Фантастика:
юмористическое фэнтези
аниме
фэнтези
5.00
рейтинг книги
Законы Рода. Том 8

Я не князь. Книга XIII

Дрейк Сириус
13. Дорогой барон!
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Я не князь. Книга XIII

Сердце Дракона. Том 9

Клеванский Кирилл Сергеевич
9. Сердце дракона
Фантастика:
фэнтези
героическая фантастика
боевая фантастика
7.69
рейтинг книги
Сердце Дракона. Том 9