我怎样才能回到主处理线程?

时间:2012-11-08 16:47:07

标签: ios multithreading ios6 nsurlconnection objective-c-blocks

我有一个应用程序,我正在访问一个带有NSURLConnection的远程网站来运行一些代码,然后保存一些XML文件。然后我访问这些XML文件并解析它们以获取信息。该过程正常,但我的用户界面未正确更新。我希望通过UILabel让用户更新。我正在尝试使用setBottomBarToUpdating:更新文本。当我将它设置为“Processing Please Wait ...”时,它第一次工作;但是,在connectionDidFinishLoading:它没有更新。我在想我的NSURLConnection是在一个单独的线程上运行的,而我在主线程上使用dispatch_get_main_queue进行更新的尝试是行不通的。如何更改代码以解决此问题?谢谢! [如果我需要包含更多信息/代码,请告诉我!]

myFile.m

NSLog(@"Refreshing...");

dispatch_sync( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
     [self getResponse:@"http://mylocation/path/to/file.aspx"];
});

[self setBottomBarToUpdating:@"Processing Please Wait..."];

queue = dispatch_queue_create("updateQueue", DISPATCH_QUEUE_CONCURRENT);

connectionDidFinishLoading:

if ([response rangeOfString:@"Complete"].location == NSNotFound]) {
  // failed
} else {
  //success
  dispatch_async(dispatch_get_main_queue(),^ {
       [self setBottomBarToUpdating:@"Updating Contacts..."];
  });

  [self updateFromXMLFile:@"http://thislocation.com/path/to/file.xml"];

  dispatch_async(dispatch_get_main_queue(),^ {
       [self setBottomBarToUpdating:@"Updating Emails..."];
  });

  [self updateFromXMLFile:@"http://thislocation.com/path/to/file2.xml"];  

}

3 个答案:

答案 0 :(得分:1)

在我的connectionDidFinishLoading中:我会尝试这样的事情:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),^ {
    if ([response rangeOfString:@"Complete"].location == NSNotFound]) {
      // failed
    } else {
      //success
      dispatch_async(dispatch_get_main_queue(),^ {
           [self setBottomBarToUpdating:@"Updating Contacts..."];
      });

      [self updateFromXMLFile:@"http://thislocation.com/path/to/file.xml"];

      dispatch_async(dispatch_get_main_queue(),^ {
           [self setBottomBarToUpdating:@"Updating Emails..."];
      });

      [self updateFromXMLFile:@"http://thislocation.com/path/to/file2.xml"];  
    }
});

然后,所有文件访问都在后台队列中进行,因此主队列未被锁定。主队列也将更快地完成对connectionDidFinishLoading的调用,因为你将所有的辛苦工作放在默认队列上,这应该让它(和主线程)准备好接受你对UI的更新的排队这将由默认队列完成,因为它处理刚刚入队的块。

队列切换成为

  • 主要线程回调到connectionDidFinishLoad:
  • 快速切换到默认全局队列释放主线程
  • 最终切换到setBottomBarToUpdating的主队列:调用
  • 在主线程上执行主队列块以正确更新UI
  • 最终完成主队列上的块
  • 最终完成默认队列上的块

你增加了并发性(你的好多核设备很好)你已经承担了主线程的I / O负担(从来都不是一个好的地方)而是让它专注于用户界面工作(适合它的地方)。

理想情况下,您也可以在主线程上运行NSURLConnection运行循环,但这可能足以让您继续运行。

答案 1 :(得分:0)

您也可以尝试performSelectorOnMainThread尝试:

if ([response rangeOfString:@"Complete"].location == NSNotFound]) {
                // failed
            } else {
                //success
                [self performSelectorOnMainThread:@selector(setBottomBarToUpdating) withObject:@"Updating Contacts..." waitUntilDone:false];

                [self updateFromXMLFile:@"http://thislocation.com/path/to/file.xml"];

                [self performSelectorOnMainThread:@selector(setBottomBarToUpdating) withObject:@"Updating Emails..." waitUntilDone:false];


                [self updateFromXMLFile:@"http://thislocation.com/path/to/file2.xml"];  

            }

答案 2 :(得分:0)

你在运行NSURLConnection的哪个运行循环?如果它是主循环,那么你正在排队setBottomBarToUpdating:你正在做的工作背后的调用,因此你没有看到UI更新的可能原因。