skip to Main Content

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?

2

Answers


  1. 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.

    Login or Signup to reply.
  2. I think you should use a library to load images from url

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search