【问题标题】:UICollectionView state restoration: restore all UICollectionViewCellsUICollectionView状态恢复:恢复所有UICollectionViewCells
【发布时间】:2017-09-22 06:51:23
【问题描述】:

我通过谷歌和SO搜索了很多,所以请原谅我,如果这个问题已经回答了!

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

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

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

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

【问题讨论】:

    标签: ios swift xcode restore state-restoration


    【解决方案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 单元格的状态被保留,因为模型反映了应用程序进入后台之前所做的更改。

    希望对您有所帮助。

    【讨论】:

    • 首先,感谢您为帮助我所做的工作!我有点迷茫,我想我对状态恢复系统没有完全了解。您的方法和我的方法之间的区别在于,我使用 encodeRestorableState 方法来保存和 decodeRestorableState 来恢复每个视图和视图控制器的信息。您使用 encode 和 init(coder aDecoder: NSCoder) 方法。你能告诉我这些系统之间的目的不同吗?
    • @Martin - 您定义了自定义初始化程序的类需要 init(coder:) 和 encode(coder:)。请参阅官方文档:developer.apple.com/documentation/foundation/nscoding。您使用的方法用于应用程序级别的状态管理。 raywenderlich.com/160653/… 的教程演示了这两种方法的用法。
    • 谢谢你,我终于想通了,它应该是怎样的,现在一切正常了:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-09
    • 2010-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多