Naresh
Naresh

Reputation: 129

loading images from coredata , tableview is not scrolling smooth

I have six custom cells. 3 cells contain imageView and some labels and others just contains labels. In viewDidLoad, I loaded all data from coredata and refreshing the tableview the problem is when table has cells (without imageview cell) it scrolls smoothly but when we add cell(which has imageview) it scrolls smoothly in down scrolling but it structs when I am up scrolling the tableview.I tried to reduce image quality but didn't work. how to solve this

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
{
    let insuranceCell = tableView.dequeueReusableCell(withIdentifier: "insuranceCell") as! InsuranceCell
    let pollutionCell = tableView.dequeueReusableCell(withIdentifier: "pollutionCell") as! PollutionCell
    let servicingCell = tableView.dequeueReusableCell(withIdentifier: "servicingCell") as! ServicingCell
    let challanPaidCell = tableView.dequeueReusableCell(withIdentifier: "challanPaidCell") as! ChallanPaidCell
    let insuranceClaimCell = tableView.dequeueReusableCell(withIdentifier: "insuranceClaimCell") as! InsuranceClaimCell
    let fuelRefillCell = tableView.dequeueReusableCell(withIdentifier: "fuelRefillCell") as! FuelRefillCell

    let cellArr = sections[indexPath.section].cell
    //Loading cell based on array details
    switch cellArr[0] {
    case is InsuranceDetails:
        insuranceCell.setup(object: cellArr[indexPath.row])
        return insuranceCell
    case is Pollution:
        pollutionCell.setup(object: cellArr[indexPath.row])
        return pollutionCell
    case is Servicing:
        servicingCell.setup(object: cellArr[indexPath.row])
        return servicingCell
    case is ChallanPaid:
        challanPaidCell.setup(object: cellArr[indexPath.row])
        return challanPaidCell
    case is InsuranceClaims:
        insuranceClaimCell.setup(object: cellArr[indexPath.row])
        return insuranceClaimCell
    case is FuelRefills:
        fuelRefillCell.setup(object: cellArr[indexPath.row])
        return fuelRefillCell
    default:
        return insuranceCell
    }

}


class InsuranceCell: UITableViewCell {

    func setup(object : NSManagedObject){
    guard let arr = object as? InsuranceDetails else {return}
    lbAmountPaid.text = arr.amountPaid
    lbAgency.text = arr.agency
    lbVehiclevalidfrom.text = arr.vehicleValidFrom
    lbVehiclevalidupto.text = arr.vehicleValidUpto
    let imageData = arr.insurancePhoto ?? Data()
    let image = UIImage(data: imageData)
    let compimapge = image?.resized(withPercentage: 0.1)
    insurancePhoto.image = compimapge

}

Upvotes: 0

Views: 300

Answers (1)

Chris
Chris

Reputation: 3817

As Fabio says, don't unnecessarily dequeue all the cells all of the time.

However, the image creation and scaling is most likely where the stuttering is coming from. The naming of the parameter in your call to UIImage.resized(withPercentage: 0.1) suggests that your source images are truly massive (you are displaying them at 1/1000th of their original size!?). If the parameter name is misleading and 0.1 really means 1/10th, I suggest renaming the parameter (UIImage.resized(withFraction: 0.1) perhaps).

Having said all that, look to move the image scaling off the main thread. Something like this (un-tested):

class InsuranceCell: UITableViewCell {

    func setup(object: NSManagedObject, in table: UITableview, at indexPath: IndexPath) {
        guard let arr = object as? InsuranceDetails else {return}

        lbAmountPaid.text = arr.amountPaid
        lbAgency.text = arr.agency
        lbVehiclevalidfrom.text = arr.vehicleValidFrom
        lbVehiclevalidupto.text = arr.vehicleValidUpto

        // Do time consuming stuff in the background
        DispatchQueue.global(qos: .userInitiated).async { 
            let imageData = arr.insurancePhoto ?? Data()
            let image = UIImage(data: imageData)

            // This will be where all the time is going. 0.1% suggests your source
            // image is massively oversized for this usage.
            let compimage = image?.resized(withPercentage: 0.1)

            // Always back to the main thread/queue for UI updates
            DispatchQueue.main.async {
                guard let cell = table.cellForRow(at: indexPath) as? InsuranceCell else {
                    // The cell we wanted to configure is no longer in view
                    return
                }

                // Don't be tempted to write straight to `self.insurancePhoto.image`,
                // it may already have been reused for a different row
                // if the user is scrolling quickly
                cell.insurancePhoto.image = compimage
            }

        }
    }
}

It requires the additional parameters in order to check that updating the cell is still appropriate once the scaling has completed.

Upvotes: 1

Related Questions