ios – UITableView is duplicating/repeating number of rows in section

[ad_1]

I am currently developing a Fitness Application and working on Workout View. It has a functionality similar to to-do checklist. So basically the user is marking Sets of a certain exercise that he finished. I know that it is needed to prepare TableViewCells for reuse, and I did that for the state when all the sets of exercise is done and user shouldn’t be able to interact whit that TableViewCell anymore. The only thing that keeps getting duplicated is numberOfRowsInSection. Guys please help me find the missing part, I have been trying for two days at this point:(

TableView is inside the collectionViewCell so I am initializing it from there. I am using custom delegate as I have to have an access to tableView from the view that holds collectionView.

protocol TableViewCellDelegate: AnyObject {
func tableView(tableViewCell: WorkoutStartedTVCurrentExerciseCell, index: Int, didTappedInTableViewCell: WorkoutStartedCell)
// other delegate methods that you can define to perform action in viewcontroller
}

class WorkoutStartedCell: UICollectionViewCell {

    weak var cellDelegateTV: TableViewCellDelegate?
    
    let scrollView: UIScrollView = {
       
        let view = UIScrollView()
        view.backgroundColor = UIColor.clear
        view.isScrollEnabled = true
        view.contentMode = .center
        view.showsHorizontalScrollIndicator = false
        view.isMultipleTouchEnabled = true
        view.isUserInteractionEnabled = true
        
        return view
    }()
    
    let titleLabel: UILabel = {
                          
        let label = UILabel()
        label.backgroundColor = UIColor.clear
        label.textColor = UIColor.black
        label.textAlignment = .center
        label.text = "Incline Bench Press"
        label.font = UIFont.systemFont(ofSize: 23.0, weight: .semibold)
                           
        return label
                           
    }()
    
    let numberOfExercisesLabel: UILabel = {
        
        let label = UILabel()
        label.backgroundColor = UIColor.clear
        label.textColor = UIColor.black.withAlphaComponent(0.7)
        label.textAlignment = .center
        label.font = UIFont.systemFont(ofSize: 16.5, weight: .medium)
                           
        return label
        
    }()
    
    let container: UIView = {
        
        let view = UIView()
        view.layer.cornerRadius = 10
        view.backgroundColor = UIColor.black
        view.layer.shadowOffset = CGSize(width: 0, height: 0)
        view.clipsToBounds = false
        view.layer.shadowOpacity = 0.35
        view.layer.shadowRadius = 10
        view.layer.shadowColor = UIColor.black.cgColor
        
        return view 
    }()
    
    let tableView: UITableView = {
       
        let tableView = UITableView()
        tableView.backgroundColor = UIColor.clear
        tableView.separatorStyle = .none
        tableView.register(WorkoutStartedTVCurrentExerciseCell.self, forCellReuseIdentifier: "currentExerciseCellID")
        tableView.layer.cornerRadius = 0
        tableView.scrollIndicatorInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
        tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
        tableView.showsHorizontalScrollIndicator = false
        tableView.showsVerticalScrollIndicator = true
        tableView.isScrollEnabled = true
    
        return tableView
    }()
    
    var number_of_sets : Int!
    var number_of_reps : Int!
    var completed_sets = [Int]()
    var remaining_sets = [Int]()
    //var current_set: IndexPath!
    //var completedSets: [Int]!
    
    override init(frame: CGRect) {
        super.init(frame: frame)
    
        backgroundColor = UIColor.white
        contentView.isUserInteractionEnabled = true
        isMultipleTouchEnabled = true
    
        //tableView.estimatedRowHeight = 0
        //tableView.estimatedSectionHeaderHeight = 0
        //tableView.estimatedSectionFooterHeight = 0
        //tableView.delegate = self
        //tableView.dataSource = self
        tableView.isScrollEnabled = false
        
        contentView.addSubview(scrollView)
        scrollView.addSubview(titleLabel)
        scrollView.addSubview(numberOfExercisesLabel)
        scrollView.addSubview(container)
        scrollView.addSubview(tableView)
        
        scrollView.translatesAutoresizingMaskIntoConstraints = false
        
        scrollView.topAnchor.constraint(equalTo: topAnchor).isActive = true
        scrollView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
        scrollView.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
        scrollView.heightAnchor.constraint(equalTo: heightAnchor).isActive = true
        scrollView.heightAnchor.constraint(equalTo: heightAnchor).priority = UILayoutPriority.defaultLow
        //scrollView.delegate = self
        
        titleLabel.translatesAutoresizingMaskIntoConstraints = false
        
        titleLabel.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 25).isActive = true
        titleLabel.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
        titleLabel.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
        titleLabel.sizeToFit()
        
        numberOfExercisesLabel.translatesAutoresizingMaskIntoConstraints = false
    
        numberOfExercisesLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 10).isActive = true
        numberOfExercisesLabel.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
        numberOfExercisesLabel.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
        numberOfExercisesLabel.sizeToFit()
        
        container.translatesAutoresizingMaskIntoConstraints = false
        
        container.topAnchor.constraint(equalTo: numberOfExercisesLabel.bottomAnchor, constant: 15).isActive = true
        container.centerXAnchor.constraint(equalTo: centerXAnchor, constant: 0).isActive = true
        container.widthAnchor.constraint(equalToConstant: self.frame.width - 0).isActive = true
        container.heightAnchor.constraint(equalToConstant: self.frame.width - 0).isActive = true
        
        tableView.translatesAutoresizingMaskIntoConstraints = false
    
        tableView.topAnchor.constraint(equalTo: container.bottomAnchor, constant: 20).isActive = true
        tableView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
        tableView.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
    
    }
    
    override func prepareForReuse() {
        super.prepareForReuse()
        
        number_of_sets = nil
        number_of_reps = nil
        remaining_sets.removeAll()
        completed_sets.removeAll()
        tableView.delegate = nil
        tableView.dataSource = nil
        
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

}

