ios - UICollectionView 状态恢复 : restore all UICollectionViewCells

标签 ios swift xcode restore state-restoration

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

问题: 我有一个带有 n 个 UICollectionViewCellsUICollectionView。每个单元格都包含来自 XIB 文件的 UIView。 View 用于数据输入,因此所有单元格都有一个唯一的 reuseIdentifier。每个 View 还有一个唯一的 restorationIdentifier。在正常使用中一切正常,但在状态恢复时却不行:

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

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

现在我的问题是:我对这个解决方案不满意,是否有更干净的方法来实现所有 UIView 的恢复?

最佳答案

我认为您对数据模型和 View 之间有点混淆。首次初始化时,您的 TableView 是根据数据模型构建的,提取存储的值以填充每个单元格中的任何内容。但是,您的用户并不直接与数据模型交互,而是与屏幕上的 View 交互。如果用户更改了 TableView 中的某些内容,您需要将该更改发回给 View Controller ,以便它可以将更改记录到数据模型中。这反过来意味着,如果需要重新创建 View ,则当您的应用程序进入后台时, View Controller 具有重建表中任何内容所需的信息。

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

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

我为单元格创建了一个委托(delegate)协议(protocol),这样如果任何一个开关被触发,一个信号就会被发送回 View Controller :

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 协议(protocol),这样它就可以记录模型中的变化,如下所示:

// 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 单元格的状态被保留,因为模型反射(reflect)了应用进入后台之前所做的更改。

希望对您有所帮助。

关于ios - UICollectionView 状态恢复 : restore all UICollectionViewCells,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46358508/

相关文章:

iphone - 从 iPhone 转发地理编码

iphone - 位置管理器在后台一段时间后停止工作

ios - Swift 中 UIImageWriteToSavedPhotosAlbum 后图像的 URL

swift - 解析 saveInBackgroundWithBlock 附加任务

swift - 在 XCode、iOS 开发中编译时 Keychain.swift 中生成错误

iphone - 如何使用 Xcode 制作首次启动 iPhone App 的导览

ios - 以键和值数组的形式快速从 JSON 中检索特定数组?

ios - 我们可以使用 CarPlay 撰写/接收音频信息吗?

objective-c - Objective C 代码库可以直接在 Swift 上运行吗?

ios - 将dylib添加到 "Link Binary With Libraries"和添加到 "Other Linker Flags"有什么区别