应用程序由导航视图组成。我正在调用viewDidPear中的一个函数,它是
[self extractInfoWithWebsite:[NSString stringWithFormat:@"http://www.cineklik.com/%@-%@.aspx", self.cinemaType, self.location]];
此函数从互联网上的当前网页进行HTML解析。代码共享有点长,但其理念是从网站中提取数据。
我遇到的问题是,如果用户决定在加载信息之前单击导航的后退按钮,页面将保持不变,应用程序将停止运行(不是崩溃,而是变为静态,不再执行任何操作)。
有解决办法吗?提前感谢
编辑:
我将代码更改为以下内容:NSOperationQueue*队列=[NSROperationQueue 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的结果。正在崩溃。。。我想这是因为我的功能仍然在后台运行。如何解决这个问题?
我会查找NSOperation
NSOperation内部的标准方法是在进行大量处理之前检查它们是否已被取消。
这里有一个很好的链接,可以开始你的研究。
编辑:我想我会澄清取消的部分
NSOperations有一个main(),在main()内部,做一些类似的事情是很好的做法
NSData* chunkyReply = nil;
if (!self.isCancelled) {
chunkyReply = [NSURL stuff];
}
if (!self.isCancelled) {
//parse chunkyReply
}
您可以在后台运行加载代码,使用:
[self performSelectorInBackground:<#(SEL)#> withObject:<#(id)#>];
然后你可以控制按下的后退按钮,你可以捕获它
有不同类型的方法,最适合我的方法是将流程封装在NSOperation中,该NSOperation是您在ViewDidLoad中创建并在ViewWillDisappear中停止的。
另一种方法是创建一个带有委托的对象,然后在离开控制器时将委托设置为零。
如果不确切地知道extractInfoWithWebsite:
是什么样子,很难给你一个更好的答案,但我假设它分为两部分:
- 从您传递的URL中检索数据
- 分析该数据
对于第一部分,如果使用[NSData dataWithContentsOfURL:...]
或[NSURLConnection sendSynchronoushRequest:returningResponse:error:]
,则需要更改它们。这两种URL获取方法都不允许取消请求。关于如何使用异步、可取消的方法,苹果有很好的文档。
接下来是对检索到的数据执行的解析。除非你从互联网上获取了一个兆字节的订单,否则你的解析可能不值得取消。然而,无论如何,你都应该在后台线程中完成繁重的工作:
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
。如果没有必要的话,早期优化毫无意义。