UICollectionView状态恢复:恢复所有UICollectionViewCells

时间:2017-09-22 06:51:23

标签: ios swift xcode restore state-restoration

我通过Google和SO搜索了很多,所以如果这个问题已经得到解答,请原谅我!

问题: 我有UICollectionViewUICollectionViewCells。每个单元格包含来自XIB文件的UIView。视图用于数据输入,因此所有单元格都具有唯一的reuseIdentifier。每个视图还有一个唯一的restorationIdentifier。一切都在正常使用中起作用,但在涉及状态恢复时则不行:

前3或4个单元格正在正常恢复,因为它们在启动时在屏幕上可见,但其余不可见的单元格无法恢复。

当前解决方案: 所以到目前为止我发现只有在启动时将View添加到用户界面时才会恢复。 我目前的工作解决方案是在恢复过程中将所有单元格的高度设置为1。现在加载每个单元格并恢复所有视图。 调用applicationFinishedRestoringState()时,我会以正确的高度重新加载CollectionView。

现在我的问题是:我对此解决方案不满意,是否有更简洁的方法来恢复所有UIViews?

1 个答案:

答案 0 :(得分:1)

我认为您的数据模型与您的观点之间存在一些混淆。首次初始化时,表视图由数据模型构建,提取存储的值以填充每个单元格中的任何内容。但是,您的用户不直接与数据模型交互,而是与屏幕上的视图交互。如果用户在表视图中更改了某些内容,则需要将该更改发送回视图控制器,以便它可以将更改记录到数据模型中。这意味着,如果需要重新创建视图,视图控制器将获得在应用程序进入后台时重建表格中所需内容所需的信息。

我在这里整理了一个简单的gitHub存储库:https://github.com/mpj-chandler/StateManagementDemo

这包括一个CustomTableViewController类,它管理用CustomTableViewCells填充的标准UITableView。自定义单元格包含三个开关按钮,允许每个单元格的状态由布尔值数组表示。

我为单元创建了一个委托协议,这样如果任何一个开关被触发,信号就会被发送回视图控制器:

protocol CustomTableViewCellDelegate {
    func stateDidChange(sender: CustomTableViewCell) -> Void
}

// Code in CustomTableViewCell.swift:

@objc fileprivate func switched(sender: UISwitch) -> Void {

    guard let index : Int = switches.index(of: sender) else { return }

    state[index] = sender.isOn   
}

// The cell's state is an observed parameter with the following didSet method:

fileprivate var state : [Bool] = Array(repeating: false, count: 3) {
    didSet {
        if state != oldValue, let _ = delegate {
            delegate!.stateDidChange(sender: self)
        }
    }
}

CustomTableViewController注册到CustomTableViewCellDelegate协议,因此它可以记录模型中的更改,如下所示:

// Code in CustomTableViewController.swift

//# MARK:- CustomTableViewCellDelegate methods

internal func stateDidChange(sender: CustomTableViewCell) -> Void {
    guard let indexPath : IndexPath = tableView.indexPath(for: sender) else { return }
    guard indexPath.row < model.count else { print("Error in \(#function) - cell index larger than model size!") ; return }

    print("CHANGING MODEL ROW [\(indexPath.row)] TO: \(sender.getState())")
    model[indexPath.row] = sender.getState()

}

您可以在此处看到该功能已设置为将模型更改输出到控制台。

如果您在模拟器中运行项目并退出到主屏幕并再次返回,您将看到tableView单元格的状态被保留,因为该模型反映了应用程序进入后台之前所做的更改。

希望有所帮助。