簡體   English   中英

UICollectionView 在項目大小為自動並顯示 header 時崩潰

[英]UICollectionView crashes when item size is automatic and header is shown

當我想將 UICollectionView 的estimatedItemSize屬性設置為UICollectionView並同時顯示UICollectionViewFlowLayout.automaticSize部分時,我遇到了一個奇怪的錯誤。

使用以下代碼,應用程序可以正確顯示UICollectionView 但是,一旦用戶在UICollectionView上滾動,應用程序會因遞歸調用 function updateVisibleCellsNow而崩潰。

我通過將estimatedItemSizeautomaticSize設置為none從另一個 StackOverflow 問題中找到了解決方法。 但是,我想保留在UICollectionViewCell中設置的自動布局功能,而不是自己計算單元格高度。 有沒有更好的解決方案? 謝謝你。

在此處輸入圖像描述

這是我關於 ViewController 的代碼

import UIKit
class DemoCollectionViewController: UIViewController {
    
    lazy private var collectionView: UICollectionView = { [weak self] in
        guard let strongSelf = self else { return UICollectionView() }
        
        // Setup of `UICollectionViewFlowLayout`
        let flowLayout = UICollectionViewFlowLayout()
        

        // ********* This is the line that causes crash *********
        flowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
        // ******************************************************

        flowLayout.headerReferenceSize = CGSize(width: getScreenWidth(), height: 44.0)
        flowLayout.sectionHeadersPinToVisibleBounds = true
        
        // Setup of `UICollectionView`
        let collectionView = UICollectionView(frame: .zero, collectionViewLayout: flowLayout).disableFrameToAutoLayout()
        collectionView.dataSource = strongSelf
        collectionView.register(ProfileThumbnailCollectionViewCell.self, forCellWithReuseIdentifier: "cellId")
        collectionView.register(UICollectionReusableView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "headerId")
        
        return collectionView
    }()
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Setup of the UICollectionView
        view.addSubview(collectionView)
        NSLayoutConstraint.activate([
            collectionView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
            collectionView.rightAnchor.constraint(equalTo: view.safeAreaLayoutGuide.rightAnchor),
            collectionView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
            collectionView.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor),
        ])
    }
}

extension DemoCollectionViewController: UICollectionViewDataSource {
    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 10
    }
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 20
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cellId", for: indexPath) as! ProfileThumbnailCollectionViewCell
        cell.contentView.backgroundColor = .yellow
        return cell
    }
    
    func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {

        switch kind {
        case UICollectionView.elementKindSectionHeader:
            let supplementaryView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "headerId", for: indexPath)
            supplementaryView.backgroundColor = .red
            return supplementaryView
        default:
            return UICollectionReusableView()
        }
    }
}

這是我關於ProfileThumbnailCollectionViewCell的代碼:

class ProfileThumbnailCollectionViewCell: UICollectionViewCell {
    
    private let profileThumbnailImageView: UIImageView = {
        let profileThumbnailImageView = UIImageView()
        profileThumbnailImageView.translatesAutoresizingMaskIntoConstraints = false
        profileThumbnailImageView.backgroundColor = .red
        profileThumbnailImageView.layer.cornerRadius = 60
        profileThumbnailImageView.layer.masksToBounds = true
        return profileThumbnailImageView
    }()
    
    private let editPenButton: UIButton = {
        let editPenButton = UIButton()
        editPenButton.translatesAutoresizingMaskIntoConstraints = false
        editPenButton.backgroundColor = .mainGreen
        editPenButton.layer.cornerRadius = 16
        editPenButton.layer.masksToBounds = true
        return editPenButton
    }()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        // Content View
        contentView.backgroundColor = .yellow
        NSLayoutConstraint.activate([
            contentView.widthAnchor.constraint(equalToConstant: UIScreen.main.bounds.width)
        ])
        
        // Profile Thumbnail ImageView
        contentView.addSubview(profileThumbnailImageView)
        NSLayoutConstraint.activate([
            profileThumbnailImageView.centerXAnchor.constraint(equalTo: contentView.centerXAnchor),
            profileThumbnailImageView.widthAnchor.constraint(equalToConstant: 120),
            profileThumbnailImageView.heightAnchor.constraint(equalToConstant: 120),
            profileThumbnailImageView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 25),
            profileThumbnailImageView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -25)
        ])
        
        // Edit thumbnail pen ImageView
        contentView.addSubview(editPenButton)
        NSLayoutConstraint.activate([
            editPenButton.widthAnchor.constraint(equalToConstant: 32),
            editPenButton.heightAnchor.constraint(equalToConstant: 32),
            editPenButton.rightAnchor.constraint(equalTo: contentView.rightAnchor),
            editPenButton.rightAnchor.constraint(equalTo: contentView.rightAnchor)
        ])
    }
    
    required init?(coder: NSCoder) {
        fatalError("This class should be inited from code instead of a nib file; init(coder:) has not been implemented")
    }
}

在 ViewDidLoad 中調用 registerNib

func registerNib(){
 let nib = UINib(nibName: "ProfileThumbnailCollectionViewCell", bundle: nil)
 self.collectionView.register(nib, forCellWithReuseIdentifier: "ProfileThumbnailCollectionViewCell")
}

在調查了幾個小時后,我無意中找到了一個變通的解決方案,但肯定這不應該被視為最終解決方案。

class ProfileThumbnailCollectionViewCell: UICollectionViewCell {
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        // Content View
        contentView.backgroundColor = .yellow

        // ******** This is the weird point ********
        let targetCellWidth = UIScreen.main.bounds.width - 1


        NSLayoutConstraint.activate([
            contentView.widthAnchor.constraint(equalToConstant: targetCellWidth)
        ])
    }
}
    

UICollectionView不會拋出任何錯誤,並正確顯示 header 視圖和UICollectionView

如果您對這種情況有任何想法,請在此處留下您的評論。 非常感謝您的信息! 謝謝!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM