UITableviewCell Publisher emits value multiple times

Viewed 585

I am trying to use Publisher instead of completion closure for a button action of an UITableviewCell.

My custom cell:

import UIKit
import Combine

class PostTVCell: UITableViewCell {
    
    @IBOutlet private var lblTitle: UILabel!
    
    private var postModel: PostModel?
    public var showDetailsPublisher = PassthroughSubject<PostModel, Never>()
    
    public func load(with model: PostModel) {
        self.postModel = model
        lblTitle.text = model.title
    }
    
    @IBAction
    private func showDetails(_ sender: UIButton) {
        showDetailsPublisher.send(postModel!)
    }
}

UITableviewDataSource code from ViewController:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! PostTVCell
        let post = postList[indexPath.row]
        cell.load(with: post)
        cell.showDetailsPublisher
            .sink { postModel in
                print("Closure called")
            }
            .store(in: &subscriptions)
        return cell
    }

It's working and subscriber closure is being called. But problem is if I scroll tableView and then press button of a cell, subscriber closure called several times. Is there have any default operator or any other mechanism, through which I can confirm, that a cell's publisher will receive subscriber only once.

2 Answers

Approaches:

Initialize Passthrough subject inside overridden function of UITableviewCell prepareForReuse(). So that whenever cell is being reused new publisher is being initialized and old on is being deinitialized thus subscriber of old publisher is being deinitialized automatically.

take subscription reference inside TableviewCell, thus old subscription is being replaced by new subscription.

My suggestion is to create one Publisher in the table and inject it into the cell when the cell is set. The cell will communicate the relevant information back via this single publisher.

You sink to this publisher in the table only once. This way you prevent unneeded memory waste, and potential memory leaks.

Don't forget to set the publisher in the cell to nil inside override func prepareForReuse().

Related