I am creating a DataSource for my UITableView. Data source is responsible for displaying weather information using WeatherViewModel class. Here is the implementation of WeatherDataSource.
class WeatherDataSource: NSObject, UITableViewDataSource {
var cellIdentifier: String
var weatherViewModels = [WeatherViewModel]()
init(cellIdentifier: String, weatherViewModels: [WeatherViewModel]) {
self.cellIdentifier = cellIdentifier
self.weatherViewModels = weatherViewModels
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print(self.weatherViewModels.count) // This is always empty
return self.weatherViewModels.count
}
// some other methods
In my View Controller, I initialize the data source as shown:
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.navigationBar.prefersLargeTitles = true
self.datasource = WeatherDataSource(cellIdentifier: "WeatherCell", weatherViewModels: self.weatherListViewModel.weatherViewModels)
self.tableView.dataSource = self.datasource
}
When I add a new item I add it to the weatherViewModels collection in the WeatherListViewModel view model as shown below:
func addWeatherDidSave(vm: WeatherViewModel) {
self.weatherListViewModel.addWeatherViewModel(vm)
print(self.weatherListViewModel.weatherViewModels.count) // this prints 1
self.tableView.reloadData()
}
The self.weatherListViewModel.weatherViewModels.count above says 1 which means item got inserted. But when I reload the tableview in line, inside the WeatherDataSource weatherViewModels is still empty! Why is that? When I created the WeatherDataSource I passed the same array to it. Now, I am modifying the array so would it not automatically reflected inside the datasource.
UPDATE: ViewModel Code
class WeatherListViewModel {
private(set) var weatherViewModels = [WeatherViewModel]()
func addWeatherViewModel(_ vm: WeatherViewModel) {
self.weatherViewModels.append(vm)
}
class WeatherViewModel: Decodable {
let name: String
var currentTemperature: TemperatureViewModel
private enum CodingKeys: String, CodingKey {
case name
case currentTemperature = "main"
}
}
SOLUTION: My solution was to add an update method to the data source and pass in the updated array. I don't really like it but it works.
func update(weatherViewModels: [WeatherViewModel]) {
self.weatherViewModels = weatherViewModels
}
Then in the View Controller you can use it like this:
func addWeatherDidSave(vm: WeatherViewModel) {
self.weatherListViewModel.addWeatherViewModel(vm)
self.datasource?.update(weatherViewModels: self.weatherListViewModel.weatherViewModels)
self.tableView.reloadData()
}