Search code examples
iosswiftuitableviewviewmodel

TableView cells are repeating Swift


So I'm making a GET request to my database and then adding each element from my array into a ViewModel, in var mainComment: Comments?. In my Custom Cell I'm assigning my label text to the ViewModel's mainComment.likes. I'm supposed to get one like for only my one cell but instead the one like is repeating for multiple cells. https://giphy.com/gifs/L2U6FALmxWx981nO44

struct Comments: Codable {
    var id:String?
    var likes:Int?
}

import UIKit
import Foundation

class CommentViewModel {
    var mainComment: Comments? 
}

//CommentVC
var comments:[CommentViewModel] = []

func loadComments(completion:@escaping(()->())) {
        guard let post_id = post_id else {
            return
        }
        let getComments = GETComments(id: post_id, path: "comments")
        getComments.getAllById { comments in
              self.comments = comments.map { comment in
                let ret = CommentViewModel()
                ret.mainComment = comment
        
                return ret
            }
            self.myTableView.reloadData()
            completion()
            }
        }
    }

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "MyCell", for: indexPath as IndexPath) as! CommentCell
        let item = comments[indexPath.item]
        cell.viewModel = item
     
        return cell
    }


class CommentCell {
var viewModel: CommentViewModel? {
        didSet {
            if let item = viewModel {
                if let numberOfLikes = item.mainComment?.likes {
                    self.numberOfLikes.text = "\(numberOfLikes)"
                }
          }
}

lazy var numberOfLikes:UILabel = {
        let label = UILabel()
        label.textAlignment = .center
        label.text = "0"
        return label
    }()

override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        addSubview(numberOfLikes)
        commentLikesConstraints()
    }
func commentLikesConstraints() {
        numberOfLikes.translatesAutoresizingMaskIntoConstraints = false
        numberOfLikes.widthAnchor.constraint(equalToConstant: 60).isActive = true
        numberOfLikes.heightAnchor.constraint(equalToConstant: 30).isActive = true
        numberOfLikes.centerXAnchor.constraint(equalTo: likeBtn.centerXAnchor).isActive = true
        numberOfLikes.topAnchor.constraint(equalTo: likeBtn.bottomAnchor, constant: -5).isActive = true
    }

Solution

  • Since you're using mainComment and likes as optionals:

    struct Comments: Codable {
        var id:String?
        var likes:Int?
    }
    

    You need to handle an else case (and probably also want an else case if viewModel is nil):

    var viewModel: CommentViewModel? {
        didSet {
            if let item = viewModel {
                if let numberOfLikes = item.mainComment?.likes {
                    self.numberOfLikes.text = "\(numberOfLikes)"
                } else {
                    self.numberOfLikes.text = "0"
                }
            } else {
                // do what you need to do if viewModel is nil
            }
        }
    }