UIView类中的CollectionView IBOutlet返回nil - 有时只返回?

时间:2018-06-12 16:59:27

标签: ios swift xcode uiview uicollectionview

所以我试图找到保持项目清洁的新方法,并且更容易为自己管理。

我希望这样做的方法是将关系中的所有内容保存在自己的swift文件中,然后在需要时调用它。

我会尽力布置我的问题,但如果屏幕截图有帮助,或者您需要任何其他信息,我会尽力提供。

需要注意的一点是:应用程序首次启动时会加载集合视图。而MenuActionLabel.text插座设置为:'嗨'。

但是当我尝试调用ShowMe()时,CollectionView没有重新加载,而是崩溃了,因为Collectioner返回了nil可选。

import UIKit

class UserMenu: UIView, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {

    struct Variables {
        static var myName = "Hi"
    }

    @IBOutlet weak var Collectioner: UICollectionView!

当我打电话给以下' ShowMe()'功能,我打印出" coll:nil"。

我通过' UserMenu()调用ViewController.swift中的函数.ShowMe()'

    func ShowMe() {
        Variables.myName = "Justin"
        print("coll: \(self.Collectioner)")
        //Collectioner.reloadData()
        //^---- causes error - see didSelectItem for my problem...
        //returns nil optional...? Why?
    }

    //testing to find errors
    func numberOfSections(in collectionView: UICollectionView) -> Int {
        if collectionView == Collectioner {
            return 1
        } else {
            return 0
        }
    }

    //testing to find errors
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
            if collectionView == Collectioner {
                return 1
            } else {
                return 0
            }
        }

    //testing to find errors
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        if collectionView == Collectioner {
            let Cell:UserMenuCell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath as IndexPath) as! UserMenuCell
            Cell.MenuActionLabel.text = "\(Variables.myName)"
            return Cell
        } else {
            let Cell:UserMenuCell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath as IndexPath) as! UserMenuCell
            return Cell
        }
    }

    //testing to find errors
    func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
        cell.alpha = 0
        UIView.animate(withDuration: 0.8) {
            cell.alpha = 1
        }
    }

    //testing to find errors
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        if collectionView == Collectioner {
            return CGSize(width: Collectioner.frame.width, height: 50)
        } else {
            return CGSize(width: Collectioner.frame.width, height: 50)
        }
    }

    //testing to find errors
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
        if collectionView == Collectioner {
            return 0
        } else {
            return 0
        }
    }

我的困惑在这里出现:

    /*
    When I tap on the cell:
    1. The collection view reloads, and the updated data is shown.

    2. Yet... if I call reloadData from elsewhere,
       the Collectioner outlet returns as an optional nil?
    */

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        if collectionView == Collectioner {
            print(collectionView)
            print(" ")
            print(Collectioner)
            print(" ")
            collectionView.reloadData()
        }
    }

}

didSelectItemAt的打印输出是:

<UICollectionView: 0x7fd13103a000; frame = (0 0; 314 716); clipsToBounds = YES; autoresize = RM+BM; gestureRecognizers = <NSArray: 0x60c000242a00>; layer = <CALayer: 0x60c00022d140>; contentOffset: {0, 0}; contentSize: {314, 50}; adjustedContentInset: {0, 0, 0, 0}> collection view layout: <UICollectionViewFlowLayout: 0x7fd12ef1b450>

some(<UICollectionView: 0x7fd13103a000; frame = (0 0; 314 716); clipsToBounds = YES; autoresize = RM+BM; gestureRecognizers = <NSArray: 0x60c000242a00>; layer = <CALayer: 0x60c00022d140>; contentOffset: {0, 0}; contentSize: {314, 50}; adjustedContentInset: {0, 0, 0, 0}> collection view layout: <UICollectionViewFlowLayout: 0x7fd12ef1b450>)

集合视图闪烁,表示已重新加载。

当我尝试从其他地方重新加载集合视图时,为什么它会返回nil?

请帮忙。它让我发疯了。我已经尝试了所有我能想到的东西,并且已经做了很多寻找答案,解决方案并且愿意接受建议和学习。

我不确定我是否需要以某种方式确认&#39;即使所有内容都通过StoryBoard正确连接,也可以在发布时使用IBOutlet。

编辑 - ViewController.swift:

import UIKit

class ViewController: UIViewController {

    let userMenu = UserMenu()

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    @IBOutlet weak var button: UIButton!
    @IBAction func button(_ sender: Any) {
        print("Tapped Button")
        UserMenu().ShowMe()
    }

}
编辑 - Heirachy fig 1

干杯,

贾斯汀。

1 个答案:

答案 0 :(得分:2)

请谈谈致电<__main__.Foo object at 0x03B21110> <__main__.Foo object at 0x03AFB5B0> <__main__.Foo object at 0x03B21150>

时会发生什么
  • 首先,调用UserMenu().ShowMe()并使用UserMenu()方法初始化新的UserMenu实例。
  • 其次,此实例将调用init()方法。

你为什么会崩溃? - 因为ShowMe()实例是按默认UserMenu方法初始化的,并且没有从Storyboard加载任何内容。当然,在这种情况下,init将为Collectioner并导致崩溃。

要修复它,您应该将nil实例保留在UserMenu内作为属性(可能将其命名为ViewControler)。每次要调用userMenu方法时,都应为ShowMe()

编辑:将用户菜单视图从故事板连接到userMenu.ShowMe()并使用下面的代码。

@IBOutlet weak var userMenu: UserMenu!