- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
iOS. Приемы программирования - Вандад Нахавандипур
Шрифт:
Интервал:
Закладка:
self.simpleOperation = [NSBlockOperation blockOperationWithBlock: ^{
NSLog(@"Main Thread = %@", [NSThread mainThread]);
NSLog(@"Current Thread = %@", [NSThread currentThread]);
NSUInteger counter = 0;
for (counter = 0;
counter < 1000;
counter++){
NSLog(@"Count = %lu", (unsigned long)counter);
}
}];
/* Запуск операции. */
[self.simpleOperation start];
/* Выводим что-нибудь на консоль, просто чтобы проверить,
должны мы дожидаться, пока выполнится блок кода, или нет.*/
NSLog(@"Main thread is here");
self.window = [[UIWindow alloc] initWithFrame:
[[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
Если запустить приложение, мы увидим, что на экране выводятся значения от 0 до 999, а за ними следует сообщение Main thread is here (Это главный поток):
Main Thread = <NSThread: 0x68 10280>{name = (null), num = 1}
Current Thread = <NSThread: 0x68 10280>{name = (null), num = 1}
…
Count = 991
Count = 992
Count = 993
Count = 994
Count = 995
Count = 996
Count = 997
Count = 998
Count = 999
Main thread is here
Итак, убеждаемся, что, поскольку блоковая операция была запущена в методе application: didFinishLaunchingWithOptions:, который сам работает в главном потоке, код внутри блока также выполняется в главном потоке. Основные сведения, которые мы получаем из этих регистрационных записей (логов), сводятся к следующему: операция блокировала главный поток, и потребовалось вернуться к выполнению кода основного потока после того, как была завершена работа блоковой операции. Это образец очень непрофессионального программирования. На самом деле программисты, работающие с iOS, должны идти на любые уловки и пользоваться любыми известными им приемами, чтобы обеспечивать отклик основного потока в любой момент и чтобы этот поток мог заниматься своим основным делом — обработкой пользовательского ввода. Вот что об этом пишет Apple.
«Необходимо внимательно отслеживать, какие задачи вы решаете в главном потоке вашего приложения. Именно в главном потоке ваша программа отрабатывает события касания и другой пользовательский ввод. Чтобы гарантировать, что приложение в любой момент будет откликаться на действия пользователя, никогда не следует загружать главный поток выполнением долговременных задач либо выполнением задач с потенциально неопределенным концом. Таковы, в частности, задачи, связанные с доступом к сети. Напротив, подобные задачи следует решать в фоновых потоках. Оптимальный способ решения таких задач — заключение их в объект операции и добавление этого объекта к операционной очереди. Но вы можете и сами создавать потоки вручную».
Подробнее эта тема рассматривается в документе Performance Tuning («Повышение производительности») в справочной библиотеке iOS. Документ расположен по адресу https://developer.apple.com/library/ios/documentation/iphone/conceptual/iphoneosprogrammingguide/PerformanceTuning/PerformanceTuning.html#//apple_ref/doc/uid/TP400 07072-CH8-SW1.
Кроме вызовов и блоковых операций, вы можете также создавать подклассы от NSOperation и выполнять вашу задачу в этом классе. Перед тем как переходить к работе, обратите внимание на некоторые нюансы, связанные с созданием подклассов от NSOperation.
Если вы не планируете пользоваться операционной очередью, то необходимо открепить от вашего потока новый поток. Это делается в методе start, относящемся к операции. Если вы не хотите пользоваться операционной очередью, а также не собираетесь выполнять данную операцию асинхронно с другими операциями, запускаемыми вручную, то можно просто вызвать метод main операции в методе start.
В реализации операции необходимо переопределить два важных метода экземпляра NSOperation — методы isExecuting и isFinished. Их может вызывать любой другой объект. В этих методах необходимо возвращать потоковобезопасное значение, которым можно будет управлять прямо из операции. Как только операция начинается, она должна посредством механизма «уведомления наблюдателей об изменениях в свойствах наблюдаемого объекта» (KVO) сообщать всем слушателям о том, что вы изменяете возвращаемые значения для двух этих методов. В примере с кодом мы рассмотрим, как это происходит на практике.
В методе main, относящемся к операции, необходимо создать собственный автоматически высвобождаемый пул на случай, если когда-нибудь в будущем операция будет добавлена в операционную очередь. Необходимо убедиться в том, что операции можно задействовать обоими способами — как при запуске вручную, так и при запуске в рамках операционной очереди.
У вас должен быть метод-инициализатор для ваших операций. Это обязательно должен быть специальный метод, выделенный под конкретную операцию. Все остальные методы-инициализаторы, в том числе применяемый по умолчанию метод init, должны вызывать вышеупомянутый специальный инициализатор, который содержит наибольшее количество параметров. Другие методы-инициализаторы должны гарантировать, что они передают подходящие параметры методу-инициализатору (если вообще передают).
Вот объявление объекта операции (.h-файл):
#import <Foundation/Foundation.h>
@interface CountingOperation: NSOperation
/* Выделенный инициализатор */
— (id) initWithStartingCount:(NSUInteger)paramStartingCount
endingCount:(NSUInteger)paramEndingCount;
@end
Реализация операции (записываемая в. m-файле) несколько длинновата, но, надеюсь, вполне понятна:
#import «CountingOperation.h»
@implementation CountingOperation
@property (nonatomic, unsafe_unretained) NSUInteger startingCount;
@property (nonatomic, unsafe_unretained) NSUInteger endingCount;
@property (nonatomic, unsafe_unretained, getter=isFinished) BOOL finished;
@property (nonatomic, unsafe_unretained, getter=isExecuting) BOOL executing;
@end
@implementation CountingOperation
— (instancetype) init {
return([self initWithStartingCount:0
endingCount:1000]);
}
— (instancetype) initWithStartingCount:(NSUInteger)paramStartingCount
endingCount:(NSUInteger)paramEndingCount{
self = [super init];
if (self!= nil){
/* Сохраните эти значения для главного метода. */
startingCount = paramStartingCount;
endingCount = paramEndingCount;
}
return(self);
}
— (void) main {
@try {
/* Это автоматически высвобождаемый пул. */
@autoreleasepool {
/* Сохраняем здесь локальную переменную, которая
должна быть установлена в YES всякий раз, когда
мы завершаем выполнение задачи. */
BOOL taskIsFinished = NO;
/* Создаем здесь цикл while, существующий лишь в том случае,
когда переменная taskIsFinished устанавливается в YES
или операция отменяется. */
while (taskIsFinished == NO &&
[self isCancelled] == NO){
/* Здесь выполняется задача. */
NSLog(@"Main Thread = %@", [NSThread mainThread]);
NSLog(@"Current Thread = %@", [NSThread currentThread]);
NSUInteger counter = startingCount;
for (counter = startingCount;
counter < endingCount;
counter++){
NSLog(@"Count = %lu", (unsigned long)counter);
}
/* Очень важно. Здесь мы можем выйти из цикла, по-прежнему
соблюдая правила, по которым отменяются операции. */
taskIsFinished = YES;
}
/* Соответствие KVO. Генерируем требуемые уведомления KVO. */
[self willChangeValueForKey:@"isFinished"];
[self willChangeValueForKey:@"isExecuting"];
finished = YES;
executing = NO;
[self didChangeValueForKey:@"isFinished"];
[self didChangeValueForKey:@"isExecuting"];
}
}
@catch (NSException * e) {
NSLog(@"Exception %@", e);
}
}
@end
Операцию можно начать так:
@interface AppDelegate ()
@property (nonatomic, strong) CountingOperation *simpleOperation;
@end
@implementation AppDelegate
— (BOOL) application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
self.simpleOperation = [[CountingOperation alloc] initWithStartingCount:0
endingCount:1000];
[self.simpleOperation start];
NSLog(@"Main thread is here");
self.window = [[UIWindow alloc] initWithFrame:
[[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
@end
Запустив данный код, мы увидим в окне консоли следующие результаты, точно как при применении блоковой операции:

