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.