有点困在同一个问题上好几天了。
我有一个ViewControllerA类,它充当CollectionView委托和数据源。CollectionView通过故事板连接。ViewControllerA类包含提供CollectionView的数据模型。
每当ViewControllerA第一次加载时,它会连接到数据库,并根据需要将信息加载到数据模型(userDictionary)中。一旦控制器加载了所有数据,它就会重新加载CollectionView,并触发同步方法来侦听数据库中的任何更改,从而相应地更新用户字典,并在CollectionView中重新加载相应的项。
到目前为止一切正常。
当我转换到任何不同的ViewController类(比如ViewControllerB类)时,我在prepareForSenderA中将用户字典的副本从ViewController a传递到ViewControllerB,并通过prepareForSenderB将其传递回ViewControllerA。
这是奇怪的行为。当我转换回ViewControllerA类时,CollectionView将使用传递给ViewControllerB的相同数据加载fine,但无法加载同步方法在ViewControllerA中观察到的任何新更改。
我知道同步方法仍然可以正常工作,因为当我在ViewControllerA中加载新数据时,它会在调试器中显示出来。我知道同一个控制器类中的userDictionary数据模型正在接收这些更新,因为一个didSet观察者正在打印userDictionary的最新状态。
奇怪的是,每当我在VisualSo操纵类中打印出数据模型的内容时,它就会打印出它在传递给VIEWSCONDERB类时存在的旧状态。即使didSet观察者刚刚证明了模型实际上是更新的!
就好像ViewControllerA类在某种程度上保留了对数据模型的引用,当它被传递给ViewControllerB时,当“模型”被传递时,不知何故“丢失”它对“自我”中的数据模型的引用。
另一个注意事项:如果我一直呆在ViewControllerA中,并且不来回传递userDictionary,我就不会再遇到这个问题。
下面的代码总结了我如何来回传递数据:
视图控制器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)
}
}
视图控制器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:在视图控制器A中启动
装载机观察到的项目数=9
来自DIDSET的userDictionary.count,9
同步器观察到newNumberOfItems=1
DIDSET=10的userDictionary.count(10=9+1)--通过
TEST=10的userDictionary.count(10=9+1)--通过
第二步:从A到B
viewControllerB.userDictArray=viewControllerA.userDictArray
第三步:从B到A
viewControllerA.userDictArray=viewControllerB.userDictArray
步骤4:观察调试器输出
来自DIDSET的userDictionary.count,10
同步器观察到newNumberOfItems=1
DIDSET=11的userDictionary.count(10=10+1)--通过
TEST中的userDictionary.count=10(10!=10+1--失败
(当diSet刚刚更新了userDictionary.count时,这一行是如何发生的?)
使用UUID的调试器输出:
步骤1:在视图控制器A中启动
装载机观察项目数量,A74593E1-1231-41BE-A5DF-693591F998E4
来自DIDSET的userDictionary.count,A74593E1-1231-41BE-A5DF-693591F998E4
同步器观察到新的项目数量,A74593E1-1231-41BE-A5DF-693591F998E4
来自DIDSET的userDictionary.count,A74593E1-1231-41BE-A5DF-693591F998E4
来自测试的userDictionary.count,A74593E1-1231-41BE-A5DF-693591F998E4
步骤4:观察调试器输出
来自DIDSET的userDictionary.count,A74593E1-1231-41BE-A5DF-693591F998E4
同步器观察到新的项目数量,A74593E1-1231-41BE-A5DF-693591F998E4
来自DIDSET的userDictionary.count,A74593E1-1231-41BE-A5DF-693591F998E4
来自测试的userDictionary.count,28D817D9-B53D-47D8-A3EF-2F7DDE6460FC
最佳答案
我真的认为你需要/想用一个“放松”的部分。
在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从视图控制器图标拖动到故事板中的
ViewControllerA
顶部的退出图标。给它一个segue标识符。现在,在
ViewControllerB
中,您可以调用:self.performSegue(withIdentifier: "unwindSegueBtoA", sender: self)
returnFromB()
中的ViewControllerA
函数将处理数据的传输。下面是一个基本示例:https://github.com/DonMag/DataPass
另一个(可能更好的)选择是创建一个“数据管理器”类,并从每个控制器设置/获取该类中的数据,而不是来回传递。
关于ios - CollectionView失去对数据模型的引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51503085/