swift - 当 UICollectionView 和 UICollectionViewCell 位于 XIB 文件中时,子视​​图为零

标签 swift uiview uicollectionview uicollectionviewcell xib

<强> Hi there! I've created a sample project that shows my problem exactly. Click to download!

我创建了一个包含 UICollectionViewCell 子类的应用程序,它包含一个 ImageView 作为 subview 。它还有一个包含 View 的 XIB 文件。

当我在直接嵌入 ViewControllerUICollectionView 中使用此 UICollectionViewCell 时,该单元工作得很好。以下是 WorkingViewController 的代码,其中包含注册单元的代码:

class WorkingViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
  @IBOutlet weak var collectionView: UICollectionView!

  override func viewDidLoad() {
    super.viewDidLoad()

    let cellNib = UINib(nibName: "ImageCell", bundle: nil)
    collectionView.register(cellNib, forCellWithReuseIdentifier: "ImageCell")

    collectionView.reloadData()
  }

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

  func randomInt(min: Int, max: Int) -> Int {
    return Int(arc4random_uniform(UInt32(max - min + 1))) + min
  }

  func numberOfSections(in collectionView: UICollectionView) -> Int {
    return 1
  }

  func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return 100
  }

  func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ImageCell", for: indexPath) as? ImageCell else {
      fatalError("Could not load cell")
    }

    let randomNumber = randomInt(min: 1, max: 10)
    cell.imageView.image = UIImage(named: "stockphoto\(randomNumber)")

    return cell
  }
}

现在将 Storyboard入口点移至BuggyViewController。这里的 UICollectionView 没有直接嵌入。它包含在还有一个 XIBUIView 中。这是该 View 的代码,包含之前注册的单元格:

class DetailView: UIView, UICollectionViewDelegate, UICollectionViewDataSource {
  @IBOutlet var contentView: UIView!
  @IBOutlet weak var collectionView: UICollectionView!

  override init(frame: CGRect) {
    super.init(frame: frame)

    setup()
  }

  required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)

    setup()
  }

  private func setup() {
    Bundle.main.loadNibNamed("DetailView", owner: self, options: nil)

    self.addSubview(self.contentView)
    self.contentView.frame = self.bounds
    self.autoresizingMask = [.flexibleWidth, .flexibleHeight]

    collectionView.delegate = self
    collectionView.dataSource = self

    let cellNib = UINib(nibName: "ImageCell", bundle: nil)
    collectionView.register(cellNib, forCellWithReuseIdentifier: "ImageCell")
    collectionView.register(ImageCell.self, forCellWithReuseIdentifier: "ImageCell")

    collectionView.reloadData()
  }

  func randomInt(min: Int, max: Int) -> Int {
    return Int(arc4random_uniform(UInt32(max - min + 1))) + min
  }

  func numberOfSections(in collectionView: UICollectionView) -> Int {
    return 1
  }

  func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return 100
  }

  func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ImageCell", for: indexPath) as? ImageCell else {
      fatalError("Could not load cell")
    }

    let randomNumber = randomInt(min: 1, max: 10)
    cell.imageView.image = UIImage(named: "stockphoto\(randomNumber)")

    return cell
  }
}

但这会导致 DetailView 第 55 行出现错误:

Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value

所以这里单元格的imageView突然为零,这让我觉得我在注册单元格或实例化它时做错了什么。但我就是无法解决它。

最佳答案

您应该删除注册单元类的行:

collectionView.register(ImageCell.self, forCellWithReuseIdentifier: "ImageCell")

事实上,您已经在 Nib 中定义了单元格,并且应该通过方法 func register(_ nib: UINib?, forCellWithReuseIdentifier identifier: String) 注册它。 。通过cellClass方法注册它会返回nil。

正如 Apple 文档所述:

If you previously registered a class or nib file with the same reuse identifier, the class you specify in the cellClass parameter replaces the old entry. You may specify nil for cellClass if you want to unregister the class from the specified reuse identifier.

这解释了为什么你的结果为零。

关于swift - 当 UICollectionView 和 UICollectionViewCell 位于 XIB 文件中时,子视​​图为零,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48581723/

相关文章:

ios - 具有粘性页脚 UIView 和动态高度内容的 UIScrollView

swift - 如何在不使用 SEGUE 的情况下在 View Controller 之间传递字符串

ios - 将实例化的 UIView 从 NIB 约束到其他 UIView

ios - 在 Swift 3 中无法调用非函数类型 'UICollectionView' 的值

ios - UICollectionView 神秘地延迟触摸直到滚动

ios - 使用 Swift 和 Firebase 更改用户电子邮件和密码

swift - CABasicAnimation 链接不起作用

ios - CollectionView 和 UISegmentedControl 错误

ios - 通过标签区分一个 UIButton

ios - 什么时候需要切换 rootViewController