ios - 为什么在某些情况下视图的快照看起来可能会大两倍?
问题描述
问题
当使用各种UIView
扩展来拍摄 a 的快照时UIView
,结果可能看起来比应有的更大(有点放大)。
有关问题的详细信息
我拍摄了 2 的快照UIViews
,我们可以在下面调用 viewA 和 viewB。
viewA:创建快照时将视图添加到视图层次结构中。
viewB:已完全定义,但在创建快照时尚未添加到视图层次结构中。然后将快照裁剪 x 次,并将结果添加到一些
UIView
中以供显示。
我已经测试了 3 种不同的代码以获得我正在寻找的结果:一个提供了所需的快照图像,但渲染质量低;另外两个为viewA但为viewB提供了更好质量的图像渲染和正确的结果,尽管快照似乎具有正确的矩形(我检查了矩形),但显示的图像显得太大(好像它们被放大了两次)。
代码
扩展#1:提供正确的结果,但图像质量低
extension UIView { func takeSnapshot() -> UIImage? { UIGraphicsBeginImageContext(self.frame.size) self.layer.render(in: UIGraphicsGetCurrentContext()!) let snapshot = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return snapshot } }
扩展#2:提供正确的图像质量,但 viewB 的裁剪图像显示两倍大
extension UIView { func snapshot(of rect: CGRect? = nil, afterScreenUpdates: Bool = true) -> UIImage { return UIGraphicsImageRenderer(bounds: rect ?? bounds).image { _ in drawHierarchy(in: bounds, afterScreenUpdates: true) } } }
扩展#3:同样,提供正确的图像质量,但 viewB 的裁剪图像显示两倍大
extension UIView { func takeScreenshot() -> UIImage { UIGraphicsBeginImageContextWithOptions(self.bounds.size, false, UIScreen.main.scale) drawHierarchy(in: self.bounds, afterScreenUpdates: true) let image = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() if (image != nil) { return image! } return UIImage() } }
最后但并非最不重要的一点是,从快照中提取裁剪图像的(简化)代码
for i in (0...numberOfCroppedImages) {
let rect = CGRect(x: CGFloat(i) * snapshot!.size.width / CGFloat(numberOfCroppedImages), y: 0, width: snapshot!.size.width / CGFloat(numberOfCroppedImages), height:snapshot!.size.height)
// defines the container view for the fragmented snapshots
let view = UIView()
view.frame = rect
// defines the layer with the fragment of the snapshot
let layer = CALayer()
layer.frame.size = rect.size
let img = snapshot?.cgImage?.cropping(to: rect)
layer.contents = img
view.layer.addSublayer(layer)
}
到目前为止尝试的操作
我已经仔细检查了所有内容CGRect
,但没有发现任何问题:视图矩形和快照大小似乎是预期的,但是,我一直有太大的渲染图像,扩展名为 #2 和 #3 viewB(viewA 被正确渲染),而扩展#1 提供了正确尺寸的图像,但质量太低而无法充分使用。
这可能是一个问题drawInHierarchy(in: afterScreenUpdates:)
吗?或者使用 ? 转换为 cgImage
let img = snapshot?.cgImage?.cropping(to: rect)
?
我会非常感谢任何指点!
解决方案
我发布了一个我发现对我有用的解决方案:
首先,无论视图是否添加到层次结构、裁剪与否,都呈现(就我而言)预期结果(质量和大小方面)的快照扩展:
extension UIView {
func takeSnapshot(of rect: CGRect? = nil, afterScreenUpdates: Bool = true) -> UIImage {
return UIGraphicsImageRenderer(bounds: rect ?? bounds).image { (context) in
self.layer.render(in: context.cgContext)
}
}
}
然后是在视图中拍摄矩形快照的代码的更新版本:
let view = UIView()
view.frame = rect
let img = self.takeSnapshot(of: rect, afterScreenUpdates: true).cgImage
view.layer.contents = img
这里的区别在于对视图中的矩形进行快照,而不是裁剪整个视图的快照。
我希望这有帮助。
推荐阅读
- linux - 避免将脚本参数评估为文件 [BASH, LINUX]
- git - 停止 Sqlite3 合并冲突并始终使用生产版本?
- amazon-web-services - 如果通过变量,AWS Lex 不会识别响应
- python - 琐碎的 tkinter 按钮适用于 Python 3.5,最初在 Python 3.6、3.7 上无响应
- html - Lxml - 如何将所有出现的特定文本包装在标签中
- php - 如何使用不同的对象制作 Symfony 抽象类型?
- c# - 针对 DataTable 运行 SQL 查询
- c# - 模拟 CloudBlockBlob 并让它返回一个流
- angular - 如果表格有来自 api 的数据,如何显示表格,否则显示其他 div
- ios - 为什么我的 WKWebviews 在模拟器上工作,但无法在 iPad 上提取文件?