Implementing State Restoration in iOS 14

UICollectionView state restoration: restore all UICollectionViewCells

I think you are getting a bit confused between your data model and your views. When first initialised, your table view is constructed from a data model, pulling in stored values in order to populate whatever is in each cell. However, your user does not interact directly with the data model, but with the view on the screen. If the user changes something in the table view, you need to signal that change back up to the view controller so that it can record the change to the data model. This means in turn that if the view needs to be recreated the view controller has the information it needs to rebuild whatever was in the table when your app entered the background.

I have put together a simple gitHub repository here: https://github.com/mpj-chandler/StateManagementDemo

This comprises a CustomTableViewController class which manages a standard UITableView populated with CustomTableViewCells. The custom cells contain three switch buttons, allowing the state of each cell to be represented by an array of Boolean values.

I created a delegate protocol for the cells such that if any of the switches is tripped, a signal is sent back to the 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 is registered to the CustomTableViewCellDelegate protocol, so that it can record the change in the model as follows:

// 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()

}

You can see here that the function is set up to output model changes to the console.

If you run the project in simulator and exit to the home screen and go back again you will see the state of the tableView cells is preserved, because the model reflects the changes that were made before the app entered the background.

Hope that helps.

Can't get State Restoration to work with Programmatic Navigation Controller

You can add an extension to your ViewController and make it conform to protocol UIViewControllerRestoration and implement the viewControllerWithRestorationIdentifierPath method.
In the ViewController's viewDidLoad function add restorationClass just like restorationIdentifer like

    override func viewDidLoad() {
super.viewDidLoad()
restorationIdentifier = "PickerVC"
restorationClass = ViewController.self
setupPicker()
}

extension ViewController: UIViewControllerRestoration {

static func viewController(withRestorationIdentifierPath identifierComponents: [Any], coder: NSCoder) -> UIViewController? {
let vc = ViewController()
return vc
}

}

Add this code in your ViewController class and delete the viewControllerWithRestorationIdentifierPath method that you have added in AppDelegate



Related Topics



Leave a reply



Submit