【发布时间】:2017-08-28 20:26:48
【问题描述】:
我有一个这样的视图控制器:
有一个 ImageView 和一个 RangeSlider。
行为应该是这样的: 如果用户滑动范围滑块,ImageView 中的图像应该切换到图像数组中的新图像。用户还可以在不损失图片质量的情况下对图片进行缩放操作。
所以我所做的就是将图像下载到viewDidLoad上的图像数组中:
//image array
var images = [UIImage]()
我正在下载 48 张图片,大小为 1920 × 1920 px,每张图片大约 120 KB,并创建下载数据的 UIImage 对象并将它们保存到数组中,如下所示:
DispatchQueue.global().async { [weak self] in
let data = try? Data(contentsOf: url)
DispatchQueue.main.async {
if data != nil {
let img = UIImage(data: data!)
self?.images.append(img!)
} else {
...
}
}
}
要更改 imageView 中的图像,我创建了这个函数:
func updateImage(currentImage: UIImage) {
self.imageView.image = currentImage
}
当用户开始滑动rangeSlider 时,应用程序的内存使用量从 40 MB 运行到 700 MB,并在用户切换所有图像后停止增加。在那之后,用户可以在不影响内存使用的情况下来回切换整个图像。
但是当我在更新图像之前稍微调整大小时,内存问题得到了解决,但是如果用户稍微放大一点,图像现在质量很差。
调整部分大小:
extension UIImage {
func resized(_ newSize:CGSize) -> UIImage {
UIGraphicsBeginImageContextWithOptions(newSize, false, 0)
self.draw(in: CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage!
}
}
func updateImage(currentImage: UIImage) {
let currentImg = currentImage.resized(self.imageView.bounds.size)
self.imageView.image = currentImg
}
对于缩放,我使用这个:
@IBAction func scaleImage(_ sender: UIPinchGestureRecognizer) {
print(self.imageView.transform)
let tmp = self.imageView.transform.scaledBy(x: sender.scale, y: sender.scale)
if (tmp.a >= 0.99 || tmp.d >= 0.99) && (tmp.a < 2.5 || tmp.d < 2.5) {
self.imageView.transform = self.imageView.transform.scaledBy(x: sender.scale, y: sender.scale)
sender.scale = 1
if (tmp.a <= 1.2 || tmp.d <= 1.2) {
self.imageView.center = defaultImageCenter
}
}
}
那么我怎样才能以一种优雅的方式来实现它,既不提供内存泄漏,又仍然使用最佳图像质量?
【问题讨论】:
-
是否完全有必要同时下载它们?
-
是的,因为它应该具有出色的用户体验而不会出现滞后内容。
-
大多数执行此类操作的应用会提前加载几张图片,但不是一次全部加载
-
您很清楚,您看到的是内存使用,而不是内存泄漏。泄漏是指分配了内存并且永远无法回收。这不是你在这里所拥有的。除非您遇到内存压力问题,否则您可能不想做任何事情。您可以使用 NSCache 或 SDWebImage 之类的框架来管理按需加载
标签: ios swift memory-leaks uiimageview