[英]“[CALayer renderInContext]” crashes on iPhone X
我有一個自定義UIView
,我想呈現為UIImage
。 自定義UIView
是UIImageView
的子類。
在此視圖內,我正在渲染一些UI元素(在圖像上繪制一堆圓圈)。 添加的圈子數量可以達到數千個。
我正在使用這個簡單的代碼片段將視圖呈現為UIImage
:
// Create the UIImage (code runs on the main thread inside an @autorelease pool)
UIGraphicsBeginImageContextWithOptions(viewToSave.image.size, viewToSave.opaque, 1.0);
[viewToSave.layer renderInContext:UIGraphicsGetCurrentContext()];
imageToSave = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// Since I'm rendering some stuff inside the .layer of the UIView,
// I don't think I can use "drawViewHierarchyInRect: afterScreenUpdates:"
這是從Instruments中獲取的內存分配,在示例中,添加了約3000個圓圈作為子視圖:
現在,這里是奇怪的部分...運行良好,我可以多次(連續)渲染圖像並將其保存在iPhone 5,iPhone 5s,iPhone 6s,iPad Air 2,iPad Mini 4等設備的圖像庫中。 。但是相同的代碼會觸發iPhone X上的內存警告,並最終導致應用程序崩潰...
不幸的是,我沒有iPhone X的訪問權限,而報告此舉的人也沒有Mac的訪問權限,因此我無法進行更深入的研究。
我真的不知道我做錯什么了嗎...您知道iPhone X是否有所不同嗎? 我已經為這個問題苦苦掙扎了一段時間了...
我想這個問題與CALayer:renderInContext:
如何在需要按比例放大的上下文中處理成千上萬個視圖的繪制有關。 可以嘗試自己渲染子視圖嗎? 然后通過使用儀器比較並驗證它是否更好。
UIImage *imageToSave = [self imageFromSubLayer:viewToSave];
- (UIImage *)imageFromSubLayers:(UIImageView *)imageView {
CGSize size = imageView.image.size;
UIGraphicsBeginImageContextWithOptions(size, YES, .0);
CGContextRef context = UIGraphicsGetCurrentContext();
for (CALayer *layer in imageView.layer.sublayers)
[layer renderInContext:context];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
我最近在我制作的應用程序中編寫了一種方法,用於將UIView轉換為UIImages(這樣我就可以在進度視圖/選項卡欄上顯示漸變)。 我最終解決了以下代碼,我使用此代碼來渲染選項卡按鈕,它適用於包括X在內的所有設備。
目標C:
UIGraphicsImageRenderer *renderer = [[UIGraphicsImageRenderer alloc] initWithSize:gradientView.bounds.size];
UIImage *gradientImage = [renderer imageWithActions:^(UIGraphicsImageRendererContext * _Nonnull rendererContext) {
[gradientView drawViewHierarchyInRect:gradientView.bounds afterScreenUpdates:true];
}];
斯威夫特4:
let renderer = UIGraphicsImageRenderer(size: gradientView.bounds.size)
let image = renderer.image { ctx in
gradientView.drawHierarchy(in: gradientView.bounds, afterScreenUpdates: true)
}
我在編寫的示例項目中使用了此代碼,這是項目文件的鏈接:
如您所見,這兩個項目都將在iPhone X上完美運行!
我知道,以下聽起來很奇怪。 但是,請嘗試使目標圖像比要繪制的像素大一像素。 這為我解決了(我的特殊問題: “ [CALayer renderInContext]”在iPhone X上崩潰 )。
在代碼中:
UIGraphicsBeginImageContextWithOptions(
CGSizeMake(viewToSave.image.size.width + 1,
viewToSave.image.size.height + 1),
viewToSave.opaque,
1.0
);
總而言之,答案在於最小的問題(不包括在問題中)...
我真的沒有考慮過(不久后才發現), iPhone X的縮放系數等於@ 3x 。 這就是iPhone X和其他所有正在運行該代碼的設備之間的區別...
在代碼的某個時刻,我將子視圖的.contentScaleFactor
設置為等於[UIScreen mainScreen].scale
。 這意味着在高端設備上,圖像質量應該更好。
對於iPhone X, [UIScreen mainScreen].scale
返回3。對於我測試過的所有其他設備, [UIScreen mainScreen].scale
返回2。這意味着在iPhone X上,用於渲染屏幕的內存量[UIScreen mainScreen].scale
。圖像要高得多。
有趣的事實二:從另一篇有用的SO文章中 ,我發現在iPhone X上,如果您嘗試分配的內存總量(1392 MB)超過50%,則會崩潰。 另一方面,例如,在iPhone 6s的情況下,百分比更高:68%(1396 MB)。 這意味着與iPhone X相比,對於某些較舊的設備,您擁有更多的工作記憶。
對不起,我誤導了我,這是一個誠實的錯誤。 謝謝大家的答案!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.