iOS,按下按钮时停止运行"back"功能



应用程序由导航视图组成。我正在调用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。如果没有必要的话,早期优化毫无意义。

最新更新