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

标签 ios swift xcode uiview uicollectionview

因此,我正在努力寻找新的方法来保持我的项目整洁,并且更易于我自己管理。

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

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

需要注意的一件事: Collection View 在应用程序首次启动时加载,这是应该的。 MenuActionLabel.text 导出设置为:'Hi'。

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

import UIKit

class UserMenu: UIView, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {

    struct Variables {
        static var myName = "Hi"
    }

    @IBOutlet weak var Collectioner: UICollectionView!

当我调用以下“ShowMe()”函数时,我得到了“coll: nil”的打印结果。

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

    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>)

并且 Collection View 闪烁,表明它已经重新加载。

那么,当我尝试从其他任何地方重新加载 Collection View 时,为什么返回 nil?

请帮忙。这让我疯狂。我已经尝试了所有我能想到的方法,并进行了大量寻找答案和解决方案的工作,并且乐于接受建议和学习。

我不确定我是否需要在启动时以某种方式“确认”IBOutlet,即使一切似乎都通过 StoryBoard 正确连接。

编辑 - 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

干杯,

贾斯汀。

最佳答案

让我们谈谈调用 UserMenu().ShowMe() 时会发生什么

  • 首先,调用 UserMenu() 并使用 init() 方法初始化一个新的 UserMenu 实例。
  • 其次,此实例将调用 ShowMe() 方法。

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

要修复它,您应该将 UserMenu 实例作为属性保留在 ViewControler 中(可以将其命名为 userMenu)。每次你想调用ShowMe()方法,它应该是userMenu.ShowMe()

编辑:将 Storyboard 中的用户菜单 View 连接到 @IBOutlet weak var userMenu: UserMenu! 并在下面使用我的代码。

class ViewController: UIViewController {

  @IBOutlet weak var 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()
  }
}

关于ios - UIView 类中的 CollectionView IBOutlet 返回 nil - 只是有时?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50822226/

相关文章:

ios - 在测验应用程序中突出显示正确答案

ios - 在 iOS 8+ 中使用什么字体显示这些 un​​icode 字符

ios - Watch Complication 导致 dyld : Symbol not found: _OBJC_CLASS_$_CLKFullColorImageProvider 崩溃

ios - Storyboard中错放的安全区域

ios - 如何根据collectionView中的条件隐藏textview及其高度?

iOS:使用客户的配置文件签署内部分发的应用程序

ios - 如何在 Swift 中从 Objective-C 访问 NSMutableArray

ios - Stripe iOS ruby

ios - 如何将字体永久添加到 Xcode

php - 空白(无)条目在 swift 4 中使用 alamofire 请求插入数据库。请解决它