Идем дальше. Попробуем воспользоваться операционной очередью и добавим к ней две простые инициирующие операции (подробнее об инициирующих операциях рассказано в разделе 7.0). Дополнительные примеры кода, описывающие инициирующие операции, имеются в разделе 7.11. Вот объявление (.hm-файл) делегата приложения, в котором используются операционная очередь и две инициирующие операции:
@interface AppDelegate ()
@property (nonatomic, strong) NSOperationQueue *operationQueue;
@property (nonatomic, strong) NSInvocationOperation *firstOperation;
@property (nonatomic, strong) NSInvocationOperation *secondOperation;
@end
@implementation AppDelegate
А вот и внутренняя часть файла реализации делегата приложения:
— (void) firstOperationEntry:(id)paramObject{
NSLog(@"%s", __FUNCTION__);
NSLog(@"Parameter Object = %@", paramObject);
NSLog(@"Main Thread = %@", [NSThread mainThread]);
NSLog(@"Current Thread = %@", [NSThread currentThread]);
}
— (void) secondOperationEntry:(id)paramObject{
NSLog(@"%s", __FUNCTION__);
NSLog(@"Parameter Object = %@", paramObject);
NSLog(@"Main Thread = %@", [NSThread mainThread]);
NSLog(@"Current Thread = %@", [NSThread currentThread]);
}
— (BOOL) application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
NSNumber *firstNumber = @111;
NSNumber *secondNumber = @222;
self.firstOperation =[[NSInvocationOperation alloc]
initWithTarget: self
selector:@selector(firstOperationEntry:)
object: firstNumber];
self.secondOperation = [[NSInvocationOperation alloc]
initWithTarget: self
selector:@selector(secondOperationEntry:)
object: secondNumber];
self.operationQueue = [[NSOperationQueue alloc] init];
/* Добавляем операции в очередь. */
[self.operationQueue addOperation: self.firstOperation];
[self.operationQueue addOperation: self.secondOperation];
NSLog(@"Main thread is here");
self.window = [[UIWindow alloc] initWithFrame:
[[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
Вот что происходит в реализации данного кода.
У нас есть два метода, firstOperationEntry: и secondOperationEntry:. Каждый из этих методов принимает в качестве параметра объект и выводит в окне консоли информацию об актуальном потоке, главном потоке и этом параметре. Это входные методы инициирующих операций, которые будут добавляться в операционную очередь.
Мы инициализируем два метода типа NSInvocationOperation и задаем целевой селектор в точке входа каждой операции (эти точки входа были описаны выше).
Затем инициализируем объект типа NSOperationQueue. (Он может создаваться и до того, как созданы методы входа.) Объект очереди будет обеспечивать параллелизм в работе операционных объектов. На данном этапе операционная очередь может немедленно начать (а может и не начать) запускать инициирующие операции, пользуясь их методами start. При этом очень важно помнить, что после добавления операции в операционную очередь от вас не требуется запускать операции вручную. Обеспечением запуска занимается операционная очередь.
Итак, еще раз запустим код примера и посмотрим, что же у нас на консоли:
[Running_Tasks_Asynchronously_with_OperationsAppDelegate firstOperationEntry: ]
Main thread is here
Parameter Object = 111
[Running_Tasks_Asynchronously_with_OperationsAppDelegate secondOperationEntry: ]
Main Thread = {name = (null), num = 1}
Parameter Object = 222
Current Thread = {name = (null), num = 3}
Main Thread = {name = (null), num = 1}
Current Thread = {name = (null), num = 4}
Блестяще! Это доказывает, что инициирующие операции параллельно выполняются каждая в своем потоке и в то же время параллельно главному потоку, вообще не блокируя его. Теперь еще пару раз прогоним этот же код и посмотрим, какой вывод будет появляться в окне консоли. В таком случае вы можете получить совершенно иной результат, например:
Main thread is here
[Running_Tasks_Asynchronously_with_OperationsAppDelegate firstOperationEntry: ]
[Running_Tasks_Asynchronously_with_OperationsAppDelegate secondOperationEntry: ]
Parameter Object = 111
Main Thread = {name = (null), num = 1}
Current Thread = {name = (null), num = 3}
Parameter Object = 222
Main Thread = {name = (null), num = 1}
Current Thread = {name = (null), num = 4}
Очевидно, что главный поток не блокируется и что обе инициирующие операции работают параллельно с главным потоком. Это доказывает, что в операционной очереди сохраняется параллелизм даже тогда, когда в нее добавляются две непараллельные операции. Операционная очередь управляет потоками, необходимыми для осуществления операций.
Если бы вы создавали подклассы от NSOperation и добавляли в операционную очередь экземпляры нового класса, то ситуация складывалась бы несколько иначе. Не забывайте о некоторых моментах.
Если обычные операции, являющиеся подклассами от NSOperation, добавлять в операционную очередь, то они будут работать асинхронно. Поэтому необходимо переопределить метод экземпляра isConcurrent, относящийся к классу NSOperation, и возвратить значение YES.
Читать дальше
Конец ознакомительного отрывка
Купить книгу