iosswiftuitableview

How to prevent UITableview cells from repeating the view inside it?


I have a table view which shows an array of signature views with guest details. When the cells are scrolled the signature from cell 1 is repeated in cell 6 and 2 in cell 7 and so on. (table view reusing of cells problem)

I tried using the cells Prepare to reuse function and cleared the cells signature view by making it nil and than when the new/reused cell is assigned create and assign a new signature view. In my other approach I tried to clear the array of the signature views which holds the signature paths in reuse function. and when the cell is created that time based on the index path the cell.signature view is appended inside an array and stored.

so when the user scrolls by default the signature path is made empty (new cells) but when the user reaches to a index path which he previously reached and since inside our array we have appended that signature view we fetch and assign the path to the current signature view but still the signs are repeating.

I can provide code of what I tried.


func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    
    let cellReusableId = String(describing: ProfileSignataureTableViewCell.self)
    
    guard let cell = tableView.dequeueReusableCell(withIdentifier: cellReusableId, for: indexPath) as? ProfileSignataureTableViewCell
    else { fatalError("Cell not exists in storyboard") }
    
    cell.firstNameText.delegate = self
    cell.lastNameText.delegate = self
    cell.ageText.delegate = self
    cell.firstNameText.tag = indexPath.row
    cell.lastNameText.tag = indexPath.row
    cell.ageText.tag = indexPath.row
    //   cell.signatureView.tag = indexPath.row
    
     cell.signatureView?.delegate = self
    cell.signatureView?.tag = indexPath.row
    
    
    if let existingSignature = signArray.first(where: { $0.indexPath == indexPath.row })?.signatureViews {
        // Reuse the existing signature view if found
        cell.signatureView = existingSignature
        print("Reusing existing signature view for row \(indexPath.row)")
        
        // use the existing signature views array to draw the signature back again not png data
        if let signatureData = existingSignature.pathArray as? [Any] {
            
            cell.signatureView?.pathArray = signatureData as! NSMutableArray
        }
        
    } else {
        
        
        if let signatureView = cell.signatureView {
            // Save the new signature view in the array
            signArray.append(Signatures(indexPath: indexPath.row, signatureViews: signatureView))
            print("Stored new signature view for row \(indexPath.row)")
            
            
        } else {
            print("No signature view available for row \(indexPath.row)")
        }
    }
        
    cell.btn_clear.tag = indexPath.row
    cell.btn_clear.addTarget(self, action: #selector(editButtonPressed), for: .touchUpInside)
   
    
    print("the new array count is \(signArray.count)")
    
    return cell
    
}


struct Signatures {
    
    var indexPath: Int?
    var signatureViews: SamsoSignatureView?
    
}


Solution

  • When cellForRowAt is called, you are preparing a cell (new or reused, on the dequeue call).

    If it's reused, it will contain the signature view from the previous use.

    On your IF clause, when a signature exists for that index path, you are assigning the view to the cell. But if it doesn't exist, in the ELSE clause, you need to assign the new signature. You are not doing that so it displays the previous signature. That should fix your main issue.

    But I agree with the comments, storing an array of views and assigning them to cells is not a good idea. Your array should have just the data, and on that method you should fill the view with the data. The idea of the cell reuse logic is that only a few cell views should be in memory, and the rest should be loaded later when the user scrolls to them.