extension WorkoutStartedCell: UITableViewDelegate, UITableViewDataSource {

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        
            return remaining_sets.count + completed_sets.count
    }
        
    func numberOfSections(in tableView: UITableView) -> Int {
        
        return 1
        
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
                
        let cell = tableView.dequeueReusableCell(withIdentifier: "currentExerciseCellID", for: indexPath) as! WorkoutStartedTVCurrentExerciseCell
        
        cell.selectionStyle = .none
        cell.Set.text = "\(Array(1...number_of_sets)[indexPath.row])"
        cell.Reps.text = "\(number_of_reps ?? 1)"
            
        if completed_sets.count == number_of_sets {
            cell.isUserInteractionEnabled = false
        } else {
            cell.isUserInteractionEnabled = true
        }
                
        if completed_sets.contains(where: {$0 == indexPath.row}) == false, indexPath.row == remaining_sets.first {
            
            //Current Set
            cell.Set.textColor = #colorLiteral(red: 0, green: 0.9810667634, blue: 0.5736914277, alpha: 1).withAlphaComponent(0.75)
            cell.SetStatic.textColor = UIColor.black.withAlphaComponent(0.7)
            cell.Weight.textColor = #colorLiteral(red: 0, green: 0.9810667634, blue: 0.5736914277, alpha: 1).withAlphaComponent(0.75)
            cell.WeightStatic.textColor = UIColor.black.withAlphaComponent(0.7)
            cell.Reps.textColor = #colorLiteral(red: 0, green: 0.9810667634, blue: 0.5736914277, alpha: 1).withAlphaComponent(0.75)
            cell.RepsStatic.textColor = UIColor.black.withAlphaComponent(0.7)
            cell.CompletedImage.tintColor = UIColor.white
            cell.CompletedImage.backgroundColor = UIColor.white
            cell.CompletedImage.layer.borderColor = UIColor.darkGray.withAlphaComponent(0.9).cgColor
            
        } else if completed_sets.contains(indexPath.row) == true, remaining_sets.contains(indexPath.row) == false {
            
            //Completed Set
            cell.Set.textColor = UIColor.black.withAlphaComponent(0.7)
            cell.SetStatic.textColor = UIColor.black.withAlphaComponent(0.7)
            cell.Weight.textColor = UIColor.black.withAlphaComponent(0.7)
            cell.WeightStatic.textColor = UIColor.black.withAlphaComponent(0.7)
            cell.Reps.textColor = UIColor.black.withAlphaComponent(0.7)
            cell.RepsStatic.textColor = UIColor.black.withAlphaComponent(0.7)
            cell.CompletedImage.tintColor = UIColor.white
            cell.CompletedImage.backgroundColor = UIColor.darkGray.withAlphaComponent(0.9)
            cell.CompletedImage.layer.borderColor = UIColor.darkGray.withAlphaComponent(0.9).cgColor
                            
        } else if completed_sets.contains(indexPath.row) == false, remaining_sets.contains(indexPath.row) == true, indexPath.row != remaining_sets.first {
            
            //Remaining Sets
            cell.Set.textColor = UIColor.black.withAlphaComponent(1.0)
            cell.SetStatic.textColor = UIColor.black.withAlphaComponent(0.7)
            cell.Weight.textColor = UIColor.black.withAlphaComponent(1.0)
            cell.WeightStatic.textColor = UIColor.black.withAlphaComponent(0.7)
            cell.Reps.textColor = UIColor.black.withAlphaComponent(1.0)
            cell.RepsStatic.textColor = UIColor.black.withAlphaComponent(0.7)
            cell.CompletedImage.tintColor = UIColor.white
            cell.CompletedImage.backgroundColor = UIColor.white
            cell.CompletedImage.layer.borderColor = UIColor.darkGray.withAlphaComponent(0.9).cgColor
    
                            
        }
        
        return cell
    }
    
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        
        return 75
        
    }
    
    func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
        return false
    }
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        
        let cell = tableView.cellForRow(at: indexPath) as? WorkoutStartedTVCurrentExerciseCell
        self.cellDelegateTV?.tableView(tableViewCell: cell!, index: indexPath.row, didTappedInTableViewCell: self)
        
    }

}

