UICollectionView状态还原:恢复所有UICollectionViewCells

问题描述:

我搜索了很多通过谷歌和所以,请原谅我,如果这个问题已经得到回答!UICollectionView状态还原:恢复所有UICollectionViewCells

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

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

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

现在我的问题是:我对这个解决方案不满意,还有没有一种更干净的方式来恢复所有的UIViews?

我认为你在你的数据模型和你的视图之间有点混乱。当第一次初始化时,你的表视图是从一个数据模型构造的,拉入存储的值以填充每个单元格中的任何内容。但是,您的用户不直接与数据模型交互,而是与屏幕上的视图交互。如果用户在表格视图中更改某些内容,则需要将该更改通知给视图控制器,以便它可以将更改记录到数据模型中。这意味着,如果需要重新创建视图,则视图控制器具有在应用程序进入后台时重建表中任何内容所需的信息。

我在这里把一个简单的GitHub库:https://github.com/mpj-chandler/StateManagementDemo

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

我创建了这样的细胞的委托协议,如果任何所述开关的跳闸时,信号被发送回视图控制器:

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单元格的状态被保留,因为该模型反映了应用程序进入背景之前所做的更改。

希望有所帮助。

+0

首先,感谢您为帮助我所做的工作! 我有点困惑,我想我没有完全理解国家恢复体系。你的方法和我的区别在于,我使用encodeRestorableState方法来保存和decodeRestorableState来恢复每个视图和视图控制器的信息。您使用编码和init(编码器aDecoder:NSCoder)方法。你能告诉我这个系统之间的目的不同吗? – Martin

+1

@Martin - 对于您定义了自定义初始化程序的类,init(coder :)和encode(coder :)是必需的。请参阅官方文档:https://developer.apple.com/documentation/foundation/nscoding。您正在使用的方法是在应用程序级别进行状态管理。 https://www.raywenderlich.com/160653/design-patterns-ios-using-swift-part-22上的教程演示了这两种方法的用法。 – Sparky

+0

谢谢,我终于明白了,它应该如何,现在一切正常:) – Martin