NSNotificationCenter - 等待在不阻塞主线程的情况下发布通知的方法?

时间:2012-04-19 15:11:57

标签: objective-c cocoa nsnotificationcenter nsnotifications

我正在使用AFNetworking客户端对象,该对象对XML文档进行异步请求并对其进行解析。

还可以使用 NSNotificationCenter 在文档解析完毕后发布通知。

有没有办法等待在不阻止主线程的情况下发布通知?

E.g代码:

-(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.");

}

基本上我想知道在上面指定的区域需要什么样的代码来确保函数等待直到fetch完成?

就像现在一样,我会在提取完成之前在调试控制台中看到“Fetch Complete。”

我尝试在TLHTTPClient类中添加BOOL标志:

BOOL fetchingFlag;

然后尝试:

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

当此类收到通知时,它会设置RESTClient.fetchingFlag = FALSE;这应该在技术上杀死while循环吧?除了我的while循环无限运行?!

2 个答案:

答案 0 :(得分:2)

  

基本上我想知道在上面指定的区域中我需要什么样的代码来确保函数等待直到fetch完成?

您需要无代码。开始提取后不要在方法中放任何东西,什么都不会发生。您的程序将“等待”(它实际上将处理其他输入),直到收到通知为止。

在通知处理程序方法中,填写完成提取时需要执行的所有操作。这是通知和其他回调方案中的一个(一个) - 在收到通知表明是时候采取行动之前,您的对象不会做任何进一步的操作。

  

有没有办法在不阻塞主线程的情况下等待发布通知?

这正是它的工作方式。

答案 1 :(得分:0)

如果在完成任务后不需要通知多个对象,则可以向-fetchActiveUser:withPassword:方法添加完成处理程序(objc块)(因此它将变为类似-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,但你应该能够得到一般的想法。