Home > front end >  Passing Data between view controllers using combine framework
Passing Data between view controllers using combine framework

Time:01-06

I am new to combine and was trying to play around in combine framework. But I am facing some issues when i try to pass a string from my tableview to detail page using a PassThroughSubject Below is my code.

The problem I face is sometimes I do not get a title in detail view controller but when you go back to tableview and click on the same row again it works. And same happens often

{

// MARK: Variables -

var viewModel = GitHubListingViewModel()
private var cancellables = Set<AnyCancellable>()
let reuseIdentifier = "Cell"

// MARK: Outlets -

@IBOutlet weak var gitHubListingTable: UITableView!

// MARK: Life Cycle -
override func viewDidLoad() {
    super.viewDidLoad()
    
    self.title = " Trending List"
    
    gitHubListingTable.dataSource = self
    gitHubListingTable.delegate = self
    
    self.gitHubListingTable.register(UINib(nibName: "GitHubListCell", bundle: nil), forCellReuseIdentifier: reuseIdentifier)
  
    viewModel.getGitHubListing()
  
    viewModel.$trendingGitHubList
        .receive(on: RunLoop.main)
        .sink { [weak self] _ in
            self?.gitHubListingTable.reloadData()
        }
        .store(in: &cancellables)
    
}

}

extension GitHubListing: UITableViewDataSource, UITableViewDelegate {
    
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return viewModel.getListCount()
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        let cell = gitHubListingTable.dequeueReusableCell(withIdentifier: reuseIdentifier, for: indexPath) as! GitHubListCell
        
        viewModel.trendingGitHubListing
            .receive(on: RunLoop.main)
            .sink { gitHubModel in
              //  if let gitHubModel = gitHubModel {
                    cell.configureCell(with: gitHubModel[indexPath.row])
              //  }
            }
            .store(in: &cancellables)
        
        return cell
    }
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let gitHubDetails = GitHubLinkDetails()
        tableView.deselectRow(at: indexPath, animated: true)
       
        viewModel.trendingGitHubListing
            .receive(on: RunLoop.main)
            .sink { githublist in
              //  if let githublist = githublist {
                    gitHubDetails.githubDetails.send(githublist[indexPath.row])
                gitHubDetails.sample.send("Title")
            //    }
            }
            .store(in: &cancellables)
        navigationController?.pushViewController(gitHubDetails, animated: true)
    }
    
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        100
    }
    
}

My detail view controller -

import UIKit
import Combine
import SDWebImage
class GitHubLinkDetails: UIViewController {
    
    // MARK: Variables -
    var sample = PassthroughSubject<String, Never>()

override func viewDidLoad() {
        super.viewDidLoad()
       self.getDetails()
        
        sample
            .sink { title in
                self.title = title
            }
            .store(in: &cancellables)
     
    }
}

CodePudding user response:

In your didSelectCellAt method, you set up your Detail View Controller in the .sink closure (which makes sense, since that's when you get the data). However, you then push the ViewController outside the closure. As a result, you have no guarantee that the setup is completed when the VC is pushed.

See what happens when you include navigationController?.pushViewController(...) as part of the .sink closure. Does that work as expected?

CodePudding user response:

PassthroughSubject based on apple documentation drops value if there are no subscribers(https://developer.apple.com/documentation/combine/passthroughsubject). To solve this issue with your current structure use CurrentValueSubject instead of PassthroughSubject. By using CurrentValueSubject you can always access the last published value even if you subscribe to the subject after publishing value.

  •  Tags:  
  • Related