在向DataSource添加值时,使用CollectionView的IBDesignable崩溃

时间:2018-06-07 20:14:38

标签: ios swift xcode interface-builder ibdesignable

我正在开发一个小UIView组件,在UICollectionView中显示主题标签,由于某些原因,我需要通过Interface Builder使其“可编辑”...因此,我做了{ {1}}。

一切正常,除非在IBDesignable我试图将对象附加到prepareForInterfaceBuilder,因此列表会在故事板中的某处集成时显示内容。

到达datasource行,这会崩溃。如果我删除了这一行,那么在故事板上正确呈现视图,如果我再次添加它 - >崩溃...在我调试之后,似乎IB无法访问此属性或看到它为零。

我无法调试任何,Xcode不允许我调试Storyboard中的选定视图>编辑(在macOS Mojave上导致错误)。我的观点没有self.hashtags.append(hashtag),并且都需要.xib

我还检查了Console.app中的日志,但没有。以下是故事板给出的主要错误消息:

Main.storyboard:错误:IB Designables:无法呈现和更新PublishViewController(tSg-9E-Vz3)的自动布局状态:代理引发了异常。

代码(重要的)

init

设置功能()

@IBDesignable
class HashtagView: UIView {

    @IBOutlet weak var height: NSLayoutConstraint?

    var collectionView: UICollectionView = {
        let layout = UICollectionViewFlowLayout()
        let view = UICollectionView(frame: .zero, collectionViewLayout: layout)
        return view
    }()

    open var hashtags: [HashTag] = []

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

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

    override func prepareForInterfaceBuilder() {
        super.prepareForInterfaceBuilder()
        setup()

        self.hashtags.append(HashTag(word: "it works")) < CRASH
        self.collectionView.reloadData()
        self.layoutSubviews()
    }
}

1 个答案:

答案 0 :(得分:1)

所以设置肯定是相关的。显然,IB正在崩溃,试图为你的UICollectionView加载你的单元格。它无法加载Nib文件。它与它同时崩溃的追加没有任何关系。我复制了你的问题,然后用代码创建了一个单元格,一切正常。如果这有助于解答您的问题,请告诉我。所有必需的代码都在那里。

import UIKit

struct HashTag {
    var word:String?
}

class HashCollectionViewCell: UICollectionViewCell {

    lazy var wordLabel : UILabel = {
        let lbl = UILabel(frame: self.bounds)
        lbl.font = UIFont.systemFont(ofSize: 17)
        lbl.textColor = .black
        return lbl
    }()

    override init(frame: CGRect) {
        super.init(frame: frame)
        self.addSubview(wordLabel)
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        self.addSubview(wordLabel)
    }

    func configureWithTag(tag:HashTag) {
        wordLabel.text = tag.word
    }

}

@IBDesignable
class HashTagView: UIView {

    private var sizingLabel = UILabel(frame: .zero)
   lazy var collectionView: UICollectionView = {
        let layout = UICollectionViewFlowLayout()
        let view = UICollectionView(frame: self.bounds, collectionViewLayout: layout)
        view.autoresizingMask = [.flexibleWidth,.flexibleHeight]
        return view
    }()

    var hashtags: [HashTag] = [HashTag(word: "this works")]

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

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


    func setup(){
        sizingLabel.font = UIFont.systemFont(ofSize: 17)

        self.addSubview(collectionView)
        collectionView.frame = self.bounds
        collectionView.backgroundColor = self.backgroundColor
        collectionView.register(HashCollectionViewCell.self, forCellWithReuseIdentifier: "hashCell")
        self.addSubview(collectionView)

        for x in 0..<10{
            addHashTag(tag: "This is more \(x)")
        }

        collectionView.delegate = self
        collectionView.dataSource = self
    }

    func addHashTag(tag:String){
        let newHash = HashTag(word: tag)
        self.hashtags.append(newHash)
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        collectionView.frame = self.bounds
    }

}

extension HashTagView: UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewDelegateFlowLayout{
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return hashtags.count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "hashCell", for: indexPath) as? HashCollectionViewCell{
            let tag = self.hashtags[indexPath.item]
            cell.configureWithTag(tag: tag)
            return cell
        }
        return UICollectionViewCell()
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        let tag = self.hashtags[indexPath.item]
        sizingLabel.text = tag.word
        sizingLabel.sizeToFit()
        return sizingLabel.frame.size
    }
}

<强>结果: enter image description here

2)您可以将nib加载到以编程方式创建的单元格中,它将起作用。对于作为编程单元格的部分,示例将如下所示。

在单元格内使用nib的View扩展名的单元格代码:

extension UIView {
    func loadNib() -> UIView {
        let bundle = Bundle(for: type(of: self))
        let nibName = type(of: self).description().components(separatedBy: ".").last!
        let nib = UINib(nibName: nibName, bundle: bundle)
        return nib.instantiate(withOwner: self, options: nil).first as! UIView
    }
}

class HashCollectionViewCell: UICollectionViewCell {

    var hashTagNib : HashTagNibView?

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

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

    func setup(){
        if let htn = HashTagNibView().loadNib() as? HashTagNibView{
            hashTagNib = htn
            hashTagNib?.frame = self.bounds
            hashTagNib?.autoresizingMask = [.flexibleWidth,.flexibleHeight]
           self.addSubview(htn)
        }

    }

    func configureWithTag(tag:HashTag) {
        if let htn = hashTagNib{
            htn.hashTagButtonLabel.setTitle(tag.word, for: .normal)
        }
    }

Nib设置如下所示: nib

根据你正在做的事情,这可能会给你更大的灵活性,结果是相似的,除了在我使用UIButton的nib例子中。 enter image description here