我有一个EAGLView,我希望将其转换为UIImage。我可以使用此处发布的解决方案执行此操作:
How to get UIImage from EAGLView?
但是,如果在创建EAGLView和UIImage之间花费了少量时间,我只能做到这一点。
此代码创建了一个EAGLView,然后是一个UIImageView,它不起作用:
EAGLView *EAGLphoto = [[EAGLView alloc] initWithImage:photo.workAreaImage];
[theWorkArea.photoArea1 addSubview:EAGLphoto];
//I put a glfinish() here but it didn't help
UIImageView *photoView = [[UIImageView alloc] initWithImage:[self glToUIImage]];
//glToUIImage is taken from the link above
[theWorkArea.photoArea2 addSubview:photoView];
我假设UIImageView尝试在EAGLView创建完成之前创建。我试图在它们之间放一个glfinish(),但它没有做任何事情。当我运行代码时,EAGLView显示正常,但UIImageView显示为黑色。
但是,上述代码的这个修改版本有效:
EAGLView *EAGLphoto = [[EAGLView alloc] initWithImage:photo.workAreaImage];
[theWorkArea.photoArea1 addSubview:EAGLphoto];
[self performSelector:@selector(getUIImage) withObject:nil afterDelay:0.1];
- (void)getUIImage {
UIImageView *photoView = [[UIImageView alloc] initWithImage:[self glToUIImage]];
//glToUIImage is taken from the link above
[theWorkArea.photoArea2 addSubview:photoView];
}
我是否正确使用glfinish()?有没有比我的黑客更好的方法?
答案 0 :(得分:0)
通常当您对UIKit对象进行可见的更改而不是立即更新时,他们只是标记自己以便将来进行这些更改,然后在您放弃主线程时将整个更改集合作为批处理(通过返回到runloop)。这不是错误或实现中的失败,它实际上通常是你所暗示的,是你可以编写代码的原因:
view.frame = someNewFrame;
view.someOtherProperty = someOtherValue;
并且不用担心在采用其他更改之前,视图通常会明显采用新帧。通常,您希望对视图执行的操作看起来是原子的。
偶尔会遇到一种情况,就像你在这里一样,你已经要求的改变尚未生效的事实已暴露出来。 frame
和someOtherProperty
会在上面的示例中返回新值,这样您就不会关心更改是否立即生效,而是基于您对performSelector:withObject:afterDelay:
的观察你偶然发现了变化并不是假装立刻的情况。
EAGLView
难以诊断,因为它不是真正的UIKit功能。它所构建的CAEAGLLayer
是,EAGLView
只是Apple在各种示例项目中为CAEAGLLayer
构建的自定义UIView子类所采用的名称。他们在他们的示例中对EAGLView
的接口或实现并不一致,但我猜是可能会创建OpenGL帧缓冲对象(也就是说,OpenGL用来存储数字的东西)与像素相关,只允许glReadPixels
工作),只有在被要求自己解决时,它才会自行解决,直到UIKit要求它这样做。直到你退出runloop之后才会这样做。
可以通过查看您拥有的EAGLView
的代码来确认诊断。如果glGenFramebuffers
,layoutSubviews
或某些其他方法(由相关的{{1}未直接调用)触发了drawRect
之类的内容,则会发出大量调用然后证明了这一点。
假设诊断正确,您可以调整init
,但我认为最好的解决方案可能就是坚持EAGLView
。这不是一个竞争条件,因此解决方案没有丝毫不稳定或不可靠,只是略微迂回地说“让UIKit赶上所有这些指令,因为我知道这将让EAGLView进入一个有意义的状态,然后继续我的东西“。