让按钮覆盖其他进程
Posted
技术标签:
【中文标题】让按钮覆盖其他进程【英文标题】:Have buttons override other processes 【发布时间】:2012-06-21 17:09:03 【问题描述】:在我的应用程序中,根视图控制器从 Internet 获取信息,对其进行解析,并将其显示在 viewDidAppear
中。我使用这种方法是因为我的应用程序嵌入在 UINavigationController
中,这样当用户按下后退按钮并弹出到根视图时,根视图控制器将重新加载其数据。
发生这种情况时,需要一些时间来获取和显示来自 Internet 的信息。在此期间,如果用户单击按钮移动到不同的视图,则在视图控制器完成获取 Web 数据的过程之前不会发生按钮动作。
如何使按钮覆盖其他进程并立即切换视图?这安全吗?提前致谢。
编辑
以下是我从网站中提取信息的部分示例(我的应用程序解析 html)。
NSURL *siteURL = [NSURL URLWithString:@"http://www.ridgefield.org/ajax/dist/emergency-announcements"];
NSError *error;
NSString *source = [NSString stringWithContentsOfURL:siteURL
encoding:NSUTF8StringEncoding
error:&error];
【问题讨论】:
【参考方案1】:这就是 Apple 人所追求的地方,“不要阻塞主线程!”。
这种工作流程的主要建议是使用单独的线程(读取:队列)从网络加载数据。然后完成加载的工作人员可以在您的视图控制器上设置一些属性,并且在该设置器内部是应该更新 UI 的地方。记得在主线程上调用 setter。
有几种方法可以剥去并发猫的皮肤,但是这个特定问题的答案使它们超出了范围。简短的回答是不要在主线程中加载,这应该会引导你到正确的地方。
【讨论】:
我查看了线程,但 Apple 似乎不希望您在辅助线程上执行任何与网络有关的操作? 我在文档中没有看到任何这样的情绪。我有两个非常依赖网络的应用程序,我们 100% 的负载发生在替代线程中。有时使用 NSOperationQueue 并行生成许多线程,每个线程都从 Web 加载。下面有一个答案建议在另一个线程中加载“现成”技术,但它基本上与此答案相同。 那么我能否通过另一个线程执行我的问题中的代码? 是的。简短的回答是将其包装到一个对调用者视图控制器也有弱引用的块中,并将其分派到另一个队列。有很多 SO 问题和很多很好的文档。这是大约 30-60 分钟的学习曲线,但知道如何快速利用 Grand Central Dispatch 将非常值得您花时间。请记住在主队列中回调 VC (dispatch_get_main_queue()
)
它不会自行停止,不。但是,当您需要时,您可以选择。起初,如果您使用同步调用,它根本不会被取消,但是当它调用回调时,您可以(在回调内部)检查您是否在屏幕上,如果没有则不更新 UI。将来,如果您想要更好地在中间停止加载,您将需要使用更复杂的加载技术,实现 URLConnection 委托方法,并在每个方法中检查您的回调 VC 是否在屏幕上,如果出现则取消加载不是。这超出了这个问题的范围,但这是正确的道路。【参考方案2】:
NSString 方法 stringWithContentsOfURL 是同步的,会阻塞你的主线程。
您可以使用异步 URL 请求,而不是使用后台线程来解决问题。这不会阻塞用户界面,因为委托协议用于让您知道请求何时完成。例如:
NSURL *url = [NSURL URLWithString:@""http://www.ridgefield.org/ajax/dist/emergency-announcements""];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
NSURLConnection* theConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
然后你的一些委托方法是:
-(void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLResponse*)theResponse
// create received data array
_receivedData = [[NSMutableData alloc] init];
-(void)connection:(NSURLConnection*)connection didReceiveData:(NSData*)theData
// append to received data.
[_receivedData appendData:theData];
-(void)connectionDidFinishLoading:(NSURLConnection*)connection
// now the connection is complete
NSString* strResult = [[NSString alloc] initWithData: _receivedData encoding:NSUTF8StringEncoding];
// now parse strResult
【讨论】:
这个技术还是用了另外一个线程,只是你不直接管理而已。 此外,您需要管理几个额外的委托方法来收集正在加载的数据,从而增加了复杂性。在另一个执行同步加载的队列上放置一个块会更简单(类似于刚刚添加到问题中的代码) OK,但是这里要解决的问题是UI被阻塞了。 那么我可以使用这种方法执行我的问题中的代码吗? 嗯,您是在网页上进行 GET,还是进行其他类型的通信?以上是关于让按钮覆盖其他进程的主要内容,如果未能解决你的问题,请参考以下文章
linux vfork的子程序与父进程共享内存,那为啥子进程执行exec就不会覆盖父进程呢?