Ios UITableView的数据源未更新阵列
我正在为UITableView创建数据源。数据源负责使用WeatherViewModel类显示天气信息。下面是WeatherDataSource的实现Ios UITableView的数据源未更新阵列,ios,swift,uitableview,Ios,Swift,Uitableview,我正在为UITableView创建数据源。数据源负责使用WeatherViewModel类显示天气信息。下面是WeatherDataSource的实现 class WeatherDataSource: NSObject, UITableViewDataSource { var cellIdentifier: String var weatherViewModels = [WeatherViewModel]() init(cellIdentifier: String,
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
在我的视图控制器中,我初始化数据源,如图所示:
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.navigationBar.prefersLargeTitles = true
self.datasource = WeatherDataSource(cellIdentifier: "WeatherCell", weatherViewModels: self.weatherListViewModel.weatherViewModels)
self.tableView.dataSource = self.datasource
}
添加新项目时,我会将其添加到WeatherListViewModel视图模型中的weatherViewModels集合,如下所示:
func addWeatherDidSave(vm: WeatherViewModel) {
self.weatherListViewModel.addWeatherViewModel(vm)
print(self.weatherListViewModel.weatherViewModels.count) // this prints 1
self.tableView.reloadData()
}
上面的self.weatherListViewModel.weatherViewModels.count显示为1,表示已插入项。但是当我在线重新加载tableview时,WeatherDataSource内部的weatherViewModels仍然是空的!为什么呢?当我创建WeatherDataSource时,我向它传递了相同的数组。现在,我正在修改数组,以便它不会自动反映在数据源中
更新:查看模型代码
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"
}
}
解决方案:我的解决方案是向数据源添加一个更新方法,并传入更新的数组。我不太喜欢,但它很管用
func update(weatherViewModels: [WeatherViewModel]) {
self.weatherViewModels = weatherViewModels
}
然后,在视图控制器中,您可以这样使用它:
func addWeatherDidSave(vm:WeatherViewModel){
您没有显示self.weatherListViewModel.addWeatherViewModel()的代码,但如果该方法只更新了
self.weatherListViewModel
数组,则此更改不会传播到WeatherDataSource
实例,因为该实例操作的是您在初始化时传入的任何内容的副本。要更改需要更改的行数self.datasource.weatherViewModels数组。您的代码不会这样做。您的问题是将self.weatherListViewModel.weatherViewModels
而不是self.weatherListViewModel
传递给WeatherDataSource
实例
class WeatherDataSource: NSObject, UITableViewDataSource {
var cellIdentifier: String
var weatherViewModel: WeatherListViewModel
init(cellIdentifier: String, weatherViewModel: WeatherListViewModel) {
self.cellIdentifier = cellIdentifier
self.weatherViewModel = weatherViewModel
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print(self.weatherViewModel.weatherViewModels.count)
return self.weatherViewModel.weatherViewModels.count
}
}
由于self.weatherListViewModel.weatherViewModels是一个数组,因此它是一个值类型,而不是引用类型
这意味着WeatherDataSource
实例中的weatherViewModels
和WeatherListViewModel
实例中的weatherViewModels
是不同的数组。虽然WeatherDataSource
是一个类,因此是一个引用类型,但属性本身是一个值类型。您需要始终对WeatherListViewModel
实例中的阵列进行操作
class WeatherDataSource: NSObject, UITableViewDataSource {
var cellIdentifier: String
var weatherViewModel: WeatherListViewModel
init(cellIdentifier: String, weatherViewModel: WeatherListViewModel) {
self.cellIdentifier = cellIdentifier
self.weatherViewModel = weatherViewModel
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print(self.weatherViewModel.weatherViewModels.count)
return self.weatherViewModel.weatherViewModels.count
}
}
视图控制器
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.navigationBar.prefersLargeTitles = true
self.datasource = WeatherDataSource(cellIdentifier: "WeatherCell", weatherViewModels: self.weatherListViewModel)
self.tableView.dataSource = self.datasource
}
您是否有用于tableView的
IBOutlet
?您也可以添加var定义吗?实际上,您不更新数据源实例,而是更新一些甚至未连接到表视图的其他实例。@kirander在下面的回答部分查看我的评论。问题有所不同。因此,即使WeatherViewModel是一个类,它仍将作为副本而不是引用传递?刚刚意识到Swift函数中的所有内容都是作为副本传递的。:(不,只复制值类型,不复制引用类型。知道哪个是副本非常重要:)实际上,当向函数传递参数时,它们总是被复制的。根据这篇文章:因为,我传递一个数组,它是通过复制数组而不是引用数组来传递数组。如果数组可以基于数组的内容被引用,那就太好了,但是看起来它总是按值传递。谢谢!是的,你是正确的对于以上工作,WeatherListViewModel应该是一个类,对吗?因为我将其恢复为struct,但它不工作,因为struct将创建一个副本。类可以工作。对,因为struct是一个值类型,并且在您对它进行变异后,它将立即成为副本。