Here is how I pass the data from ViewController and setting CollectionView delegate and data source.

`

extension workoutStartedView: UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
                
        return exercise_names.count
    
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        
        let exercisesCount = Array(1...exercise_names.count)
    
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellID, for: indexPath) as! WorkoutStartedCell
        
        cell.number_of_reps = Int(number_of_reps[indexPath.item])!
        cell.number_of_sets = Int(number_of_sets[indexPath.item])!
        cell.remaining_sets = remainingSets[indexPath.item]
        cell.completed_sets = completedSets[indexPath.item]
        cell.titleLabel.text = exercise_names[indexPath.item]
        cell.numberOfExercisesLabel.text = "Exercise \(exercisesCount[indexPath.item]) of \(exercise_names.count)"
        cell.cellDelegateTV = self
        cell.tableView.heightAnchor.constraint(equalToConstant: 75 * CGFloat(Int(self.number_of_sets[indexPath.item])!)).isActive = true
        cell.scrollView.contentSize = CGSize(width: collectionView.frame.width, height: 100 + (collectionView.frame.width) + (75 * CGFloat(Int(self.number_of_sets[indexPath.item])!)))
        cell.scrollView.scrollToTop(animated: false)
        cell.tableView.delegate = cell.self
        cell.tableView.dataSource = cell.self
        cell.tableView.reloadData()
        //cell.layoutIfNeeded()
        
        cell.tag = Array(0...exercise_names.count - 1)[indexPath.row]
        
        return cell
        
    }
    
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        
        collectionView.scrollToItem(at: indexPath, at: .left, animated: true)
        
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
    
            return sectionInsets
        }
    
        func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
            
            return CGSize(width: collectionView.bounds.width - 40, height: collectionView.bounds.height)
        }
    
       
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
          
        return 10
    }

}

`

Here I am handling data from collectionViewCell throw custom delegate

`

extension workoutStartedView: TableViewCellDelegate {

    func tableView(tableViewCell: WorkoutStartedTVCurrentExerciseCell, index: Int, didTappedInTableViewCell: WorkoutStartedCell) {
                
        //if didTappedInTableViewCell.remaining_sets.count > 1 {
        
        didTappedInTableViewCell.completed_sets.append(didTappedInTableViewCell.remaining_sets.first!)
        didTappedInTableViewCell.remaining_sets.removeFirst()
            
        if completedSets.count > 0 {
            if self.completedSets.count > didTappedInTableViewCell.tag {
                self.completedSets[didTappedInTableViewCell.tag] = didTappedInTableViewCell.completed_sets
            } else if self.completedSets.count <= didTappedInTableViewCell.tag {
                self.completedSets.append(didTappedInTableViewCell.completed_sets)
            }
        } else if completedSets.count <= 0 {
            self.completedSets.append(didTappedInTableViewCell.completed_sets)
        }
        
        if self.remainingSets[didTappedInTableViewCell.tag].count > 0 {
            self.remainingSets[didTappedInTableViewCell.tag] = didTappedInTableViewCell.remaining_sets
        } else if self.remainingSets[didTappedInTableViewCell.tag].count <= 1 {
            self.remainingSets.removeFirst()
        }
        
        print(didTappedInTableViewCell.completed_sets)
        print(didTappedInTableViewCell.remaining_sets)
        print(self.completedSets)
        print(self.remainingSets)
            
        //collectionView.reloadData()
        didTappedInTableViewCell.tableView.reloadData()
        
    }

}

`

[ad_2]

Leave a Reply