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 加载错误的图像的主要内容,如果未能解决你的问题,请参考以下文章

加载自动加载文件时出现“无法打开加载文件”错误

html页面加载JS文件经常错误

20180901 文件加载 错误处理 错误的触发

AppDomain 加载错误

错误: 找不到或无法加载主类 ArrayListMagnet?

ASP.NET运行时错误:未能加载文件或程序集或它的某一依赖项.参数错误.