该应用程序由导航视图组成。 我在viewDidAppear中调用了一个函数,它是
[self extractInfoWithWebsite:[NSString stringWithFormat:@"http://www.cineklik.com/%@-%@.aspx", self.cinemaType, self.location]];
此功能通过互联网上的当前网页进行HTML解析。 代码有点长,但想法是从网站中提取数据。
我遇到的问题是,如果用户决定在加载信息之前单击导航的后退按钮,页面将保持不变并且应用程序停止运行(不是崩溃但是变为静态,不会再做任何事了。)
有解决方案吗? 提前谢谢
编辑:
我将代码更改为以下内容: NSOperationQueue * queue = [NSOperationQueue new];
/* Create our NSInvocationOperation to call loadDataWithOperation, passing in nil */
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self
selector:@selector(extractInfoWithWebsite:)
object:[NSString stringWithFormat:@"http://www.cineklik.com/%@-%@.aspx", self.cinemaType, self.location]];
/* Add the operation to the queue */
[queue addOperation:operation];
[operation release];
现在我可以按下后退按钮而不会冻结,但现在出现以下错误导致崩溃: 试图从主线程或Web线程以外的线程获取Web锁。这可能是从辅助线程调用UIKit的结果。现在崩溃...... 我认为这是因为我的功能仍然在后台运行。 如何解决这个问题?
答案 0 :(得分:2)
我会查找NSOperation
NSOperation内部的标准方法是在进行繁重处理之前检查它们是否已被取消。
Here是开始研究的好链接。
编辑:我想我会澄清已取消的部分
NSOperations有一个main()和main(),这是一个很好的做法,比如
NSData* chunkyReply = nil;
if (!self.isCancelled) {
chunkyReply = [NSURL stuff];
}
if (!self.isCancelled) {
//parse chunkyReply
}
答案 1 :(得分:0)
您可以使用以下方式在后台运行加载代码:
[self performSelectorInBackground:<#(SEL)#> withObject:<#(id)#>];
然后你可以控制按下的后退按钮,你可以捕捉它
答案 2 :(得分:0)
有不同类型的方法,最适合我的方法是将进程封装在您在ViewDidLoad中创建并在ViewWillDisappear中停止的NSOperation中。
另一种方法是使用委托创建对象,然后在离开控制器时设置委托nil。
答案 3 :(得分:0)
如果不确切知道extractInfoWithWebsite:
的样子,很难给出更好的答案,但我会假设它分为两部分:
对于第一部分,如果您使用[NSData dataWithContentsOfURL:...]
或[NSURLConnection sendSynchronoushRequest:returningResponse:error:]
,则需要更改它们。这两种URL提取方法都不允许您取消请求。 Apple有good documentation关于如何使用异步,可取消的方法。
接下来是您对检索的数据执行的解析。除非您从Internet获取兆字节订单,否则您的解析可能不会值取消。但是,你应该在后台线程中进行繁重的工作:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//perform parsing
dispatch_async(dispatch_get_main_queue(), ^{
if (!self.view.window)
return; //won't update UI if we've moved offscreen
//call methods to update the UI
});
});
这将在默认优先级后台队列中执行解析,并在解析完成后更新主队列中的UI(任何文本字段等)。
是的,这是不可取消的,但就像我说的那样,除非您正在处理很多数据,否则将解析封装到NSOperation中可能是安全的。你会浪费一点CPU时间,但我会首先尝试这种方法,如果性能不是你需要的,那么稍后再改为NSOperation
。如果没有必要,在早期优化中没有任何意义。