初始加载后从数据模型更新 uiTableViewCell
Updating uiTableViewCell from data model after intial load
我是 iOS 开发的新手,所以这个问题可能看起来微不足道。我搜索了一下,找不到关于这个问题的任何问题。但我想知道在从数据模型 初始加载单元格后 运行 时间 更改数据模型时更新 UITableView
的自定义单元格的正确方法是什么。从更改,我的意思是数据条目更改,而不是添加或删除数据。
这是一个例子。假设我有这些 DataModel
和 DataModelCell
如下:
class DataModelView : UITableViewCell {
@IBOutlet weak var mainLabel: UILabel!
}
class DataModel {
var title: String = "" {
didSet {
// which cell this entry is connected to?
}
}
}
...
items: [DataModel] = []
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "DataModelView", for: indexPath)
cell.mainLabel?.text = items[indexPath.item].title
// addition line for each approach
// approach 1:
// items[indexPath.item].view = cell
// approach 2:
// items[indexPath.item].viewIndexPath = indexPath
return cell
}
我的问题是,当我在 运行 时间更改数据模型 中的一个单元格 title
时,我想更新相应的单元格UI。我想知道在 UITableView
.
中建立数据模型条目和单元格之间关系的最佳方法是什么
我想到了 3 种不同的方法。我想知道他们是否正确,或者有没有更好的方法:
第一种方法: weak
指向我的数据条目中单元格的指针,如下所示:
class DataModel {
weak var view: DataModelView?
var title: String = "" {
didSet {
view?.mainLabel?.text = title
}
}
}
第二种方法: 在我的数据条目中保留 IndexPath
个单元格,如下所示:
class DataModel {
var viewIndexPath: IndexPath?
var title: String = "" {
didSet {
// call delegate to controller and ask to update cell for viewIndexPath
}
}
}
第三种方法:不要保留与数据输入中的单元格对应的任何内容:
class DataModel {
var title: String = "" {
didSet {
// call delegate to controller and ask to find and update cell for self
}
}
}
在前两种方法中,我在数据模型中保持单元格和数据模型之间的关系。在第三种方法中,我需要在控制器中保持这种关系。
这些方法都正确吗(尤其是第一种)?你推荐哪一个?通常最好的方法是什么?
我看到人们在他们的视图中保留指向数据模型的指针,以便从视图中更新数据模型。我想知道它在其他方面是否也正确(第一种方法)。
应该是这样的
class DataModelView: UITableViewCell {
@IBOutlet weak var mainLabel: UILabel!
var yourModel: DataModel? {
didSet {
mainLabel.text = yourModel?.title
}
}
在你的 cellForRowAt
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "DataModelView", for: indexPath)
cell.yourData = items[indexPath.item]
return cell
}
在您的项目数组中更改任何项目后,只需调用
tableView.reloadData()
第4种方法:单元格中数据模型的弱指针和键值观察
class DataModelView : UITableViewCell {
@IBOutlet weak var mainLabel: UILabel!
var observation : NSKeyValueObservation?
weak var model : DataModel? {
didSet {
if model == nil { observation = nil }
else {
observation = model!.observe(\.title, options: [.new]) { [weak self] (model, _) in
self?.mainLabel.text = model.title
}
}
}
}
}
KVO 需要从 NSObject
继承
class DataModel : NSObject {
@objc dynamic var title: String = ""
}
在cellForRow
传递模型
let cell = tableView.dequeueReusableCell(withIdentifier: "DataModelView", for: indexPath) as! DataModelView
cell.model = items[indexPath.row]
并移除 didEndDisplaying
中的观察者
func tableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath) {
(cell as! DataModelView).observation = nil
}
我是 iOS 开发的新手,所以这个问题可能看起来微不足道。我搜索了一下,找不到关于这个问题的任何问题。但我想知道在从数据模型 初始加载单元格后 运行 时间 更改数据模型时更新 UITableView
的自定义单元格的正确方法是什么。从更改,我的意思是数据条目更改,而不是添加或删除数据。
这是一个例子。假设我有这些 DataModel
和 DataModelCell
如下:
class DataModelView : UITableViewCell {
@IBOutlet weak var mainLabel: UILabel!
}
class DataModel {
var title: String = "" {
didSet {
// which cell this entry is connected to?
}
}
}
...
items: [DataModel] = []
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "DataModelView", for: indexPath)
cell.mainLabel?.text = items[indexPath.item].title
// addition line for each approach
// approach 1:
// items[indexPath.item].view = cell
// approach 2:
// items[indexPath.item].viewIndexPath = indexPath
return cell
}
我的问题是,当我在 运行 时间更改数据模型 中的一个单元格 title
时,我想更新相应的单元格UI。我想知道在 UITableView
.
我想到了 3 种不同的方法。我想知道他们是否正确,或者有没有更好的方法:
第一种方法: weak
指向我的数据条目中单元格的指针,如下所示:
class DataModel {
weak var view: DataModelView?
var title: String = "" {
didSet {
view?.mainLabel?.text = title
}
}
}
第二种方法: 在我的数据条目中保留 IndexPath
个单元格,如下所示:
class DataModel {
var viewIndexPath: IndexPath?
var title: String = "" {
didSet {
// call delegate to controller and ask to update cell for viewIndexPath
}
}
}
第三种方法:不要保留与数据输入中的单元格对应的任何内容:
class DataModel {
var title: String = "" {
didSet {
// call delegate to controller and ask to find and update cell for self
}
}
}
在前两种方法中,我在数据模型中保持单元格和数据模型之间的关系。在第三种方法中,我需要在控制器中保持这种关系。
这些方法都正确吗(尤其是第一种)?你推荐哪一个?通常最好的方法是什么?
我看到人们在他们的视图中保留指向数据模型的指针,以便从视图中更新数据模型。我想知道它在其他方面是否也正确(第一种方法)。
应该是这样的
class DataModelView: UITableViewCell {
@IBOutlet weak var mainLabel: UILabel!
var yourModel: DataModel? {
didSet {
mainLabel.text = yourModel?.title
}
}
在你的 cellForRowAt
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "DataModelView", for: indexPath)
cell.yourData = items[indexPath.item]
return cell
}
在您的项目数组中更改任何项目后,只需调用
tableView.reloadData()
第4种方法:单元格中数据模型的弱指针和键值观察
class DataModelView : UITableViewCell {
@IBOutlet weak var mainLabel: UILabel!
var observation : NSKeyValueObservation?
weak var model : DataModel? {
didSet {
if model == nil { observation = nil }
else {
observation = model!.observe(\.title, options: [.new]) { [weak self] (model, _) in
self?.mainLabel.text = model.title
}
}
}
}
}
KVO 需要从 NSObject
class DataModel : NSObject {
@objc dynamic var title: String = ""
}
在cellForRow
传递模型
let cell = tableView.dequeueReusableCell(withIdentifier: "DataModelView", for: indexPath) as! DataModelView
cell.model = items[indexPath.row]
并移除 didEndDisplaying
func tableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath) {
(cell as! DataModelView).observation = nil
}