自定义 CollectionViewCell 的 ImageView 在应该配置时为 nil

ImageView of a custom CollectionViewCell is nil when it should be configured

我有一个 tableViewCell 和一个 collectionViewcollectionView's cells 是自定义的,它们只包含一个 imageView

Here is my test project

这是我的 CollectionView class:

中的 DataSource 个必需方法
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ImageCell", for: indexPath) as! ImageCell

    let image = UIImage(named: listItems[indexPath.row])
    cell.testImageView.image = image

    return cell
}

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

当我尝试为单元格的 imageView 设置图像时,我得到了这个 error:

fatal error: unexpectedly found nil while unwrapping an Optional value

我已经检查过 image,它不是 nil,但是 testImageView 是,当我尝试将图像设置为 collectionViewCell 的 testImageView 时出现此错误。 我该如何解决? 编辑1

这是从 tableViewController 调用的方法来填充 collectionView 的 listItem

func load(listItem: [String]) {
    self.listItems = listItem
    reloadData()

}

此外,如果我使用此代码从 collectionView cellForItemAt indexPath 中删除代码,一切正常

let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ImageCell", for: indexPath)
let imageView = UIImageView(image:UIImage(named: listItems[indexPath.row]))

cell.backgroundView = imageView

可能 "testImageView" 出口变量未从界面构建器连接,或者没有具有 reuseIdentifier "ImageCell" 的 CollectionViewCell。使用 LLDB po 命令检查 cell 是否为 nil。

你弄错了你的两个视图控制器。您的 IB 插座连接到不同视图控制器中的单元格。我的意思是你可以在不同的控制器中有多个视图连接到同一个 IBOutlet,但在你的情况下,第一个加载的视图没有连接,所以这就是它崩溃的原因。

这是您的插座所连接的电池。

这是您正在尝试加载(但没有将 IBOutlet 连接到图像视图):

以防万一您想使用代码..

import UIKit


class ImageCell : UICollectionViewCell {

    private var imageView: UIImageView!
    private var descLabel: UILabel!

    public var image: UIImage? {
        get {
            return self.imageView.image
        }

        set {
            self.imageView.image = newValue
        }
    }

    public var imageDesc: String? {
        get {
            return self.descLabel.text
        }

        set {
            self.descLabel.text = newValue
        }
    }

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

        self.initControls()
        self.setTheme()
        self.doLayout()
    }

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

        self.initControls()
        self.setTheme()
        self.doLayout()
    }

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

    func initControls() {
        self.imageView = UIImageView()
        self.descLabel = UILabel()
    }

    func setTheme() {
        self.imageView.contentMode = .scaleAspectFit

        self.descLabel.numberOfLines = 1
        self.descLabel.lineBreakMode = .byWordWrapping
        self.descLabel.textAlignment = .center
        self.descLabel.textColor = UIColor.black

        self.contentView.backgroundColor = UIColor.white
    }

    func doLayout() {
        self.contentView.addSubview(self.imageView)
        self.contentView.addSubview(self.descLabel)

        self.imageView.leftAnchor.constraint(equalTo: self.contentView.leftAnchor, constant: 5).isActive = true
        self.imageView.rightAnchor.constraint(equalTo: self.contentView.rightAnchor, constant: -5).isActive = true
        self.imageView.topAnchor.constraint(equalTo: self.contentView.topAnchor, constant: 0).isActive = true

        self.descLabel.leftAnchor.constraint(equalTo: self.contentView.leftAnchor, constant: 5).isActive = true
        self.descLabel.rightAnchor.constraint(equalTo: self.contentView.rightAnchor, constant: -5).isActive = true
        self.descLabel.topAnchor.constraint(equalTo: self.imageView.bottomAnchor, constant: 5).isActive = true
        self.descLabel.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor, constant: -5).isActive = true

        for view in self.contentView.subviews {
            view.translatesAutoresizingMaskIntoConstraints = false
        }
    }
}


class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {

    private var collectionView: UICollectionView!
    private var dataSource: Array<String>!

    override func viewDidLoad() {
        super.viewDidLoad()

        self.initDataSource()
        self.initControls()
        self.setTheme()
        self.registerClasses()
        self.doLayout()
    }

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

    func initDataSource() {
        self.dataSource = ["Image1", "Image2", "Image3", "Image4", "Image5", "Image6"]
    }

    func initControls() {
        let layout = UICollectionViewFlowLayout()
        layout.itemSize = CGSize(width: 117, height: 125)
        layout.invalidateLayout()
        self.collectionView = UICollectionView(frame: self.view.frame, collectionViewLayout: layout)
        self.collectionView.delegate = self
        self.collectionView.dataSource = self
    }

    func setTheme() {
        self.collectionView.backgroundColor = UIColor.clear

        self.edgesForExtendedLayout = UIRectEdge(rawValue: 0)
        self.view.backgroundColor = UIColor.blue
    }

    func registerClasses() {
        self.collectionView.register(ImageCell.self, forCellWithReuseIdentifier: "ImageCellIdentifier")
    }

    func doLayout() {
        self.view.addSubview(self.collectionView)

        self.collectionView.leftAnchor.constraint(equalTo: self.view.leftAnchor).isActive = true
        self.collectionView.rightAnchor.constraint(equalTo: self.view.rightAnchor).isActive = true
        self.collectionView.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true
        self.collectionView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor).isActive = true

        for view in self.view.subviews {
            view.translatesAutoresizingMaskIntoConstraints = false
        }
    }

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

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return self.dataSource.count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ImageCellIdentifier", for: indexPath) as! ImageCell

        let imageName = self.dataSource[indexPath.row]
        cell.image = UIImage(named: imageName)
        cell.imageDesc = imageName

        return cell
    }
}

http://imgur.com/o7O7Plw