Поиск с использованием NSOperation - PullRequest
0 голосов
/ 14 декабря 2010

Я пытаюсь создать панель поиска для поиска вещей, которые я получаю с помощью NSURLConnection.Прямо сейчас, если я что-то ищу, эта строка отправляется в виде URL-адреса с асинхронным запросом, который дает мне данные.

NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:urlString] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:20.0];
    [theConnection cancel];
    [theConnection release];

theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];

Эти данные анализируются, и когда они успешны, я публикую уведомление1004 *

-(void)connectionDidFinishLoading:(NSURLConnection *)connection
     {       
         xmlParser = [[NSXMLParser alloc] data];
         [xmlParser setDelegate:xmlGeocoder];
         BOOL success = [xmlParser parse];

         if(success == YES){
             NSLog(@"No Errors");

             [[NSNotificationCenter defaultCenter] postNotificationName:@"getArray" object:self];

         }else{
             NSLog(@"Error Error Error!!!");
             [[NSNotificationCenter defaultCenter] postNotificationName:@"failToGetArray" object:self];
         }
}

и мой searchresultsTableView перезагружается.

self.array1 = [array2 copy];
    [self.searchDisplayController.searchResultsTableView reloadData];

Все эти методы зависят друг от друга, поэтому выполнение B невозможно, когда A все еще занят.Я использую NSNotificationCenter, чтобы сказать им, чтобы они выполняли этот код.

Но я хочу попробовать NSOperation, и я понятия не имею, КАК реализовать это.Нужно ли размещать свои поисковые запросы в операции или в каждом используемом мной методе?

Может ли кто-нибудь дать мне пример кода, чтобы дать мне представление о том, как это должно быть сделано?Заранее спасибо ...

1 Ответ

2 голосов
/ 15 декабря 2010

NSOperation очень полезен.Чтобы использовать его, вы расширяете NSOperation и переопределяете метод "main".В основном методе вы выполняете свои вычисления / веб-запрос и т. Д. Таким образом, NSOperation лучше всего подходит для задач, которые вы можете заключить в несколько простых шагов, после каждого шага вы проверяете, все ли в порядке, и либо переходите к следующему шагу, либо отменяете операцию.Как только это будет сделано, вы можете просто создать свою собственную пользовательскую NSOperation и передать ее объекту NSOperationQueue, и он позаботится о потоке, запуске, остановке очистки и т. Д.

В приведенном ниже примере я написал протоколчтобы справиться с завершением задачи, я бы посоветовал вам использовать этот подход вместо использования уведомлений - если только у вас нет нескольких объектов, о которых нужно немедленно уведомлять.

Создайте новый класс, который расширяет класс NSOperation:

//This object takes a "searchTerm" and waits to be "started".
#import <Foundation/Foundation.h>

@protocol ISSearchOperationDelegate

- (void) searchDataReady:(NSArray*) searchResult;

@end


@interface ISSearchOperation : NSOperation {

    id <ISSearchOperationDelegate> delegate;

    NSString *searchTerm;
}   

@property(nonatomic, retain) NSString *searchTerm;

@property(nonatomic, assign) id delegate;

- (id) initWithSearchTerm:(NSString*) searchString;

@end

Когда объект, расширяющий NSOperation, добавляется в NSOperationQueue, объект очереди пытается вызвать «основной» метод в NSOperation, поэтому вы должны обернуть свою задачу в этом методе.(обратите внимание, что после каждой выполненной подзадачи я проверяю, хорошо ли она прошла, и «возвращаюсь», если нет. Класс NSOperation имеет свойство под названием isCancelled Это свойство может быть установлено с помощью NSOperationQueue, поэтому вы также должны проверитьесли это было установлено во время вашего завершения main. Итак, резюмируем, вы проверяете изнутри main, прошел ли каждый шаг, как вы хотели, и вы проверяете, отменял ли что-то извне вашу задачу.):

- (id) initWithSearchTerm:(NSString*) searchString {

    if (self = [super init]) {

        [self setSearchTerm:searchString];
    }

    return self;
}

- (void) main {

    [self performSelector:@selector(timeOut) withObject:nil afterDelay:4.0];
    if ([self isCancelled]) return;
    NSData *resultData = [self searchWebServiceForString:self.searchTerm];
    if (resultData == nil) return;
    if ([self isCancelled]) return;
    NSArray *result = [self parseJSONResult:resultData];    
    if ([self isCancelled]) return;
    if (result == nil) return;
    [NSObject cancelPreviousPerformRequestsWithTarget:self];
    [delegate performSelectorOnMainThread:@selector(searchDataReady:) withObject:result waitUntilDone:YES]; 
}

// Я не скопировал реализацию всех методов, которые я вызываю во время main, но я надеюсь, вы понимаете, что это просто «задачи», каждая из которых должна быть успешно выполнена, прежде чем следующая подзадача может быть вычислена.Итак, сначала я поставил там тест тайм-аута, затем я получаю свои данные из веб-службы и затем анализирую их.

Хорошо, чтобы все это заработало, вам нужна очередь.

Итакв классе, которым вы хотите быть делегатом для этой операции, вы делаете это:

где-то настраиваете очередь:

NSOperationQueue *q = [[NSOperationQueue alloc] init];
[self setQueue:q];
[q release];


- (void) doSearch:(NSString*) searchString {

    [queue cancelAllOperations];
    ISSearchOperation *searchOperation = [[ISSearchOperation alloc] initWithSearchTerm:searchString];
    [searchOperation setDelegate:self];
    [queue addOperation:searchOperation]; //this makes the NSOperationQueue call the main method in the NSOperation
    [searchOperation release];
}

//the delegate method called from inside the NSOperation
- (void) searchDataReady:(NSArray*) results {

    //Data is here!
}

Некоторым преимуществом с NSOperations является то, что с точки вызывающей сторонывид, мы просто создаем объект, устанавливаем делегата, ждем ответа.Но за кулисами запускается ряд многопоточных задач, которые можно отменить в любое время, и таким образом, чтобы они могли справиться, если многопоточные компоненты не работают.

Как видно из метода doSearch, он начинается с отменывсе предыдущие операции я выполнял в приложении, где каждый раз, когда пользователь вводил букву в слове, я искал веб-сервис.Это означает, что если бы пользователь искал «hello world» - я бы выполнил поиск «h», затем «he», затем «hel», затем «hell», затем «hello» и т. Д. Я хотел остановиться и убратьзадача "h", как только пользователь набрал "e", потому что она тогда устарела. Я обнаружил, что NSOperation был единственным способом, который давал отзывчивость многопоточности, и ни один из беспорядка, который обычно сопровождается порождением множества потоков сверхудруг друга.

Надеюсь, вы можете использовать его, чтобы начать:)

...