NSNotificationCenter — способ дождаться публикации уведомления без блокировки основного потока?

Я использую клиентский объект AFNetworking, который делает асинхронный запрос XML-документа и анализирует его.

Также используйте NSNotificationCenter для отправки уведомления о завершении синтаксического анализа документа.

Есть ли способ дождаться публикации уведомления, не блокируя основной поток?

Например код:

-(void)saveConfiguration:(id)sender {

    TLHTTPClient *RESTClient = [TLHTTPClient sharedClient];

    // Performs the asynchronous fetching....this works. 
    [RESTClient fetchActiveUser:[usernameTextField stringValue] withPassword:[passwordTextField stringValue]];

    /*
     * What do I need here ? while (xxx) ?
     */

    NSLog(@"Fetch Complete.");

}

В основном мне интересно, какой код мне нужен в указанной выше области, чтобы гарантировать, что функция ждет до завершения выборки?

Сейчас я увижу "Выборка завершена" в консоли отладки до завершения выборки.

Я попытался добавить флаг BOOL в класс TLHTTPClient:

BOOL fetchingFlag;

а затем пытается:

while([RESTClient fetchingFlag]) { NSLog(@"fetching...); } 

Когда этот класс получает уведомление, он устанавливает RESTClient.fetchingFlag = FALSE; который технически должен убить цикл while, верно? За исключением того, что мой цикл while работает бесконечно?!


person skålfyfan    schedule 19.04.2012    source источник
comment
Можно подождать в другой теме?   -  person MechEthan    schedule 19.04.2012
comment
вы можете сделать разбор в отдельном потоке   -  person Kamal    schedule 19.04.2012
comment
Если вы регистрируетесь на уведомление, вы уже ждете, не блокируя основной поток, верно?   -  person Wolfgang Schreurs    schedule 19.04.2012
comment
@WolfgangSchreurs добавил код для дальнейшего объяснения.   -  person skålfyfan    schedule 19.04.2012
comment
Непонятно, что вы хотите здесь. Вы не хотите, чтобы ваше уведомление публиковалось до завершения асинхронного задания? Разместите его в конце работы, а не сразу после ее начала. В этом-то и дело. Извините, если я что-то упустил.   -  person jrturton    schedule 19.04.2012


Ответы (2)


В основном мне интересно, какой код мне нужен в указанной выше области, чтобы гарантировать, что функция ожидает завершения выборки?

Вам не нужен код. Ничего не добавляйте в метод после начала выборки, и ничего не произойдет. Ваша программа будет «ждать» (на самом деле она будет обрабатывать другой ввод), пока не будет получено уведомление.

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

Есть ли способ дождаться публикации уведомления, не блокируя основной поток?

Именно так это уже работает.

person jscs    schedule 19.04.2012
comment
После того, что вы сказали, а затем переосмысления того, что я пытаюсь сделать, и повторного изучения моего кода, вы действительно были правы! Благодарность! - person skålfyfan; 19.04.2012

Если вам не нужно информировать несколько объектов после завершения задачи, вы можете добавить обработчик завершения (блок objc) в метод -fetchActiveUser:withPassword: (чтобы он стал чем-то вроде -fetchActiveUser:withPassword:completionHandler: и добавить код для выполнения в обработчике завершения.

Например, скажем, ваш метод -fetchActiveUser:withPassword:completionHandler: выглядит следующим образом:

- (void)fetchActiveUser:(NSString *)user 
           withPassword:(NSString *)pass 
      completionHandler:(void (^)(TLUser *user, NSError *error))handler
{
    NSURL *URL                   = [NSURL URLWithString:@"http://www.website.com/page.html"];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];    
    NSOperationQueue *queue      = [NSOperationQueue currentQueue];
    [NSURLConnection sendAsynchronousRequest:request 
                                       queue:queue 
                           completionHandler:^ (NSURLResponse *response, NSData *data, NSError *error) 
    {
        if (!handler) 
        { 
            return 
        };

        if (data) 
        {
            TLUser *user = [TLUser userWithData:data];

            if (user)
            {
                handler(user, nil);
            }
            else
            {
                NSError *error = // 'failed to create user' error ...
                handler(nil, error);
            }
        }
        else
        {
            handler(nil, error);
        }
    }];
}

Обработчик завершения будет вызываться всякий раз, когда задача будет завершена. Он либо вернет объект TLUser, либо ошибку, если что-то пошло не так (плохое соединение, формат данных изменился при синтаксическом анализе и т. д.).

Вы сможете вызвать метод следующим образом:

- (void)saveConfiguration:(id)sender 
{
    TLHTTPClient *RESTClient = [TLHTTPClient sharedClient];


    // Performs the asynchronous fetching

    [RESTClient fetchActiveUser:[usernameTextField stringValue] 
                   withPassword:[passwordTextField stringValue] 
              completionHandler:^ (TLUser *user, NSError *error)
    {
        if (user)
        {
            NSLog(@"%@", user);
        }
        else
        {
            NSLog(@"%@", error);    
        }
    }];
}

Конечно, в этом примере я использовал встроенные асинхронные методы NSURLConnection вместо AFNetworking, но вы должны получить общее представление.

person Wolfgang Schreurs    schedule 19.04.2012