iosswiftuicollectionviewuicollectionreusableview

How to change label text place in collectionveiw header at runtime?


this is screenshot(image) of my viewcontrollerI'm using collectionview and placed label in header, header and label created in storyboard I want to change label text at runtime.

I know I can do it in viewForSupplementaryElementOfKind of collectionview but I want it in viewdidload method

my code is as below

Controller code


class DeleteViewController: UIViewController,UICollectionViewDelegate,UICollectionViewDataSource {
    
    @IBOutlet weak var collectionView: UICollectionView!
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 1
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
        cell.backgroundColor = .red
        return cell
    }
    
    
    func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
        let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "headerId", for: indexPath) as! TestCollectionReusableView
        headerView.labelText.text = "dummy" // this line shows dummy
        return headerView
        
    }

   let testCollectionReusableView = TestCollectionReusableView()
    override func viewDidLoad() {
        super.viewDidLoad()
        collectionView.register(TestCollectionReusableView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "headerId")
        testCollectionReusableView.labelText.text = "Test" 
// above line Xcode 12.4 shows error - **Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value**
        
    }


}

Header Class File


class TestCollectionReusableView: UICollectionReusableView {
        
    @IBOutlet weak var labelText: UILabel!
    
}

Solution

  • Probably the best place to do this is in your DeleteViewController assuming that this class holds your collection view and is a data source for it.

    You can simply add a new property such as headerText: String which may then be user in your data source method. Whenever you change the text you should reload your collection view (or just the headers) for change to take effect.

    So for instance

    class DeleteViewController: UIViewController, UICollectionViewDataSource {
        
        @IBOutlet private var collectionView: UICollectionView?
    
        private var currentHeaderText: String = "Dummy"
    
        override func viewDidLoad() {
            super.viewDidLoad()
            changeHeaderText(to: "Some other text")
        }
    
        private func changeHeaderText(to text: String) {
            currentHeaderText = text
            collectionView?.reloadData()
        }
    
        func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
            let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "headerId", for: indexPath) as! TestCollectionReusableView
            headerView.labelText.text = currentHeaderText
            return headerView
        }
    
    }
    

    A more optimized approach may be to detect which index paths need reloading and only reload those index paths. It would even be possible to use methods like collectionView?.visibleSupplementaryViews(ofKind: <#T##String#>) and loop through all visible views that correspond to your class to apply the change. But this is all up to you.