Home > Net >  Images in UITableView keep re-loading and wrong images flash while scrolling in swift
Images in UITableView keep re-loading and wrong images flash while scrolling in swift

Time:02-16

The application has a UITable View which loads dynamic images into cells. Images are downloaded while scrolling and they are converted into UIImages. Those UIImages will be set to the ImageView with help of KingFisher. Simple Cache mechanism has been already implemented but images are flash on scroll until the exact image loads. Code is mentioned below.

Table View Code

    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
       }
    }

Data Binding inside the Custom cell

I made the image data nil before reuse

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

And set respective data inside onBind() data method.

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")
    
}

But Still, images blink when scrolling down the view for the first time. After the exact image is loaded it won't blick. How to sort the initial blinking issue on first scroll?

CodePudding user response:

What about still using KingFisher but telling it how to interpret/process the downloaded data?

Let's create our own 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)
            }
        }
    }
}

I was wondering if you had Data URI (since it made me think of related question), ie the content is data:image/png;base64,theBase64Data, so I added a removal of it if needed.

In use, it's like that:

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)")
    }
}

Be careful, since I made a processor, we should get a data to interpret. So if you want to use other processing (like resizing, etc.) process the base 64 before to have a real working image first.

It's not fully tested, but I guess it could be a good start.

CodePudding user response:

I think you should use a library to load images from url

  • Related