- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
iOS. Приемы программирования - Вандад Нахавандипур
Шрифт:
Интервал:
Закладка:
1. Мы собираемся асинхронно запускать блоковый объект в параллельной очереди.
2. В ходе выполнения этого блока будем однократно (синхронно) запускать другой блоковый объект. Его мы будем использовать для скачивания изображения по URL, при этом будет применяться функция dispatch_sync. Мы поступаем именно так, поскольку хотим, чтобы обработка остального кода, стоящего в данной параллельной очереди, не начиналась, пока не загрузится изображение. В результате мы заставляем подождать только одну параллельную очередь, а не все остальные очереди. Если синхронно скачивать файл по URL из асинхронного блока кода, мы заблокируем лишь очередь, обрабатывающую синхронную функцию, но не главный поток. Вся операция так и остается асинхронной с точки зрения главного потока. Мы решаем основную задачу: при загрузке изображения главный поток не блокируется.
3. Сразу после того, как загрузка изображения завершится, мы синхронно выполним блоковый объект в главной очереди (см. раздел 7.4), чтобы отобразить картинку в пользовательском интерфейсе.
Каркас для планируемой программы совершенно прост:
— (void) viewDidAppear:(BOOL)animated{
[super viewDidAppear: animated];
dispatch_queue_t concurrentQueue =
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(concurrentQueue, ^{
__block UIImage *image = nil;
dispatch_sync(concurrentQueue, ^{
/* Здесь скачивается изображение. */
});
dispatch_sync(dispatch_get_main_queue(), ^{
/* Здесь мы демонстрируем изображение пользователю и делаем это
в главной очереди. */
});
});
}
Второй вызов к dispatch_sync, после которого отобразится картинка, будет выполняться в очереди после первого синхронного вызова, который обеспечивает загрузку изображения. Именно этого мы и добивались, поскольку нам необходимо дождаться, пока изображение загрузится полностью, и только после этого мы сможем отобразить его для пользователя. Итак, после завершения скачивания изображения мы выполняем второй блоковый объект, но на этот раз — в главной очереди.
Скачаем изображение и отобразим его для пользователя. Это мы сделаем в методе экземпляра viewDidAppear:, относящемся к контроллеру вида, который в данный момент отображается в приложении для iPhone:
— (void) viewDidAppear:(BOOL)paramAnimated{
[super viewDidAppear: paramAnimated];
dispatch_queue_t concurrentQueue =
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(concurrentQueue, ^{
__block UIImage *image = nil;
dispatch_sync(concurrentQueue, ^{
/* Здесь скачивается изображение. */
/* Изображение iPad с сайта Apple. Гиперссылка слишком длинная,
поэтому ее нужно правильно разбить на две строки. */
NSString *urlAsString = @"http://images.apple.com/mobileme/features"
«/images/ipad_findyouripad_201 00518.jpg»;
NSURL *url = [NSURL URLWithString: urlAsString];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL: url];
NSError *downloadError = nil;
NSData *imageData = [NSURLConnection
sendSynchronousRequest: urlRequest
returningResponse: nil
error:&downloadError];
if (downloadError == nil &&
imageData!= nil){
image = [UIImage imageWithData: imageData];
/* Изображение у нас есть. Теперь можно его использовать. */
}
else if (downloadError!= nil){
NSLog(@"Error happened = %@", downloadError);
} else {
NSLog(@"No data could get downloaded from the URL.");
}
});
dispatch_sync(dispatch_get_main_queue(), ^{
/* Здесь картинка отображается, и это происходит в главной очереди. */
if (image!= nil){
/* Здесь создается вид с изображением. */
UIImageView *imageView = [[UIImageView alloc]
initWithFrame: self.view.bounds];
/* Задаем характеристики изображения. */
[imageView setImage: image];
/* Убеждаемся, что изображение масштабировано правильно. */
[imageView setContentMode: UIViewContentModeScaleAspectFit];
/* Добавляем изображение к виду данного контроллера вида. */
[self.view addSubview: imageView];
} else {
NSLog(@"Image isn't downloaded. Nothing to display.");
}
});
});
}
Как показано на рис. 7.2, мы успешно загрузили изображение, а также создали вид изображения, в котором картинка будет представлена пользователю в графическом интерфейсе.
Рис. 7.2. Загрузка изображения и демонстрация его пользователю, применяется GCD
Приведем другой пример. Допустим, у нас есть массив из 10 000 случайных чисел, которые сохранены в файле на диске. Мы хотим загрузить этот файл в память и отсортировать числа в порядке возрастания (то есть сделать так, чтобы список начинался с наименьшего числа). Потом мы хотим отобразить полученный список для пользователя. Инструмент управления, который будет применяться при этой операции, определяется тем, для какой системы вы пишете программу. В случае с iOS идеальным выходом было бы использовать экземпляр UITableView, а при работе с Mac OS X — экземпляр NSTableView. Поскольку массива у нас еще нет, начнем с его создания, потом загрузим этот массив, а потом отобразим.
Вот два метода, которые помогут нам найти место на диске устройства, где мы собираемся сохранить массив из 10 000 случайных чисел:
— (NSString *) fileLocation{
/* Получаем каталог (-и) документа. */
NSArray *folders =
NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask,
YES);
/* Мы что-нибудь нашли? */
if ([folders count] == 0){
return nil;
}
/* Получаем первый каталог. */
NSString *documentsFolder = [folders objectAtIndex:0];
/* Прикрепляем имя файла к концу пути документа. */
return [documentsFolder
stringByAppendingPathComponent:@"list.txt"];
}
— (BOOL) hasFileAlreadyBeenCreated{
BOOL result = NO;
NSFileManager *fileManager = [[NSFileManager alloc] init];
if ([fileManager fileExistsAtPath: [self fileLocation]]){
result = YES;
}
return result;
}
А вот теперь очень важный нюанс. Мы хотим сохранить на диске массив из 10 000 случайных чисел, если, и только если мы не создавали такой массив на диске раньше. В противном случае мы сразу загрузим массив с диска. Если же прежде мы не создавали этот массив на диске, то сначала создадим его, а потом перейдем к загрузке массива с диска. В итоге, если считывание массива с диска пройдет успешно, мы отсортируем этот массив в порядке возрастания и, наконец, отобразим результаты для пользователя в графическом интерфейсе. Реализацию отображения результатов пользователю оставляю вам для самостоятельной работы.
— (void) viewDidAppear:(BOOL)paramAnimated{
[super viewDidAppear: paramAnimated];
dispatch_queue_t concurrentQueue =
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
/* Если мы еще не отсортировали массив из 10 000 случайных чисел
на диске ранее, сгенерируем эти числа сейчас, а потом сохраним
их на диск в массиве. */
dispatch_async(concurrentQueue, ^{
NSUInteger numberOfValuesRequired = 10000;
if ([self hasFileAlreadyBeenCreated] == NO){
dispatch_sync(concurrentQueue, ^{
NSMutableArray *arrayOfRandomNumbers =
[[NSMutableArray alloc] initWithCapacity: numberOfValuesRequired];
NSUInteger counter = 0;
for (counter = 0;
counter < numberOfValuesRequired;
counter++){
unsigned int randomNumber =
arc4random() % ((unsigned int)RAND_MAX + 1);
[arrayOfRandomNumbers addObject:
[NSNumber numberWithUnsignedInt: randomNumber]];
}
/* Теперь записываем массив на диск. */
[arrayOfRandomNumbers writeToFile: [self fileLocation]
atomically: YES];
});
}
__block NSMutableArray *randomNumbers = nil;
/* Считываем числа с диска и сортируем их в порядке возрастания. */
dispatch_sync(concurrentQueue, ^{
/* Если файл на данный момент уже создан, занимаемся его считыванием. */
if ([self hasFileAlreadyBeenCreated]){
randomNumbers = [[NSMutableArray alloc]
initWithContentsOfFile: [self fileLocation]];
/* Теперь сортируем числа. */
[randomNumbers sortUsingComparator:
^NSComparisonResult(id obj1, id obj2) {

