我正在使用在主线程上执行的关注代码来截取关闭屏幕(不是self.view的子视图)视图的屏幕截图,然后显示在{{1 }}。一切都在功能方面运行良好,但是因为这个代码是在扩展上运行的,所以存在更严格的内存界限(我读过~30 MB是上限?),
UIImageView
只要按下UIGraphicsBeginImageContextWithOptions(CGSizeMake(self.screenshotView.frame.size.width, self.screenshotView.frame.size.height-2), YES, 0.0f);
CGContextRef context = UIGraphicsGetCurrentContext();
[self.screenshotView.layer renderInContext:context];
_generatedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
self.previewImageView.image = _generatedImage;
,就会使用performSelectorOnMainThread
调用此代码所在的方法。还会出现一个UIButton
来处理UI的冻结,但是如果连续按下按钮(在解除UIAlertController
之后),前几次内存使用将保持在基线附近(〜 15 MB),然后加标到~30 MB并保持在那里,直到几秒后再次调用该方法,然后当它完成渲染时,它会回落到~15 MB。
我不确定导致这种行为的原因是什么,为什么内存使用量不会一直保持在15 MB左右,而且我不确定当连续调用该方法时它会出现什么样的情况。听起来更像是有时会发生一件事吗?我怎样才能确保不会发生这种情况,只有在可以安全再次渲染而不增加内存使用时才会忽略UIAlertController
。
答案 0 :(得分:3)
内存峰值不是由renderInContext:
调用引起的,尽管所有内容都包括指向它的工具,但这是由于捕获的subviews
的{{1}}引起的。在我的情况下,这是一个错误的约束导致UIView
将其UITextView
设置为height
。
对于有这样的问题并且无法解决问题的人,请从2000
继续前进并查看您的子视图以确保它们正确无误。
答案 1 :(得分:1)
1.您能详细说明为什么要在主线程上捕获屏幕截图?使用以下命令运行async:
dispatch_async(dispatch_get_global_queue(0, 0), ^{
});
这可能会解决挂起问题&尝试在autoreleasepool
中执行这些代码行,这将有助于减少内存占用量。
2.你试过drawViewHierarchyInRect: afterScreenUpdates:
它的速度要快得多吗?可以提高效率并帮助解决你的记忆问题。
该方法呈现到上下文然后您可以调用:
CGImageRef image = CGBitmapContextCreateImage(UIGraphicsGetCurrentContext());
但它应该在autoreleasepool
内执行。如果没有,则记忆继续上升。
修改强>
3.如果你可以通过同步捕获方法来防止多个上下文创建。它可能有助于增加内存:
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
dispatch_queue_t renderQueue = dispatch_queue_create("com.throttling.queue", NULL);
- (void) captureScreen {
if (dispatch_semaphore_wait(semaphore, DISPATCH_TIME_NOW) == 0) {
dispatch_async(renderQueue, ^{
// capture
dispatch_semaphore_signal(semaphore);
});
}
}