我是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
}
我的问题是,当我在运行时更改数据模型中的一个单元格{strong> 中的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
}
}
}
在前两种方法中,我在数据模型中保持单元格与数据模型之间的关系。在第三种方法中,我需要将此关系保留在控制器中。
所有这些方法是否都正确(尤其是第一个)?您建议哪一个?通常什么是最佳方法?
我已经看到人们在他们的视图中保留了指向数据模型的指针,以便从视图中更新数据模型。我想知道它是否也以其他方式正确(第一种方法)。
答案 0 :(得分:1)
第四种方法:对单元格中数据模型的弱指示和对键值的观察
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
}
答案 1 :(得分:-1)
应该是这样
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()