我想从一开始就解释我的问题。我正在使用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也必须在主线程中运行。
这些是我得到的一些错误报告,
这些错误就像一些线程冲突。但我不知道如何解决这个问题。我将我的代码用于一些没有任何Web视图或地图的本机应用程序。所以它适用于崩溃。但是,当我使用这个应用程序,有WebView或Map崩溃了一些时间,并给我这个错误。
我在这里遇到了很多麻烦,如果任何人可以提供任何想法或示例代码来处理线程,处理线程优先级,或者使用NSTimer和NSRunLoop而不使用NSThreads,或者在不使用NSThread的情况下克服应用程序的缓慢,任意回答非常非常有帮助,我期待很快收到你的回复。
感谢。
答案 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中也对此进行了解释。)
本质上:当你使用自己的私有线程时,默认模式就足够了。但是,您必须确保运行循环实际上正在运行。
这实际上是通过该代码段的最后一行完成的,但它有效地导致您的方法在取消定时器之前不会返回...