如何使用委托更新 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
    }