【问题标题】:NSNotificationCenter - Way to wait for a notification to be posted without blocking main thread?NSNotificationCenter - 在不阻塞主线程的情况下等待通知发布的方式?
【发布时间】:2012-04-19 15:11:56
【问题描述】:

我正在使用 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.");

}

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

现在我会在获取完成之前在调试控制台中看到 “Fetch Complete.”

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

BOOL fetchingFlag;

然后尝试:

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

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

【问题讨论】:

  • 你可以在另一个线程中等待吗?
  • 你可以在单独的线程中进行解析
  • 如果你注册一个通知,你已经在等待而不阻塞主线程,对吧?
  • @WolfgangSchreurs 添加代码进一步解释。
  • 这里不清楚你想要什么。您不希望在异步作业完成之前发布通知吗?在工作结束时发布,而不是在开始之后立即发布。这就是重点。抱歉,如果我遗漏了什么。

标签: objective-c cocoa nsnotificationcenter nsnotifications


【解决方案1】:

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

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

在通知处理程序方法中,放置完成获取时需要做的所有事情。这是通知和其他回调方案的(一个)点——您的对象在收到该采取行动的通知之前不会做任何进一步的事情。

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

这正是它的工作原理。

【讨论】:

  • 在你所说的之后,然后重新思考我想要完成的事情并重新检查我的代码,你确实是正确的!谢谢!
【解决方案2】:

如果您不需要在任务完成时通知多个对象,您可以在-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,但是您应该能够了解大致的概念。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-09-18
    • 1970-01-01
    • 2013-12-26
    • 2020-12-01
    • 1970-01-01
    • 2019-12-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多