我的类中有一个UICollectionView声明为 @IBOutlet弱varartworkCollectionView:UICollectionView!
在此类中,有一个委托方法被其他两个View Controller调用,其中一个VC是一个弹出窗口,另一个是普通的VC。
委托方法从数据库中获取一些数据,然后更新在闭包内部调用的集合视图: self.artworkCollectionView.reloadData()
当弹出的VC调用委托方法时,一切都很好。但是,当普通VC到达self.artworkCollectionView.reloadData()时,委托方法被常规VC调用时,它将收到臭名昭著的致命错误:意外地找到nil,同时隐式展开了Optional值。
我已经检查了对单元复用ID的所有引用,并且都正确。我怀疑因为UICollectionView被声明为弱变量,所以当我从当前类转到弹出窗口,然后弹出窗口调用委托方法时,引用不会丢失,而是当我从当前类转到正常对象时VC,然后普通的VC调用委托方法,丢失了对我的弱var的引用,因此它被“视为”为nil。
@IBOutlet weak var artworkCollectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
// Set up
artworkCollectionView.dataSource = self
artworkCollectionView.delegate = self
artworkCollectionView.isUserInteractionEnabled = true
artworkCollectionView.allowsSelection = true
artworkCollectionView.register(UINib(nibName:
"MyCollectionViewCell", bundle: nil),
forCellWithReuseIdentifier: "cell")
}
// delegate method
func reloadCollections() {
retrieveAlbumRatings { (isAlbum) in
if isAlbum {
self.retrieveAlbumData(completion: { (isFinished) in
if isFinished {
// Reload collection views
self.artworkCollectionView.reloadData()
}
})
}
}
}
如果我是对的,我的问题是:如何给弱varartworkCollectionView:UICollectionView!一个强引用,以便它不会在从当前类到常规VC以及返回的流中丢失?
编辑:这是我到目前为止所尝试的:
从出口声明中删除“弱”,使其成为:@IBOutlet var ArtworkCollectionView:UICollectionView! 但是我遇到了同样的错误
我通过override performSegue将artworkCollectionView传递给了普通的VC,然后将其作为委托方法的参数传递回去。这不会给我致命错误,但也不会重新加载UICollectionView,因为我认为无论如何,对UICollectionView出口的弱引用都丢失了。
感谢您的帮助(免责声明:我对Swift还是很陌生。)
答案 0 :(得分:0)
在此类中,有一个委托方法,其他两个调用 View Controllers,这些VC之一是弹出窗口,另一个是 普通的VC。
委托方法从数据库中获取一些数据,然后进行更新 集合视图在闭包内部调用: self.artworkCollectionView.reloadData()
UICollectionView
会用该数据更新。您的问题如下:
我通过override将artworkCollectionView传递给了普通的VC performSegue,然后将其作为委托的参数传递回去 方法。这不会给我致命错误,但也不会给我致命错误 重新加载UICollectionView,因为我认为无论如何弱 对UICollectionView出口的引用丢失。 除非您有充分的理由这样做,否则在大多数情况下,您不应该像这样传递任何东西(我看不到)。
您想在这里分开关注。您必须仔细考虑要在VC之间传递的内容,以避免在它们之间产生怪异的依赖关系。我不会通过插座的原因有很多,首先是,如果您决定更改插座,那么现在必须跟踪多个VC中的插座。第二个原因是它需要太多的精神体操来跟踪插座的状态,因为它在各处无处不在。还只能保证将插座设置在生命周期的某些阶段。例如,如果您从prepareForSegue:sender:
中的序列中检索目标VC并尝试在此时引用出口,则它们将全部为零,因为尚未设置它们。
这些都是很好的理由,为什么包含以上代码的VC应该是(也是唯一一个)对artworkCollectionView
中显示的内容和时间进行控制的人。这里的问题是您如何解决此问题,而不是让弹出窗口或普通VC调用委托方法,或者做一些奇怪的事情,例如将插座从一个VC传递到另一个VC,而只是传递数据。
最简单的示例是:
parentViewController
或
presentingViewController
获取对原始VC的引用。UIButton
来关闭而不是为他们这样做)。viewWillAppear
使其将数据内容加载到
当时UICollectionView
。我认为没有理由为什么要在原始VC之外传递任何出口,而这些出口应该是管理它的那个。
答案 1 :(得分:0)
简短的回答:不要那样做。您应该将视图控制器的视图视为私有。您应该在视图控制器中添加一个方法,其他对象会调用该方法来告诉它重新加载其集合视图。
更长的答案是,只要视图控制器在屏幕上,视图控制器的集合视图就应该保留。听起来您对对象生命周期以及ARC的工作原理没有很深入的了解。您应该阅读并做一些练习,直到您对它有所了解为止。
尝试这样的事情:
//Make artworkCollectionView a normal weak var, not implicitly unwrapped.
//You'll need to change your other code to unwrap it every time you use it.
@IBOutlet weak var artworkCollectionView: UICollectionView?
...
func reloadCollections() {
retrieveAlbumRatings { (isAlbum) in
if isAlbum {
//The construct `[weak self]` below is called a capture list
self.retrieveAlbumData(completion: { [weak self] (isFinished) in
guard let weakSelf = self else {
print("self is nil");
return
}
}
if isFinished {
// Reload collection views
guard let collectionView = weakSelf.artworkCollectionView else {
print("collectionView is nil!")
return
}
collectionView.reloadData()
})
}
}
}