简体   繁体   中英

Swift CollectionViewCell showing Subview, which is NOT added

I have a collectionView, which returns 20 cells. The cells get their information from an api. If dates is true, the calendarImageView and the eventDatesLabel should be added/shown, else it shouldn't. The testprint is showing for the cells with dates==true and not showing for cells with dates==false. The cells are pretty big, so you only see two cells on iPhone 7 and to see the other cells, you have to scroll down. If a cell with dates==false is within the first cells, the calendarImageView and eventDatesLabel is not showing (as it should), but if a cell with dates==false is further down, it still gets displayed (while it shouldn't), even if the testprint is not showing, which would mean, that the views are not even added to the cell. How is this possible? Also the bannerView works the same. But there I have no problem at all, even if it is written exactly the same.

class HomeCell: UICollectionViewCell {

    func configure(with homeEvent: HomeEvent) {
        //configures the content of subviews with variables from homeEvent, which is the result of api request
        setupViews()
    }

    override func prepareForReuse() {
        //resets the variables for reuse
    }

    //here I defined all the labels, imageViews and so on...

    weak var homeControllerDelegate: HomeControllerDelegate?

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

    func setupViews() {
        addSubview(eventImageView)
        addSubview(genreLabel)
        if discount == 1 {
            addSubview(fixDiscountLabel)
        }
        else {
            addSubview(variableDiscountLabel)
        }
        addSubview(eventTitleLabel)
        addSubview(eventSubTitleLabel)
        if dates == true {
            print("test")
            addSubview(calendarImageView)
            addSubview(eventDatesLabel)
        }
        if banner == true {
            addSubview(bannerView)
            bannerView.addSubview(bannerLabelNormal)
            bannerView.addSubview(bannerLabelBold)
        }

        //here i set the constraints

        }
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        guard let cell = eventCollectionView.dequeueReusableCell(withReuseIdentifier: homeCellId, for: indexPath) as? HomeCell
            else {
                return UICollectionViewCell()
        }
        let event = homeEvents[indexPath.item] //homeEvents is an Array of Data for each cell. So every Element in this Array contains the variables needed to set the cells content, like dates, banner, ...
        cell.configure(with: event)
        cell.backgroundColor = UIColor(displayP3Red: 245/255, green: 245/255, blue: 245/255, alpha: 1)
        cell.layer.borderColor = UIColor(displayP3Red: 233/255, green: 233/255, blue: 233/255, alpha: 1).cgColor
        cell.layer.borderWidth = 1
        cell.layer.cornerRadius = 2
        cell.homeControllerDelegate = self
        return cell
    }

问题可能是由于该单元是可重用的,所以请尝试在prepareForReuse()方法中删除所有子视图。

You should also remove subviews based on whether they are in the view hierarchy, based on the data. As others have said, the collection view cells are reused. If at index 0 you had a cell where dates was true, and you added the calendarImageView and eventDatesLabel, then when that cell is offscreen it will be reused at another index, let's say index 10. So when it is being reused at index 10 the views you added before will still be there and you have to manage them. So you might be able to solve it by doing the following:

func setupViews() {
    addSubview(eventImageView)
    addSubview(genreLabel)
    if discount == 1 {
        addSubview(fixDiscountLabel)
    }
    else {
        addSubview(variableDiscountLabel)
    }
    addSubview(eventTitleLabel)
    addSubview(eventSubTitleLabel)
    if dates == true {
        print("test")
        addSubview(calendarImageView)
        addSubview(eventDatesLabel)
    } else {
        if subviews.contains(calendarImageView) {
            calendarImageView.removeFromSupeview()
        }

        if subviews.contains(eventDatesLabel) {
            eventDatesLabel.removeFromSuperview()
        }
    }
    if banner == true {
        addSubview(bannerView)
        bannerView.addSubview(bannerLabelNormal)
        bannerView.addSubview(bannerLabelBold)
    } else {
        if subviews.contains(bannerView) {
            bannerView.removeFromSuperview()
        }
    }
}

But honestly this code is a bit messy, there is too much logic for something that can be simplified with separation. I would personally suggest making two different cells (one that has your calendar views and one that has your banner views), register both of them to your collection view, and then based on your object dequeue the one that you actually need. In that way each cell will just have one set layout, and you don't have to manage cells as they are reused.

Add all the subviews at once in your setupViews method, then show/hide views for the required condition.

override init(frame: CGRect) {
    super.init(frame: frame)
    addSubview(eventImageView)
    addSubview(genreLabel)
    addSubview(fixDiscountLabel)
    addSubview(variableDiscountLabel)
    addSubview(eventTitleLabel)
    addSubview(eventSubTitleLabel)
    addSubview(calendarImageView)
    addSubview(eventDatesLabel)
    addSubview(bannerView)
    bannerView.addSubview(bannerLabelNormal)
    bannerView.addSubview(bannerLabelBold)
}

private func hideAllViews(){
    eventImageView.isHidden = true
    genreLabel.isHidden = true
    eventTitleLabel.isHidden = true
    eventSubTitleLabel.isHidden = true
    fixDiscountLabel.isHidden = true
    variableDiscountLabel.isHidden = true
    calendarImageView.isHidden = true
    eventDatesLabel.isHidden = true
    bannerView.isHidden = true
}

func setupViews() {
    hideAllViews()
    if discount == 1 {
        fixDiscountLabel.isHidden = false
    }
    else {
        variableDiscountLabel.isHidden = false
    }
    if dates == true {
        print("test")

        calendarImageView.isHidden = false
        eventDatesLabel.isHidden = false

    }
    if banner == true {
        bannerView.isHidden = false
    }

    //here i set the constraints

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM