Ios UITableView的数据源未更新阵列

Ios UITableView的数据源未更新阵列,ios,swift,uitableview,Ios,Swift,Uitableview,我正在为UITableView创建数据源。数据源负责使用WeatherViewModel类显示天气信息。下面是WeatherDataSource的实现 class WeatherDataSource: NSObject, UITableViewDataSource { var cellIdentifier: String var weatherViewModels = [WeatherViewModel]() init(cellIdentifier: String,

我正在为UITableView创建数据源。数据源负责使用WeatherViewModel类显示天气信息。下面是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
在我的视图控制器中,我初始化数据源,如图所示:

 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是一个值类型,并且在您对它进行变异后,它将立即成为副本。