当一个UIScrollView
(或其派生类)滚动时,似乎所有NSTimers
正在运行的都会暂停,直到滚动完成.
有办法解决这个问题吗?主题?优先级设置?什么?
我有一个动画透明的OpenGL ES子视图(Apple的模板EAGLView类的修改),它绘制一个旋转的球体.就像Apple的例子一样,CADisplayLink用在可用的设备上.
在同一屏幕上,有一个UIScrollView包含可以选择的UIButtons.当用户滚动UIScrollView时,我的EAGLView的动画会冻结.此行为在iPhone 2G设备上的iOS模拟器4.2和iPhone OS 3.1.3上重现.
除了编写自己的滚动视图之外,还有任何关于如何防止EAGLView暂停的想法?
我正在制作放大镜应用程序,允许用户触摸屏幕并移动他的手指,将有一个放大镜与他的手指路径.我通过截屏实现它并将图像分配给放大镜图像视图,如下所示:
CGSize imageSize = frame.size;
UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0.0);
CGContextRef c = UIGraphicsGetCurrentContext();
CGContextScaleCTM(c, scaleFactor, scaleFactor);
CGContextConcatCTM(c, CGAffineTransformMakeTranslation(-frame.origin.x, -frame.origin.y));
[self.layer renderInContext:c];
UIImage *screenshot = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return screenshot;
Run Code Online (Sandbox Code Playgroud)
问题是这个问题很self.layer renderInContext
慢,因此用户在移动手指时感觉不顺畅.self.layer renderInContext
然而,我试图在其他线程中运行,它使放大镜图像看起来很奇怪,因为放大镜中的图像显示延迟.
有没有更好的方法将视图渲染成图像?确实renderInContext:
使用GPU?
我有一个CAEAGLLayer支持的视图,它位于UIScrollView中.当我开始滚动时,调用openGL视图的-draw方法的CADisplayLink停止被调用.
我确认滚动时不会调用我的runloop启动/停止方法.一旦滚动开始,-draw方法就不会被调用,并且一旦滚动结束就恢复调用.
滚动开始后,UIKit是否会停止触发CADisplayLink?
显示链接被添加到运行循环中,如下所示:
[dl addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
Run Code Online (Sandbox Code Playgroud)
也许这个运行循环模式和UIScrollView存在冲突?是否存在其他运行循环模式或替代解决方案,即使在UIScrollView滚动时也能保持CADisplayLink触发?
我认为在任何应用程序中都不只有一个CADisplayLink.那是错的吗?
应用程序转到后台后,必须立即停止调用OpenGL函数.但不知何故,当用户按下主页按钮时,所有停止OpenGL的努力都会失败并且我的应用程序经常(但并不总是)崩溃.
它崩溃了
异常类型:EXC_BAD_ACCESS代码:KERN_INVALID_ADDRESS位于0x1 libGPUSupportMercury.dylib gpus_ReturnNotPermittedKillClient
据我所知,如果你在应用程序不在前台后调用OpenGL函数,应用程序将崩溃,因为GPU不适用于应用程序.
使用OpenGL呈现的视图具有调度队列
self.drawingQueue = dispatch_queue_create("openglRenderQueue", DISPATCH_QUEUE_SERIAL);
Run Code Online (Sandbox Code Playgroud)
它必须与UIScrollView并行渲染.所以有一个GCD 信号量让队列等待UIScrollView.
self.renderSemaphore = dispatch_semaphore_create(1);
Run Code Online (Sandbox Code Playgroud)
我创建了一个CADisplayLink来更新runloop:
CADisplayLink *dl = [[UIScreen mainScreen] displayLinkWithTarget:self selector:@selector(update)];
[dl addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
self.displayLink = displayLink;
Run Code Online (Sandbox Code Playgroud)
update方法在串行渲染队列上执行绘图计算异步,并使用信号量等待UIScrollView.它最终在主线程上提交同步.
- (void)update {
dispatch_async(drawingQueue, ^{
if (dispatch_semaphore_wait(renderSemaphore, DISPATCH_TIME_NOW) != 0) {
return;
}
@autoreleasepool {
[EAGLContext setCurrentContext:context];
glBindFramebufferOES(GL_FRAMEBUFFER_OES, framebuffer);
glViewport(0, 0, width, height);
glMatrixMode(GL_MODELVIEW);
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
// Quickly grab the target game state for rendering
GameState state = targetState;
[sprite drawState:state];
dispatch_sync(dispatch_get_main_queue(), ^{
if ([self canRender]) { …
Run Code Online (Sandbox Code Playgroud) 我在后台线程上使用与主线程不同的EAGLContext渲染OpenGL上下文.
我使用这样的东西:
- (void)renderInBackground {
EAGLContext *context = [[EAGLContext] alloc] init];
[EAGLContext setCurrentContext:context];
Rendering..
}
Run Code Online (Sandbox Code Playgroud)
但是,即使这是在后台线程中执行,当使用重型着色器时,主线程也会被阻塞,并且UI会卡住.
为什么后台线程阻塞主线程?方法不同步.
我正在使用GCD从互联网上进行一些后台加载.除了有点瑕疵之外,这很有效.在我的应用程序中,我有3个选项卡,当单击任何选项卡时,GCD开始为相应的选项卡执行后台加载.如果用户决定从第一个选项卡转到第二个选项卡(当GCD开始下载第一个选项卡的数据时),然后再次返回第一个选项卡.GCD将启动另一个后台线程(即使第一个后台线程尚未完成下载数据).
那么有没有办法检查后台线程当前是否正在运行?因此,如果用户选择非常快速地来回切换标签(由于某种原因),它就不会启动多个后台线程.
ios ×5
opengl-es ×4
iphone ×3
caeagllayer ×2
uikit ×2
uiscrollview ×2
calayer ×1
concurrency ×1
ios6 ×1
nstimer ×1
objective-c ×1
uiview ×1