如何使用委托更新 table 视图单元格
How to update a table view cell using a delegate
我有一个委托方法,将对象从详细视图控制器传递到主视图控制器,这是一个 table 视图控制器。然后该对象用于更新 table 视图的数据:
var filters = [Filter]()
func didSelectFilter(selectedFilter: Filter) {
// finds the relevant data from the array and updates it
for case var filter in filters where filter.title == selectedFilter.title {
filter.setting = selectedFilter.setting
}
tableview.reloadData()
}
我可以确认对象正在正确传递。对象如下:
struct Filter {
let title: FilterType
var setting: String
}
但是,更新后的数据未反映在 table 视图中。
我已经尝试为每个数据分配索引路径并更新特定的单元格,但仍然没有反映出变化:
if let indexPath = filter.indexPath {
let foundIndexPath = IndexPath(row: indexPath.row, section: indexPath.section)
if let cell = tableView.cellForRow(at: foundIndexPath) {
cell.textLabel?.text = filter.setting
}
}
我如何在详细视图控制器中使用委托方法:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let selectedData = parsedData[indexPath.row]
// update the data to be passed
filter.setting = selectedData
// pass the data to the master view controller
delegate?.didSelectFilter(selectedFilter: filter)
self.navigationController?.popViewController(animated: true)
}
class Filter {
var title: FilterType!
var setting: String!
init(title: FilterType, setting: String) {
self.title = title
self.setting = setting
}
}
换句话说,Filter
对象在主视图控制器中创建,传递给详细视图控制器,进行修改,然后传递回主视图控制器。问题是更改没有反映在主视图控制器的 table 视图中。
由于您的模型是 struct
,即值类型,因此在 for case var filter...
中创建变量时,您实际上是在创建一个副本,而不是修改它自己的数据源。
您可以做的是将您的模型变成 class,这样您就可以创建对数据源中对象的引用,或者替换索引路径中的对象。例如:
for case var filter in filters where filter.title == selectedFilter.title {
filter.setting = selectedFilter.setting
self.filters[theRelevantIndexPosition] = filter
}
有多种方法可以做到这一点 - 您可以先使用您的数据来处理它,然后在您的多个控制器中实现它。
假设您有 一些东西 像这样:
enum FilterType {
case TypeA, TypeB, TypeC, TypeD
}
struct Filter {
let title: FilterType
var setting: String
}
这是一个您可以 运行 作为简单视图控制器的示例:
class MasterViewController: UIViewController {
var filters: [Filter] = []
override func viewDidLoad() {
super.viewDidLoad()
// init array with 7 Filter objects, various "title" types
filters.append(Filter(title: .TypeA, setting: "1"))
filters.append(Filter(title: .TypeB, setting: "2"))
filters.append(Filter(title: .TypeC, setting: "3"))
filters.append(Filter(title: .TypeD, setting: "4"))
filters.append(Filter(title: .TypeB, setting: "5"))
filters.append(Filter(title: .TypeC, setting: "6"))
filters.append(Filter(title: .TypeB, setting: "7"))
print("array before update")
filters.forEach {
print([=11=])
}
print() // blank line
// create "selected" Filter - this would come from your Detail VC
let selFilter = Filter(title: .TypeB, setting: "Change Me")
didSelectFilter(selectedFilter: selFilter)
print("array after update")
filters.forEach {
print([=11=])
}
print() // blank line
}
func didSelectFilter(selectedFilter: Filter) {
// change .setting on each array element where .title == selectedFilter.title
filters.indices.filter { filters[[=11=]].title == selectedFilter.title } .forEach {
filters[[=11=]].setting = selectedFilter.setting
}
// tableView.reloadData()
}
}
调试控制台输出将如下所示:
before
Filter(title: TestApp.FilterType.TypeA, setting: "1")
Filter(title: TestApp.FilterType.TypeB, setting: "2")
Filter(title: TestApp.FilterType.TypeC, setting: "3")
Filter(title: TestApp.FilterType.TypeD, setting: "4")
Filter(title: TestApp.FilterType.TypeB, setting: "5")
Filter(title: TestApp.FilterType.TypeC, setting: "6")
Filter(title: PanZoom.FilterType.TypeB, setting: "7")
after
Filter(title: TestApp.FilterType.TypeA, setting: "1")
Filter(title: TestApp.FilterType.TypeB, setting: "Change Me")
Filter(title: TestApp.FilterType.TypeC, setting: "3")
Filter(title: TestApp.FilterType.TypeD, setting: "4")
Filter(title: TestApp.FilterType.TypeB, setting: "Change Me")
Filter(title: TestApp.FilterType.TypeC, setting: "6")
Filter(title: PanZoom.FilterType.TypeB, setting: "Change Me")
如您所见,.title == .TypeB
的元素更新了 .setting
属性。
如果您知道您的数组将只有每个“标题”类型的一个元素,而不是获取所有元素的索引使用那种类型,你可以这样做:
if let idx = filters.firstIndex(where: { [=13=].title == selectedFilter.title }) {
filters[idx].setting = selectedFilter.setting
}
我有一个委托方法,将对象从详细视图控制器传递到主视图控制器,这是一个 table 视图控制器。然后该对象用于更新 table 视图的数据:
var filters = [Filter]()
func didSelectFilter(selectedFilter: Filter) {
// finds the relevant data from the array and updates it
for case var filter in filters where filter.title == selectedFilter.title {
filter.setting = selectedFilter.setting
}
tableview.reloadData()
}
我可以确认对象正在正确传递。对象如下:
struct Filter {
let title: FilterType
var setting: String
}
但是,更新后的数据未反映在 table 视图中。
我已经尝试为每个数据分配索引路径并更新特定的单元格,但仍然没有反映出变化:
if let indexPath = filter.indexPath {
let foundIndexPath = IndexPath(row: indexPath.row, section: indexPath.section)
if let cell = tableView.cellForRow(at: foundIndexPath) {
cell.textLabel?.text = filter.setting
}
}
我如何在详细视图控制器中使用委托方法:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let selectedData = parsedData[indexPath.row]
// update the data to be passed
filter.setting = selectedData
// pass the data to the master view controller
delegate?.didSelectFilter(selectedFilter: filter)
self.navigationController?.popViewController(animated: true)
}
class Filter {
var title: FilterType!
var setting: String!
init(title: FilterType, setting: String) {
self.title = title
self.setting = setting
}
}
换句话说,Filter
对象在主视图控制器中创建,传递给详细视图控制器,进行修改,然后传递回主视图控制器。问题是更改没有反映在主视图控制器的 table 视图中。
由于您的模型是 struct
,即值类型,因此在 for case var filter...
中创建变量时,您实际上是在创建一个副本,而不是修改它自己的数据源。
您可以做的是将您的模型变成 class,这样您就可以创建对数据源中对象的引用,或者替换索引路径中的对象。例如:
for case var filter in filters where filter.title == selectedFilter.title {
filter.setting = selectedFilter.setting
self.filters[theRelevantIndexPosition] = filter
}
有多种方法可以做到这一点 - 您可以先使用您的数据来处理它,然后在您的多个控制器中实现它。
假设您有 一些东西 像这样:
enum FilterType {
case TypeA, TypeB, TypeC, TypeD
}
struct Filter {
let title: FilterType
var setting: String
}
这是一个您可以 运行 作为简单视图控制器的示例:
class MasterViewController: UIViewController {
var filters: [Filter] = []
override func viewDidLoad() {
super.viewDidLoad()
// init array with 7 Filter objects, various "title" types
filters.append(Filter(title: .TypeA, setting: "1"))
filters.append(Filter(title: .TypeB, setting: "2"))
filters.append(Filter(title: .TypeC, setting: "3"))
filters.append(Filter(title: .TypeD, setting: "4"))
filters.append(Filter(title: .TypeB, setting: "5"))
filters.append(Filter(title: .TypeC, setting: "6"))
filters.append(Filter(title: .TypeB, setting: "7"))
print("array before update")
filters.forEach {
print([=11=])
}
print() // blank line
// create "selected" Filter - this would come from your Detail VC
let selFilter = Filter(title: .TypeB, setting: "Change Me")
didSelectFilter(selectedFilter: selFilter)
print("array after update")
filters.forEach {
print([=11=])
}
print() // blank line
}
func didSelectFilter(selectedFilter: Filter) {
// change .setting on each array element where .title == selectedFilter.title
filters.indices.filter { filters[[=11=]].title == selectedFilter.title } .forEach {
filters[[=11=]].setting = selectedFilter.setting
}
// tableView.reloadData()
}
}
调试控制台输出将如下所示:
before
Filter(title: TestApp.FilterType.TypeA, setting: "1")
Filter(title: TestApp.FilterType.TypeB, setting: "2")
Filter(title: TestApp.FilterType.TypeC, setting: "3")
Filter(title: TestApp.FilterType.TypeD, setting: "4")
Filter(title: TestApp.FilterType.TypeB, setting: "5")
Filter(title: TestApp.FilterType.TypeC, setting: "6")
Filter(title: PanZoom.FilterType.TypeB, setting: "7")
after
Filter(title: TestApp.FilterType.TypeA, setting: "1")
Filter(title: TestApp.FilterType.TypeB, setting: "Change Me")
Filter(title: TestApp.FilterType.TypeC, setting: "3")
Filter(title: TestApp.FilterType.TypeD, setting: "4")
Filter(title: TestApp.FilterType.TypeB, setting: "Change Me")
Filter(title: TestApp.FilterType.TypeC, setting: "6")
Filter(title: PanZoom.FilterType.TypeB, setting: "Change Me")
如您所见,.title == .TypeB
的元素更新了 .setting
属性。
如果您知道您的数组将只有每个“标题”类型的一个元素,而不是获取所有元素的索引使用那种类型,你可以这样做:
if let idx = filters.firstIndex(where: { [=13=].title == selectedFilter.title }) {
filters[idx].setting = selectedFilter.setting
}