但是UIButton仍然按下,直到xml数据被返回,因此如果这是一个互联网服务的问题,它不能被纠正,应用程序实际上是不可用的.
这里是电话:
- {
- AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
- if(!appDelegate.XMLdataArray.count > 0){
- [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
- [appDelegate GetApps]; //function that retrieves data from Website and puts into the array - XMLdataArray.
- }
- XMLViewController *controller = [[XMLViewController alloc] initWithNibName:@"MedGearsApps" bundle:nil];
- [self.navigationController pushViewController:controller animated:YES];
- [controller release];
- }
它工作正常,但如何使视图按钮功能与卡住.换句话说,我只是想让UIButton和其他UIButton在后台运行起来.
我听说过PerformSelectorInMainThread,但我不能把它正确地练习
任何帮助是赞赏:)
解决方法@H_403_16@
你不太了解线程模型,如果您开始添加异步代码,而不必了解发生了什么,您可能会自己拍摄自己的脚步.
您编写的代码在主应用程序线程中运行.但是,当你想到它时,你不必写主要的功能 – 你只需要实现应用程序委托和事件回调(如触摸处理程序),并且以某种方式在时间到来时自动运行.这不是一个魔术,这只是一个名为Run Loop的Cocoa对象.
运行循环是接收所有事件的对象,处理定时器(如NSTimer中)并运行代码.这意味着,例如,当您在用户点按按钮时执行某些操作,调用树看起来有点像这样:
- main thread running
- main run loop
- // fire timers
- // receive events — aha,here we have an event,let’s call the handler
- view::touchesBegan…
- // use tapped some button,let’s fire the callback
- someButton::touchUpInside
- yourCode
现在,您的代码执行您想要执行的操作,“运行循环”继续运行.但是,当您的代码完成时间太长,例如在您的情况下,运行循环必须等待,因此在代码完成之前,事件将不会被处理.这是你在应用程序中看到的.
要解决这种情况,你必须在另一个线程中运行长操作.这不是很难,但是你必须考虑几个潜在的问题.在另一个线程中运行可以像调用performSelectorInBackground
一样简单:
- [appDelegate performSelectorInBackground:@selector(GetApps) withObject:nil];
而现在你必须考虑一种告诉应用程序已经加载数据的方法,例如在主线程上使用通知或调用选择器.顺便说一下:将数据存储在应用程序委托中(甚至使用应用程序委托来加载数据)不是很优雅的解决方案,但这是另一个故事.
如果您选择performSelectorInBackground解决方案,请查看有关memory management in secondary threads的相关问题.您将需要自己的自动释放池,以便您不会泄露自动释放的对象.
在一段时间后更新答案 – 现在通常最好使用Grand Central Dispatch在后台运行代码:
- dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),^{
- // No explicit autorelease pool needed here.
- // The code runs in background,not strangling
- // the main run loop.
- [self doSomeLongOperation];
- dispatch_sync(dispatch_get_main_queue(),^{
- // This will be called on the main thread,so that
- // you can update the UI,for example.
- [self longOperationDone];
- });
- });
您编写的代码在主应用程序线程中运行.但是,当你想到它时,你不必写主要的功能 – 你只需要实现应用程序委托和事件回调(如触摸处理程序),并且以某种方式在时间到来时自动运行.这不是一个魔术,这只是一个名为Run Loop的Cocoa对象.
运行循环是接收所有事件的对象,处理定时器(如NSTimer中)并运行代码.这意味着,例如,当您在用户点按按钮时执行某些操作,调用树看起来有点像这样:
- main thread running
- main run loop
- // fire timers
- // receive events — aha,here we have an event,let’s call the handler
- view::touchesBegan…
- // use tapped some button,let’s fire the callback
- someButton::touchUpInside
- yourCode
现在,您的代码执行您想要执行的操作,“运行循环”继续运行.但是,当您的代码完成时间太长,例如在您的情况下,运行循环必须等待,因此在代码完成之前,事件将不会被处理.这是你在应用程序中看到的.
要解决这种情况,你必须在另一个线程中运行长操作.这不是很难,但是你必须考虑几个潜在的问题.在另一个线程中运行可以像调用performSelectorInBackground
一样简单:
- [appDelegate performSelectorInBackground:@selector(GetApps) withObject:nil];
而现在你必须考虑一种告诉应用程序已经加载数据的方法,例如在主线程上使用通知或调用选择器.顺便说一下:将数据存储在应用程序委托中(甚至使用应用程序委托来加载数据)不是很优雅的解决方案,但这是另一个故事.
如果您选择performSelectorInBackground解决方案,请查看有关memory management in secondary threads的相关问题.您将需要自己的自动释放池,以便您不会泄露自动释放的对象.
在一段时间后更新答案 – 现在通常最好使用Grand Central Dispatch在后台运行代码:
- dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),^{
- // No explicit autorelease pool needed here.
- // The code runs in background,not strangling
- // the main run loop.
- [self doSomeLongOperation];
- dispatch_sync(dispatch_get_main_queue(),^{
- // This will be called on the main thread,so that
- // you can update the UI,for example.
- [self longOperationDone];
- });
- });