Objective c 在UIScrollView中拍摄CATiledLayer备份视图的图像快照

Objective c 在UIScrollView中拍摄CATiledLayer备份视图的图像快照,objective-c,uiscrollview,calayer,catiledlayer,Objective C,Uiscrollview,Calayer,Catiledlayer,我有一个自定义地图视图,它由UIScrollView组成。滚动视图的子视图由CATiledLayer支持。这里一切都很好。平移和缩放将加载新的地图分幅,所有操作都会执行良好 我想做的是捕获动画的视频帧到这个滚动视图。基本上,我想创建一个对滚动视图的contentOffset和zoomScale进行动画更改的视频 我知道这个概念是合理的,因为我可以使用私有API函数UIGetScreenImage()以10fps的速度捕捉应用程序的屏幕,组合这些图像,我可以得到平滑的播放动画,并且具有滚动视图动画

我有一个自定义地图视图,它由
UIScrollView
组成。滚动视图的子视图由
CATiledLayer
支持。这里一切都很好。平移和缩放将加载新的地图分幅,所有操作都会执行良好

我想做的是捕获动画的视频帧到这个滚动视图。基本上,我想创建一个对滚动视图的
contentOffset
zoomScale
进行动画更改的视频

我知道这个概念是合理的,因为我可以使用私有API函数
UIGetScreenImage()
以10fps的速度捕捉应用程序的屏幕,组合这些图像,我可以得到平滑的播放动画,并且具有滚动视图动画使用的计时曲线

当然,我的问题是我不能使用私有API。浏览苹果列出的备选方案后,我有了一个几乎被认为是有效的选择:向
CALayer
询问
renderInContext
并从中获取
UIGraphicsGetImageFromCurrentImageContext()

不过,这似乎不适用于
CATiledLayer
支持的视图。捕捉到的是块状、未缩放的图像,就好像从来没有加载过更高分辨率的平铺一样。考虑到
CATiledLayer
为提高性能而在后台线程中绘制,并且从主线程调用
renderInContext
可能无法捕获这些更新,这有点道理。即使我也渲染平铺层的
presentationLayer
,结果也是类似的


在包含滚动视图动画的过程中,是否有苹果认可的方法来捕获
CATiledLayer
背景视图的图像?或者在任何时候,对这件事

我做了一个快速测试,并使用renderInContext:在一个包装滚动视图的视图上似乎可以工作。您试过了吗?

顺便说一句,如果您在
CATiledLayer
-backed视图中正确实现
渲染层:inContext:
,这是可行的

这段代码对我有用

- (UIImage *)snapshotImageWithView:(CCTiledImageScrollView *)view
{
// Try our best to approximate the best tile set zoom scale to use
CGFloat tileScale;
if (view.zoomScale >= 0.5) {
    tileScale = 2.0;
}
else if (view.zoomScale >= 0.25) {
    tileScale = 1.0;
}
else {
    tileScale = 0.5;
}

// Calculate the context translation based on how far zoomed in or out.
CGFloat translationX = -view.contentOffset.x;
CGFloat translationY = -view.contentOffset.y;
if (view.contentSize.width < CGRectGetWidth(view.bounds)) {
    CGFloat deltaX = (CGRectGetWidth(view.bounds) - view.contentSize.width) / 2.0;
    translationX += deltaX;
}
if (view.contentSize.height < CGRectGetHeight(view.bounds)) {
    CGFloat deltaY = (CGRectGetHeight(view.bounds) - view.contentSize.height) / 2.0;
    translationY += deltaY;
}

// Pass the tileScale to the context because that will be the scale used in drawRect by your CATiledLayer backed UIView
UIGraphicsBeginImageContextWithOptions(CGSizeMake(CGRectGetWidth(view.bounds) / view.zoomScale, CGRectGetHeight(view.bounds) / view.zoomScale), NO, tileScale);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(context, translationX / view.zoomScale, translationY / view.zoomScale);

// The zoomView is a subview of UIScrollView. The CATiledLayer backed UIView is a subview of the zoomView.
[view.zoomView.layer renderInContext:context];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

return image;
-(UIImage*)快照图像带视图:(cctileImage ScrollView*)视图
{
//尽我们最大的努力,以接近最佳的瓷砖集缩放比例使用
cgloat-tileScale;
如果(view.zoomScale>=0.5){
tileScale=2.0;
}
否则如果(view.zoomScale>=0.25){
tileScale=1.0;
}
否则{
tileScale=0.5;
}
//根据放大或缩小的距离计算上下文转换。
CGFloat translationX=-view.contentOffset.x;
CGFloat translationY=-view.contentOffset.y;
if(view.contentSize.width
}


在此处找到完整的示例代码:

是。我提供了一些示例代码,更简洁地说明了这个问题:请注意,捕获普通的
UIView
效果很好,但是
CATiledLayer
备份的视图显示为空白灰色。有人在这里发布了答案: