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

ЖАНРЫ

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

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

Шрифт:

В реализации операции необходимо переопределить два важных метода экземпляра 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];

Поделиться с друзьями: