Добро пожаловать в восьмую главу нашего путешествия по Objective-C! В этой главе мы снова обратимся к теме многопоточности и асинхронности, чтобы еще глубже понять, как создавать быстрые и отзывчивые приложения. Если вы уже знакомы с основами из предыдущих глав, то здесь мы закрепим знания и рассмотрим новые примеры. Как всегда, мы будем объяснять все простым и понятным языком, чтобы вы могли легко во всем разобраться.
Пример:
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
// Длительная задача
NSLog(@"Начало задачи");
[NSThread sleepForTimeInterval:3]; // Симуляция задержки
NSLog(@"Задача завершена");
});
NSLog(@"Этот код выполняется сразу, не дожидаясь завершения задачи");
Вывод:
dispatch_async(queue, ^{
// Фоновая задача
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"https://example.com/data.json"]];
// Возвращаемся в главный поток для обновления UI
dispatch_async(dispatch_get_main_queue(), ^{
// Обновляем интерфейс
self.label.text = @"Данные загружены";
});
});
Создание серийной очереди:
dispatch_queue_t serialQueue = dispatch_queue_create("com.example.serialQueue", DISPATCH_QUEUE_SERIAL);
Создание параллельной очереди:
dispatch_queue_t concurrentQueue = dispatch_queue_create("com.example.concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(serialQueue, ^{
NSLog(@"Задача 1");
});
dispatch_async(serialQueue, ^{
NSLog(@"Задача 2");
});
dispatch_async(serialQueue, ^{
NSLog(@"Задача 3");
});
Вывод:
dispatch_async(concurrentQueue, ^{
NSLog(@"Задача A");
});
dispatch_async(concurrentQueue, ^{
NSLog(@"Задача B");
});
dispatch_async(concurrentQueue, ^{
NSLog(@"Задача C");
});
Вывод может быть любым:
dispatch_sync(queue, ^{
NSLog(@"Синхронная задача");
});
NSLog(@"Этот код выполнится после завершения синхронной задачи");
Вывод:
dispatch_async(queue, ^{
NSLog(@"Асинхронная задача");
});
NSLog(@"Этот код выполнится сразу, не дожидаясь завершения асинхронной задачи");
Вывод:
Создание операций:
NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"Операция 1");
}];
NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"Операция 2");
}];
Добавление зависимостей:
[operation2 addDependency:operation1]; // Операция 2 выполнится после операции 1
Добавление операций в очередь:
NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init];
[operationQueue addOperations:@[operation1, operation2] waitUntilFinished:NO];
Вывод:
Пример использования dispatch_group:
dispatch_group_t group = dispatch_group_create();
dispatch_group_enter(group);
dispatch_async(queue, ^{
NSLog(@"Задача 1");
dispatch_group_leave(group);
});
dispatch_group_enter(group);
dispatch_async(queue, ^{
NSLog(@"Задача 2");
dispatch_group_leave(group);
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"Все задачи завершены");
});
Вывод:
Пример использования dispatch_barrier_async:
dispatch_queue_t concurrentQueue = dispatch_queue_create("com.example.concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(concurrentQueue, ^{
NSLog(@"Чтение данных 1");
});
dispatch_async(concurrentQueue, ^{
NSLog(@"Чтение данных 2");
});
dispatch_barrier_async(concurrentQueue, ^{
NSLog(@"Запись данных");
});
dispatch_async(concurrentQueue, ^{
NSLog(@"Чтение данных 3");
});
Вывод:
Пример использования @synchronized:
@synchronized(self) {
// Код внутри этого блока будет выполняться только одним потоком за раз
sharedCounter++;
}
Пример:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Фоновая задача
NSData *data = ...; // Длительная операция
dispatch_async(dispatch_get_main_queue(), ^{
// Обновление интерфейса
self.imageView.image = [UIImage imageWithData:data];
});
});
Решение: использование слабой ссылки
__weak typeof(self) weakSelf = self;
dispatch_async(queue, ^{
// Используем weakSelf вместо self
[weakSelf doSomething];
});
dispatch_get_main_queue()
или [[NSOperationQueue mainQueue] addOperationWithBlock:]
.dispatch_sync
на главной очереди.Пример дедлока:
dispatch_sync(dispatch_get_main_queue(), ^{
// Это приведет к дедлоку, так как главный поток ждет сам себя
});
Решение:
dispatch_async
для выполнения загрузки в фоне.Решение:
dispatch_queue_create
с DISPATCH_QUEUE_SERIAL
.dispatch_async
.Решение:
NSBlockOperation
для создания операций.addDependency
.NSOperationQueue
.Поздравляем! Вы успешно освоили более глубокие аспекты многопоточности и асинхронности в Objective-C. Теперь вы знаете, как использовать GCD и NSOperation для управления потоками, создавать очереди, синхронизировать задачи и избегать распространенных ошибок. Эти навыки помогут вам создавать быстрые и отзывчивые приложения, которые будут радовать пользователей.
В следующей главе мы поговорим о использовании сторонних библиотек в Objective-C. Вы узнаете, как подключать библиотеки с помощью CocoaPods, и познакомитесь с популярными инструментами, которые облегчат вам разработку.
Не забывайте практиковаться! Многопоточность — важный и сложный аспект разработки. Чем больше вы будете экспериментировать и писать код, тем лучше будете понимать, как создавать эффективные и надежные приложения.
Удачи и до встречи в следующей главе!
Просмотров: 49