繁体   English   中英

UITableView 中的图像在 swift 中滚动时不断重新加载和错误图像 flash

[英]Images in UITableView keep re-loading and wrong images flash while scrolling in swift

该应用程序有一个 UITable View,可将动态图像加载到单元格中。 滚动时下载图像,并将它们转换为 UIImage。 这些 UIImages 将在 KingFisher 的帮助下设置为 ImageView。 简单的缓存机制已经实现,但图像是 flash 滚动,直到准确的图像加载。 代码在下面提到。

表视图代码

    extension EmployeeListViewController:UITableViewDelegate,UITableViewDataSource {
    
         func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    
         let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: EmployeeTableViewCell.self), for: indexPath) as! EmployeeTableViewCell
         cell.onBindCell(management: (employeePresenter?.getManagementItem(position: indexPath.row))!)
         cell.actionCallBack = self
                    
         let empIdNumber = NSString(string: (directoryPresenter!.getManagementItem(position: indexPath.row).agmid))
                    
                      
         if let cachedImage = self.cache.object(forKey: empIdNumber) {
                cell.profileImage.kf.base.image = cachedImage
         } else {
                directoryPresenter?.getProfileImage(id: empIdNumber as String) { image in
                cell.profileImage.kf.base.image = image
                self.cache.setObject(image!, forKey: empIdNumber)
          }
        }
        return cell
       }
    }

自定义单元格内的数据绑定

我在重新使用之前将图像数据设为零

override func prepareForReuse() {
    profileImage.kf.base.image = nil
}

并在 onBind() 数据方法中设置相应的数据。

func onBindCell(management: Management) {
    name.text = management.getEmployeeDisplayName()
    
    // Place Holder
    profileImage.kf.base.image = UIImage(named: management.details.gender == "M" ? "placeholder_profile_male" : "placeholder_profile_female")
    
}

但是,当第一次向下滚动视图时,图像仍然会闪烁。 加载确切的图像后,它不会闪烁。 如何解决第一次滚动时的初始闪烁问题?

当您使用Kingfisher时,您不应管理图像的下载/缓存,因为这是该库的责任

所以更换

let empIdNumber = NSString(string: (directoryPresenter!.getManagementItem(position: indexPath.row).agmid)) 
if let cachedImage = self.cache.object(forKey: empIdNumber) {
  cell.profileImage.kf.base.image = cachedImage
} else {
  directoryPresenter?.getProfileImage(id: empIdNumber as String) { image in 
    cell.profileImage.kf.base.image = image
    self.cache.setObject(image!, forKey: empIdNumber)
  }
}

let url = URL(string: directoryPresenter!.getManagementItem(position: indexPath.row).agmid) 
cell.profileImage.kf.setImage(with: url,placeholder: UIImage(named: "placeholderImage"))

仍然使用 KingFisher 但告诉它如何解释/处理下载的数据怎么样?

让我们创建自己的ImageProcessor

struct CustomBase64Processor: ImageProcessor {

    var identifier: String = "com.larme.customBase64Processor"
    var encoding: String.Encoding = .utf8

    func process(item: ImageProcessItem, options: KingfisherParsedOptionsInfo) -> KFCrossPlatformImage? {
        print("CustomBase64Processor Processing: \(item)")
        switch item {
        case .image(let image):
            return image
        case .data(let data):
            // Strip the Base 64 data
            if let utf8String = String(data: data, encoding: encoding) {
                //Remove Data URI if needed
                let base64String = utf8String.replacingOccurrences(of: "data:image\\/.*?;base64,",
                                                                   with: "",
                                                                   options: .regularExpression)
                // Convert into a Data the Base64 Encoded String
                if let cleanedData = Data(base64Encoded: base64String.trimmingCharacters(in: .whitespacesAndNewlines)) {
                    return KFCrossPlatformImage(data: cleanedData)
                } else {
                    // Just an attempt here, but in fact it could be a gif, and that's not supported.
                    // Let's rely on KFCrossPlatformImage initilization
                    return KFCrossPlatformImage(data: Data(base64String.utf8))
                }
            } else {
                //Default image data aren't UTF8 Convertible, and are "ready to process"
                return KFCrossPlatformImage(data: data)
            }
        }
    }
}

我想知道您是否有 Data URI(因为它让我想到了相关问题),即内容是data:image/png;base64,theBase64Data ,所以如果需要,我添加了删除它。

在使用中是这样的:

imageView.kf.setImage(with: url,
                      placeholder: nil,
                      options: [.processor(CustomBase64Processor())]) { result in
    print("KingFisher callback: \(result)")
    switch result {
    case .success(let imageresult):
        print("Success: \(imageresult)")
    case .failure(let error):
        print("Error: \(error)")
    }
}

小心,既然我做了一个处理器,我们应该得到一个data来解释。 因此,如果您想使用其他处理(如调整大小等),请先处理 base 64,然后才能获得真正的工作图像。

它尚未经过全面测试,但我想这可能是一个好的开始。

我认为您应该使用库从 url 加载图像

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM