Kind of stuck on the same problem now for a couple of days.
I have a ViewControllerA class that serves as a CollectionView delegate and datasource. The CollectionView is hooked up through a storyboard. ViewControllerA class contains the data model that feeds the CollectionView.
Whenever ViewControllerA loads for the first time, it connects to a database, and loads information as needed into a data model (userDictionary) . Once the controller loads all data, it reloads the CollectionView, and fires syncing methods that listen for any changes in the database, to update the userDictionary accordingly, and reload the respective items in the collectionView.
Everything works fine up to this point.
When I transition to any different ViewController class, say ViewControllerB class, I’m passing a copy of the userDictionary from ViewControllerA to ViewControllerB in prepareForSenderA, and passing it back to ViewControllerA through prepareForSenderB.
Here’s the strange behavior. When I transition back to ViewControllerA class, the CollectionView loads fine with the same data that was passed to ViewControllerB, but fails to load any new changes that the syncing method observes in ViewControllerA.
I know that the syncing methods are still working fine, because any new data is showing up in the debugger when I print it out as it’s loading in ViewControllerA. And I know that my userDictionary data model in the same controller class is receiving those updates because of a didSet observer that’s printing out the most up-to-date state of userDictionary.
And the odd thing is that whenever I print out the contents of the data model within ViewControllerA class, it prints out the old state of the model as it existed when it was passed to ViewControllerB class. Even though the didSet observer just proved that the model was actually updated!
It’s almost as if ViewControllerA class is somehow retaining a reference to the data model as it existed when it was passed over to ViewControllerB, and somehow “loses” its reference to the data model in “self” when that model gets passed back.
Another note: If I stay in ViewControllerA the whole time, and don’t pass the userDictionary back and forth, I don’t get this problem any more.
The code below sums up how I'm passing data back and forth:
View Controller A Class:
class ViewControllerA: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {
//MARK: Data Structures
var userDictionary = [[String: String]]() { didSet { print("userDictionary.count from DIDSET,", userDictionary.count)}}
//prints out: 9
//MARK: Initialization
override func viewDidLoad() {
self.loadUserDictionaryFromDatabase()
}
func loadUserDictionaryFromDatabase() {
//code that loads information from a database
//var objectInstance["name"] = firstName
//self.userDictionary.append(objectInstance)
print("loader observed numberOfItems", numberOfItems)
//...once data is fully loaded
self.syncDataFromDatabase()
}
func syncDataFromDatabase() {
//sync new data from database
//var newObjectInstance["newName"] = newFirstName
//self.userDictionary.append(newName)
print("syncer observed newNumberOfItems", newNumberOfItems)
}
//MARK: View Controller Transitions
@IBAction func segueAtoB(_ sender: Any) {
self.performSegue(withIdentifier: "segueAtoB", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
//Segue from VCA to VCB
if segue.identifier == "segueAtoB" {
let controller = segue.destination as! ViewControllerA
//Pass initialized userDictionary from VCA to VCB
controller.userDictionary = self.userDictionary
}
}
//MARK: Dummy Test Number of Items in UserDictionary
@IBAction func printMostUpToDateNumberofItemsInDictionary(_ sender: Any) {
print("userDictionary.count from TEST,", userDictionary.count)
}
}
View Controller B Class:
class ViewControllerB: UIViewController {
//MARK: Data Structures
var userDictionary = [[String: String]]()
//MARK: View Controller Transitions
@IBAction func segueBtoA(_ sender: Any) {
self.performSegue(withIdentifier: "segueBtoA", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
//1. Segue to Home-Screen Controller
if segue.identifier == "segueBtoA" {
let controller = segue.destination as! ViewControllerB
controller.userDictionary = self.userDictionary
}
}
}
Result of Prints:
Step 1: Start in View Controller A
- loader observed numberOfItems = 9
- userDictionary.count from DIDSET, 9
- syncer observed newNumberOfItems = 1
- userDictionary.count from DIDSET = 10 (10 = 9 + 1) -- PASS
- userDictionary.count from TEST = 10 (10 = 9 + 1) -- PASS
Step 2: Segue From A to B
viewControllerB.userDictArray = viewControllerA.userDictArray
Step 3: Segue From B to A
viewControllerA.userDictArray = viewControllerB.userDictArray
Step 4: Observe Debugger Output
- userDictionary.count from DIDSET, 10
- syncer observed newNumberOfItems = 1
- userDictionary.count from DIDSET = 11 (10 = 10 + 1) -- PASS
- userDictionary.count from TEST = 10 (10 != 10 + 1) -- FAIL (How is this line happening when diSet just updated userDictionary.count?)
Debugger output using UUID:
Step 1: Start in View Controller A
- loader observed numberOfItems, A74593E1-1231-41BE-A5DF-693591F998E4
- userDictionary.count from DIDSET, A74593E1-1231-41BE-A5DF-693591F998E4
- syncer observed newNumberOfItems, A74593E1-1231-41BE-A5DF-693591F998E4
- userDictionary.count from DIDSET, A74593E1-1231-41BE-A5DF-693591F998E4
- userDictionary.count from TEST, A74593E1-1231-41BE-A5DF-693591F998E4
Step 4: Observe Debugger Output
- userDictionary.count from DIDSET, A74593E1-1231-41BE-A5DF-693591F998E4
- syncer observed newNumberOfItems, A74593E1-1231-41BE-A5DF-693591F998E4
- userDictionary.count from DIDSET, A74593E1-1231-41BE-A5DF-693591F998E4
- userDictionary.count from TEST, 28D817D9-B53D-47D8-A3EF-2F7DDE6460FC