Swift 在委托方法中引用时,弱var出口丢失(=零)

Swift 在委托方法中引用时,弱var出口丢失(=零),swift,Swift,我的类中有一个UICollectionView声明为 @IBOutlet弱var artworkCollectionView:UICollectionView 在这个类中,有一个委托方法被另外两个视图控制器调用,其中一个是弹出窗口,另一个是普通的VC 委托方法从数据库中获取一些数据,然后更新在闭包内调用的集合视图: self.artworkCollectionView.reloadData() 当弹出式VC调用委托方法时,一切都很好。但是当委托方法到达self.artworkCollection

我的类中有一个UICollectionView声明为 @IBOutlet弱var artworkCollectionView:UICollectionView

在这个类中,有一个委托方法被另外两个视图控制器调用,其中一个是弹出窗口,另一个是普通的VC

委托方法从数据库中获取一些数据,然后更新在闭包内调用的集合视图: self.artworkCollectionView.reloadData()

当弹出式VC调用委托方法时,一切都很好。但是当委托方法到达self.artworkCollectionView.reloadData()时被普通VC调用时,它会得到一个臭名昭著的致命错误:在隐式展开可选值时意外发现nil

我已经检查了所有对cell reuseIdentifier的引用,并且都是正确的。我怀疑,由于UICollectionView被声明为弱var,当我从当前类转到弹出窗口,然后弹出窗口调用委托方法时,引用没有丢失,但当我从当前类转到普通VC,然后普通VC调用委托方法时,对我的弱var的引用丢失,因此它被“看到”零

如果我是对的,我的问题是:我如何给出弱var artworkCollectionView:UICollectionView!一个强大的引用,这样它就不会在从当前类到普通VC的流中丢失

编辑:以下是我到目前为止尝试的内容:

  • 从出口声明中删除“弱”,使其成为:@IBOutlet var artworkCollectionView:UICollectionView! 但我也犯了同样的错误

  • 我通过override performSegue将artworkCollectionView传递给普通VC,然后将其作为委托方法的参数传回。这不会给我致命错误,但也不会重新加载UICollectionView,因为我认为无论如何,对UICollectionView出口的弱引用都会丢失

  • 感谢您的帮助(免责声明:我对Swift非常陌生)

    在这个类中,有一个委托方法被另两个委托方法调用 视图控制器,其中一个是弹出窗口,另一个是 正常VC

    委托方法从数据库中获取一些数据,然后进行更新 在闭包内调用的集合视图: self.artworkCollectionView.reloadData()

  • 流程似乎是,您有一个包含上述代码的VC,该VC可以打开一个弹出窗口,或者只是执行一个标准的“普通VC”推送序列
  • 您希望在弹出式VC或普通VC中执行某些操作,加载一些数据,然后当用户被引导回原始VC时,
    UICollectionView
    将使用该数据更新
  • 您的问题如下:

    我通过覆盖将artworkCollectionView传递给普通VC performsgue,然后将其作为委托的参数传回 方法。这并没有给我致命的错误,但也没有 重新加载UICollectionView,因为我认为不管怎样 对UICollectionView插座的引用丢失。 在大多数情况下,你不应该像这样到处传递任何东西,除非你有很好的理由这样做(我看不到)

    你需要在这里分离关注点。你必须仔细考虑你想在风投之间传递什么,以避免他们之间产生奇怪的依赖关系。出于多种原因,我不会通过门店,第一个原因是,如果你决定改变它,你现在必须在多个风投中跟踪该门店。第二,它需要太多的精神体操来跟踪出口的状态,因为它到处都在传递。插座也仅保证在生命周期的某些阶段设置。例如,如果您从
    prepareforsgue:sender:
    中的segue中检索目标VC,并尝试引用当时的出口,它们将全部为零,因为它们尚未设置

    这些都是包含上述代码的VC应该(也是唯一一个)控制在
    artworkCollectionView
    中显示的内容以及显示时间的原因。这里的问题是如何处理这个问题,而不是让弹出窗口或普通VC调用委托方法,或者做一些奇怪的事情,比如从一个VC传递出口到另一个VC,而是传递数据

    最简单的例子是:

  • 弹出式VC和普通VC调用一些代码来实际获取 数据
  • 然后取决于你是如何切换到弹出的VC或 从原始VC中选择普通VC,使用
    parentViewController
    presentingViewController
    获取对原始VC的引用
  • 通过该引用将数据设置到原始VC中
  • 如有必要,关闭弹出窗口VC或普通VC(取决于您的特定应用程序,可能您希望用户按下
    ui按钮来关闭,而不是为他们这样做)
  • 当原始VC重新出现时,向生命周期方法添加一些代码,如
    视图将出现
    以将数据内容加载到 当时的UICollectionView
  • 我看不出有什么理由让你在管理它的最初的VC之外通过任何渠道

    在这个类中,有一个委托方法被另两个委托方法调用 视图控制器,其中一个是弹出窗口,另一个是 正常VC

    委托方法从数据库中获取一些数据,然后进行更新 在闭包内调用的集合视图: self.artworkCollectionView.reloadData()

  • 流程似乎是,您有一个包含上述代码的VC,该VC可以打开一个弹出窗口,或者只是执行一个标准的“普通VC”推送序列
  • 如果您希望在弹出的VC或普通VC中执行某些操作,请加载一些数据,然后在用户被定向返回时执行
    @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()
    
                    }
                })
            }
        }
    }
    
    //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()
                })
            }
        }
    }