iOS,按下“后退”按钮时停止运行功能

时间:2012-03-06 13:34:07

标签: iphone ios xcode html-parsing

该应用程序由导航视图组成。 我在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的结果。现在崩溃...... 我认为这是因为我的功能仍然在后台运行。 如何解决这个问题?

4 个答案:

答案 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。如果没有必要,在早期优化中没有任何意义。

相关问题