QLThumbnailGenerator 加载错误的图像
Posted
技术标签:
【中文标题】QLThumbnailGenerator 加载错误的图像【英文标题】:QLThumbnailGenerator loading wrong images 【发布时间】:2021-09-06 23:59:41 【问题描述】:我有一个显示图像缩略图的 NSCollectionView,我刚刚切换到使用 QLThumbnailGenerator 来获取它们。 可以查看超过 6,000 张可能的图像,如果我滚动得太快,我会开始从生成器返回错误的缩略图。 这是一个错误,还是我可以做些什么来解决这个问题? 这是在 NSCollectionViewItem 派生类中编写的代码……
var request: QLThumbnailGenerator.Request?
func loadImage()
if imageView?.image != NSImage(imageLiteralResourceName: "Placeholder")
return
request = QLThumbnailGenerator.Request(fileAt: url!, size: imageSize, scale: 1.0, representationTypes: [.lowQualityThumbnail])
QLThumbnailGenerator.shared.generateBestRepresentation(for: request!)
(thumbnail: QLThumbnailRepresentation?, error: Error?) -> Void in
if let request = self.request
QLThumbnailGenerator.shared.cancel(request)
DispatchQueue.main.async
[unowned self] in
if self.imageView?.image != NSImage(imageLiteralResourceName: "Placeholder")
return
let transition = CATransition()
transition.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
transition.duration = 0.3
imageView?.layer?.add(transition, forKey: nil)
imageView?.image = thumbnail?.nsImage
…
【问题讨论】:
我的猜测:当它们被滚动到视图之外时,它们会被重复使用。到完成处理程序被调用时,该项目不再是 url 的项目。 【参考方案1】:嗯,我发现了问题
首先,作为对 Willeke 的回应,我说我在 prepareForReuse 方法中取消了请求。
原来我使用了错误的 QLThumbnailGenerator。
override func prepareForReuse()
super.prepareForReuse()
if let request = self.request
thumbnailGenerator.cancel(request)
self.request = nil
imageView?.image = NSImage(imageLiteralResourceName: "Placeholder")
问题是如此微妙。我在原始帖子中没有引用的一件事是,我有一个包含私有 QLThumbnailGenerator 实例的 var,即使我在 loadImage 方法中使用共享实例,我也使用它来取消请求。
我将 loadImage 方法切换为使用私有 var 后,一切都开始变得更好。
我说得更好,因为仍然存在生成器由于某种不明原因返回 nil 图像的情况。
因此,对于那些时候,我有一个帮助方法可以以“老式”方式加载这些缩略图......
static func previewOfFile(at url: URL, size: NSSize, asIcon: Bool = false, completion: @escaping (NSImage) -> ())
let cfUrl = url as CFURL
guard let imageSource = CGImageSourceCreateWithURL(cfUrl, nil),
let image = getImage(for: imageSource, at: url, size: size) else
completion(NSWorkspace.shared.icon(forFile: url.path))
return
completion(image)
…现在完整的代码是…
let thumbnailGenerator = QLThumbnailGenerator()
var request: QLThumbnailGenerator.Request?
func loadImage()
imageView?.image = NSImage(imageLiteralResourceName: "Placeholder")
request = QLThumbnailGenerator.Request(fileAt: self.url!, size: self.imageSize, scale: 1.0, representationTypes: [.lowQualityThumbnail])
self.thumbnailGenerator.generateRepresentations(for: self.request!)
(thumbnail: QLThumbnailRepresentation?, type: QLThumbnailRepresentation.RepresentationType, error: Error?) -> Void in
DispatchQueue.main.async
let transition = CATransition()
transition.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
transition.duration = 0.5
self.imageView?.layer?.add(transition, forKey: nil)
self.imageView?.image = thumbnail?.nsImage
if thumbnail?.nsImage == nil
DispatchQueue.main.async
ThumbnailImage.previewOfFile(at: self.url!, size: self.imageSize)
[unowned self] retrievedImage in
transition.duration = 0.3
self.imageView?.image = retrievedImage
我希望这对偶然发现此问题的其他人有用
【讨论】:
以上是关于QLThumbnailGenerator 加载错误的图像的主要内容,如果未能解决你的问题,请参考以下文章