运行应用程序时,我遇到了图像使用过多内存的问题。 905kb 的 SVG 图像在呈现时大约需要 150mb,并且系统正在缓存该图像。在不同页面上加载多个不同的 SVG 图像会导致内存压力问题。
所以我开始研究图像下采样并找到了解决方案。我设法创建一个函数来根据图像的大小对图像进行下采样(有帮助)。目前,我可以使用下采样器类对图像进行下采样,该类需要为我想要启用的每个 imageView 设置为自定义类下采样。
但是我正在尝试为 UIImageView 创建一个 IBDesignable 扩展,以便我可以使用任何自定义类,但仍然可以获得对图像进行下采样的好处。
这是下采样类的代码
import UIKit
class DownsamplingImageView: UIImageView {
@IBInspectable
var downSample: Bool = true {
didSet {
setNeedsLayout()
}
}
override func layoutSubviews() {
super.layoutSubviews()
if downSample, let image = self.image {
let targetSize = self.bounds.size
let downsampledImage = image.downsample(to: targetSize)
self.image = downsampledImage
}
}
}
extension UIImage {
func downsample(to targetSize: CGSize) -> UIImage? {
let sourceSize = self.size
let widthRatio = targetSize.width / sourceSize.width
let heightRatio = targetSize.height / sourceSize.height
let scaleFactor = max(widthRatio, heightRatio)
let scaledSize = CGSize(width: sourceSize.width * scaleFactor, height: sourceSize.height * scaleFactor)
UIGraphicsBeginImageContextWithOptions(scaledSize, false, 0.0)
self.draw(in: CGRect(origin: CGPoint.zero, size: scaledSize))
let downsampledImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return downsampledImage
}
}
这就是我尝试进行扩展的方法,但不幸的是它不起作用。
import UIKit
@IBDesignable
extension UIImageView {
@IBInspectable
var downSample: Bool {
get {
return image != nil
}
set {
setNeedsLayout()
}
}
override open func layoutSubviews() {
super.layoutSubviews()
if downSample, let image = self.image {
let targetSize = self.bounds.size
let downsampledImage = image.downsample(to: targetSize)
self.image = downsampledImage
}
}
}
extension UIImage {
func downsample(to targetSize: CGSize) -> UIImage? {
let sourceSize = self.size
let widthRatio = targetSize.width / sourceSize.width
let heightRatio = targetSize.height / sourceSize.height
let scaleFactor = max(widthRatio, heightRatio)
let scaledSize = CGSize(width: sourceSize.width * scaleFactor, height: sourceSize.height * scaleFactor)
UIGraphicsBeginImageContextWithOptions(scaledSize, false, 0.0)
self.draw(in: CGRect(origin: CGPoint.zero, size: scaledSize))
let downsampledImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return downsampledImage
}
}
有人可以帮忙或解释一下为什么 UIImageView 上的扩展不起作用但使用自定义类可以吗?还有什么办法可以让扩展工作吗?
PS:150mb 使用量减少到仅 6mb 使用量,幸运的是,当用户离开页面时它就被释放了! 万一有人想要启用下采样,第一个代码可以完美运行,您所要做的就是将 UIImageView 自定义类设置为
DownsamplingImageView
我最终使用图像下采样器来解决这个问题。
import UIKit
class DownsamplingImageView: UIImageView {
@IBInspectable
var downSample: Bool = true {
didSet {
setNeedsLayout()
}
}
override func layoutSubviews() {
super.layoutSubviews()
if downSample, let image = self.image {
let targetSize = self.bounds.size
let downsampledImage = image.downsample(to: targetSize)
self.image = downsampledImage
}
}
}
extension UIImage {
func downsample(to targetSize: CGSize) -> UIImage? {
let sourceSize = self.size
let widthRatio = targetSize.width / sourceSize.width
let heightRatio = targetSize.height / sourceSize.height
let scaleFactor = max(widthRatio, heightRatio)
let scaledSize = CGSize(width: sourceSize.width * scaleFactor, height: sourceSize.height * scaleFactor)
UIGraphicsBeginImageContextWithOptions(scaledSize, false, 0.0)
self.draw(in: CGRect(origin: CGPoint.zero, size: scaledSize))
let downsampledImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return downsampledImage
}
}
致谢:我忘了我是从哪里得到这个的。我只是回答这个问题,以防有人遇到同样的问题。归功于原主人。