NSThread导致UIWebView崩溃

时间:2012-12-12 10:54:47

标签: iphone ios nstimer nsthread nsrunloop

我想从一开始就解释我的问题。我正在使用UIWebView创建一个应用程序。此外,我正在使用应用程序的用户捕捉屏幕,并使用该图像阵列创建视频。

我正在使用NSTimer来获取屏幕截图。我工作得很好,但我有一个问题。那是当用户开始滚动网页或用户在屏幕上触摸时,NSTimer暂停,在他发布触摸后NSTimer继续。

这是我用来获取屏幕截图的NSTimer。

assetWriterTimer = [NSTimer scheduledTimerWithTimeInterval:1.0f/24.0f
                                                    target:self
                                                  selector:@selector (writeSample)
                                                  userInfo:nil
                                                   repeats:YES];

我用Google搜索了这个问题,大部分人都得到了同样的问题。所以他们找到了答案,那就是使用NSRunLoop。他们说停止暂停NSTimer。

所以我使用NSRunLoop并将NSTimer添加到NSRunLoop中,这是我做完之后的代码。

NSRunLoop* runLoop = [NSRunLoop currentRunLoop];
assetWriterTimer = [NSTimer scheduledTimerWithTimeInterval:1.0f/24.0f
                                                    target:self
                                                  selector:@selector (writeSample)
                                                  userInfo:nil
                                                   repeats:YES];

[runLoop addTimer:assetWriterTimer forMode:NSRunLoopCommonModes];
[runLoop run];

此代码运行良好,并没有停止暂停NSTimer。但在我使用NSRunLoop后,我的应用程序真的很慢。此外,还需要花费大量时间将网页加载到WebView中,并且滚动速度也非常慢。

所以我开始再次搜索谷歌,我发现了这个问题。这就是主线程中所做的所有事情以及iphone不能同时处理所有事情。因此人们建议使用NSThread来解决问题。所以我所做的是创建一个NSThread并将进程附加到自定义线程。

在我将NSThread应用到它之后,这是我的代码。

    [NSThread detachNewThreadSelector:@selector(launchTimer) toTarget:self withObject:nil];

 -(void)launchTimer{


    NSRunLoop* runLoop = [NSRunLoop currentRunLoop];
    assetWriterTimer = [NSTimer scheduledTimerWithTimeInterval:1.0f/24.0f
                                                        target:self
                                                      selector:@selector (writeSample)
                                                      userInfo:nil
                                                       repeats:YES];

    [runLoop addTimer:assetWriterTimer forMode:NSRunLoopCommonModes];
    [runLoop run];

 }


-(void) writeSample{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    //did some coding here to take screen shot
    [pool release];
}

这解决了应用程序问题永远放缓的问题,我的应用程序再次运行非常顺利,但它现在带来了严重的问题。这是因为我猜想使用线程。我的自定义线程和主线程现在发生冲突并导致应用程序崩溃。我搜索谷歌的原因。我发现了一些与此类问题相关的问题,有些人回答了这些问题,并说任何UI更改都需要在主线程中完成。 UIWebView WebThread也必须在主线程中运行。

这些是我得到的一些错误报告,

enter image description here

enter image description here

这些错误就像一些线程冲突。但我不知道如何解决这个问题。我将我的代码用于一些没有任何Web视图或地图的本机应用程序。所以它适用于崩溃。但是,当我使用这个应用程序,有WebView或Map崩溃了一些时间,并给我这个错误。

我在这里遇到了很多麻烦,如果任何人可以提供任何想法或示例代码来处理线程,处理线程优先级,或者使用NSTimer和NSRunLoop而不使用NSThreads,或者在不使用NSThread的情况下克服应用程序的缓慢,任意回答非常非常有帮助,我期待很快收到你的回复。

感谢。

2 个答案:

答案 0 :(得分:0)

我的猜测是您编写的用于捕获屏幕截图的代码导致了问题。一个简单的测试是注释掉writeSample方法中的所有代码,看看应用程序是否仍然崩溃。我这样说是因为你说得对,所有与UI相关的任务都应该始终在主线程中运行。

我建议为计时器使用一个单独的线程,以便暂停计时器,然后从writeSample方法强制屏幕捕获代码在主线程上运行。

希望这有帮助

答案 1 :(得分:0)

首先关闭:

只要您使用计时器,就可以使用运行循环 - 您可以轻松see from the reference

  

计时器与运行循环一起使用。

(这是第二段的第一句话)

除此之外,还有你的症状:

  • 通过捕获图像来阻止线程,导致它断断续续。

这不应该让你感到惊讶!

  • 将该工作移出该线程,释放第一个工作的压力。

令人震惊,我知道!

好吧,鉴于您没有向我们展示导致同步问题的任何代码,(阅读:崩溃)这个讽刺的答案是我能为您提供的所有帮助。

以及阅读和内化我上面链接的文件的提示......


修改

我忘了提及,这个:

NSRunLoop* runLoop = [NSRunLoop currentRunLoop];
assetWriterTimer = [NSTimer scheduledTimerWithTimeInterval:blablabla];
[runLoop addTimer:assetWriterTimer forMode:NSRunLoopCommonModes];
[runLoop run];

没有多大意义,因为......

  

-scheduledTimerWithTimeInterval:目标:选择器:USERINFO:重复:

     

创建并返回一个新的NSTimer对象,并在默认模式下在当前运行循环上安排它。

magnificent documentation中也对此进行了解释。)

本质上:当你使用自己的私有线程时,默认模式就足够了。但是,您必须确保运行循环实际上正在运行。

这实际上是通过该代码段的最后一行完成的,但它有效地导致您的方法在取消定时器之前不会返回...