Swift 3中tableView在reloadData()后未更新

3

我正在构建一个主从应用程序。我有一个章节视图控制器(VC),它是主VC的子级。点击章节VC中的行会弹出不同的详细VC,用户在其中完成所需信息。一旦详细VC中的信息完成,我希望在相关章节VC行中显示一个勾号。FYI,selectedProject是一个核心数据对象。

我在详细VC的viewWillDisappear中调用通知以刷新章节VC。

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
    let detailCase: String = selectedProject!.section![indexPath.row]
    configureCell(cell, withSectionName: detailCase)
    print("location complete is \(selectedProject!.completeLocation)")
    print("electricity complete is \(selectedProject!.completeElectricity)"
    print(cell.textLabel!.text!)
    print(cell.accessoryType.rawValue)
    return cell
}

func configureCell(_ cell: UITableViewCell, withSectionName sectionName: String) {
        switch sectionName {
        case "Project Details" :
            cell.accessoryType = .checkmark
        case "Location" :
            if selectedProject?.completeLocation == true {
                cell.accessoryType = .checkmark
            }
        case "Electricity Use" :
            if selectedProject?.completeElectricity == true {
                cell.accessoryType = .checkmark
            }
        default :
            cell.accessoryType = .none
        }
        cell.textLabel!.text = sectionName
}

func refreshTable(notification: Notification) -> Void {
    print("Notification ran")
    self.tableView.reloadData()
}

控制台:

通知已运行

位置完成为真

用电完成为真

项目详细信息

3

位置完成为真

用电完成为真

位置

3

位置完成为真

用电完成为真

用电量

3

The 3's = .checkmark

看起来cellForRowAt非常清楚它应该做什么,但表格没有立即显示复选标记。相反,您必须单击返回到主VC,然后转到分区VC以显示复选标记,或者您必须单击分区VC中的不同行,复选标记将随机显示。

我尝试在dispatchqueue.main.async中调用reloadData,但没有成功。我再次尝试在流程的不同点调用reloadData,但仍然没有成功。我尝试调用tableView.beginUpdates/.endUpdates和reloadSectionData,同样无法使复选标记显示。

如果我以编程方式提示section VC的viewWilDisappear和viewWillAppear,当选择sections VC中的不同行时,复选标记将出现。 “似乎” reloadData()并没有促使tableView完全重新加载。

附:storyboard中的accessory项设置为.none。

4个回答

14

UI更新需要在主队列上调用。尝试这样做:

DispatchQueue.main.async {
    self.tableView.reloadData()
}

正确的解决方案! - Mannopson
感谢您的回答。在我的问题底部,我提到了我尝试过DispatchQueue.main.async,但没有成功。我已经尝试通过通知器调用它,除非您建议其他可能有效的位置。 - Chris Bell
@ChrisBell:在这种情况下,我对核心问题的判断可能是错误的(尽管始终将UI更新放在主线程上)。您应该将代码更新为您当前使用的版本,并确认refreshTable:是否被调用。这将帮助我们缩小问题范围。 - dylanthelion

2
这对我有帮助。希望它能帮到你 :)
 DispatchQueue.main.async {
            self.tableView.reloadData()
            self.tableView.beginUpdates()
            self.tableView.endUpdates()
        }

dylanthelion已经回答了关于.reloadData()和DispatchQueue.main.async的问题。至于beginUpdates()和endUpdates(),它们是不必要的。 - Eric Aya
对于我和那个提问的人(请阅读他的回复),仅使用.reloadData在我们的情况下并没有起作用。只有当我添加了beginUpdates和endUpdates时,它才能正常工作。 - Matthew
在这种情况下,我认为你应该解释一下为什么你不得不这样做。这部分内容真的可以帮助其他人。 :) (点击[编辑]进行操作) - Eric Aya
我不知道为什么,但我也需要这个操作序列来强制刷新tableView。在我的代码中,仅仅调用reloadData是不够的。谢谢。 - Marco

0
请确保在viewDidLoad()方法中使用了以下两行代码:
//registering the xib
self.tableView.register(UINib(nibName: "enter_xib_class_name", bundle: nil), forCellReuseIdentifier: "enter_cell_identifier")
//delegate enabling
self.tableView.delegate=self
//datasource
self.tableView.datasource=self

0

好的,鉴于没有任何修复措施,我改变了tableView的类型,从动态变为静态。我为所有固定单元格创建了tableViewCell输出口,然后通过这种方式添加和删除了勾选标记。

对于任何感兴趣的人,以下是代码:

var tableCellArray = [UITableViewCell]()

/*-----------------------------------------------------------*/

// MARK: - Outlets

@IBOutlet weak var projectDetails: UITableViewCell!
@IBOutlet weak var location: UITableViewCell!
@IBOutlet weak var electricityUse: UITableViewCell!

// MARK: - Actions

// MARK: - Default functions

override func viewDidLoad() {
    super.viewDidLoad()
    tableCellArray = [projectDetails, location, electricityUse]
    configureCells()
    NotificationCenter.default.addObserver(forName: Notification.Name(rawValue: "refresh"), object: nil, queue: nil, using: refreshTable)
}

// MARK: - Table view data source

func configureCells() {
    var i = 0
    for each in tableCellArray {
        configureCheckmark(each, withIndex: i)
        i = i + 1
    }
}

func configureCheckmark(_ cell: UITableViewCell, withIndex index: Int) {
    var accessoryType: UITableViewCellAccessoryType = .none
    switch index {
        case 0 :
            accessoryType = .checkmark
        case 1 :
            if selectedProject?.completeLocation == true {
                accessoryType = .checkmark
            }
        case 2 :
            if selectedProject?.completeElectricity == true {
                accessoryType = .checkmark
            }
        default :
            accessoryType = .none
        }
    cell.accessoryType = accessoryType
}

func refreshTable(notification: Notification) -> Void {
    configureCells()
    tableView.beginUpdates()
    tableView.endUpdates()
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接