现在在同一问题上停留了几天。
我有一个ViewControllerA类,它用作CollectionView委托和数据源。 CollectionView通过情节提要进行连接。 ViewControllerA类包含提供CollectionView的数据模型。
每次ViewControllerA首次加载时,它都会连接到数据库,并根据需要将信息加载到数据模型(userDictionary)中。一旦控制器加载了所有数据,它将重新加载CollectionView,并触发同步方法来侦听数据库中的任何更改,以相应地更新userDictionary,并重新加载collectionView中的各个项目。
到目前为止,一切正常。
当我过渡到其他不同的ViewController类时,例如说ViewControllerB类,我是将userDictionary的副本从ViewControllerA传递给prepareForSenderA中的ViewControllerB,然后通过prepareForSenderB传递回ViewControllerA。
这是奇怪的行为。当我过渡到ViewControllerA类时,CollectionView可以很好地使用传递给ViewControllerB的相同数据,但是无法加载同步方法在ViewControllerA中观察到的任何新更改。
我知道同步方法仍然可以正常工作,因为当我将其打印到ViewControllerA中时,所有新数据都会在调试器中显示。而且我知道我的同一个控制器类中的userDictionary数据模型正在接收这些更新,这是因为didSet观察程序正在打印出userDictionary的最新状态。
奇怪的是,每当我在ViewControllerA类中打印出数据模型的内容时,它就会打印出传递给ViewControllerB类时存在的模型的旧状态。即使didSet观察者刚刚证明该模型实际上已更新!
几乎就像ViewControllerA类以某种方式保留了对数据模型的引用(当它传递给ViewControllerB时一样),并且以某种方式“丢失”了对模型自身的引用(当该模型被传回时) 。
另一注:如果我一直呆在ViewControllerA中,并且不来回传递userDictionary,则不会再遇到此问题。
下面的代码总结了我如何来回传递数据:
View Controller A类:
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类:
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
}
}
}
打印结果:
步骤1:从View Controller A开始
步骤2:从A到B连续
viewControllerB.userDictArray = viewControllerA.userDictArray
第3步:从B到A的顺序
viewControllerA.userDictArray = viewControllerB.userDictArray
步骤4:观察调试器输出
使用UUID的调试器输出:
第1步:在View Controller A中启动
第4步:观察调试器输出
答案 0 :(得分:1)
我真的认为您需要/想要使用“放松”功能。
在ViewControllerA
中添加以下功能:
@IBAction func returnFromB(_ segue: UIStoryboardSegue) {
if let vcDest = segue.destination as? ViewControllerA,
let vcSource = segue.source as? ViewControllerB {
// pass userDictionary from VCB back to VCA
vcDest.userDictionary = vcSource.userDictionary
print("unwind segue from B")
}
}
然后,通过Ctrl-Drag将其从View Controller图标连接到情节提要中ViewControllerA
顶部的Exit图标。给它一个segue标识符。
现在,您可以在ViewControllerB
中致电:
self.performSegue(withIdentifier: "unwindSegueBtoA", sender: self)
,并且returnFromB()
中的ViewControllerA
函数将处理回传数据。
这是一个基本示例:https://github.com/DonMag/DataPass
另一个(可能更好)的选择是创建一个“数据管理器”类,并从每个控制器的该类中设置/获取数据,而不是来回传递。