Refreshing / Reloading Data of Supplementary View (Header & Footer) for Collection View

I have deployed 2 Supplementary Views for Header and Footer views for my collection view.

Header '0' has UILabel text which dynamically sets data dynamically after transitioning to push secondary view controller.

But I am having problem that when UILabel in header loads again after returning and taking data from secondary view controller collection view get updated but Header and Footer Supplementary views has overlapping of old and new data...!!!

How to fix overlapping of data and 'Reload Supplementary Views' for Header and Footer?

Accepted Reply

Here is the problem: line 8 you recreate a label and add it over if there is already an existing one:

Code Block
let headerUILabelText = UILabel()
headerUILabelText.textAlignment = .left
headerUILabelText.font = UIFont.systemFont(ofSize: 20, weight: .bold)
headerUILabelText.numberOfLines = 0
headerUILabelText.text = "Your Roll Number is \(NumberInteger). Your Exam Numbers are \(examNumbers(number: "\(NumberInteger)"))"
headerUILabelText.textColor = .darkGray
headerUILabelText.lineBreakMode = .byTruncatingTail
headerView.addSubview(headerUILabelText)

You should either:
  • remove subviews first

  • test if there is already a UILabel and not recreate if so

  • replace existing subview.

I have used this extension:
Code Block
extension UIView {
class func getAllSubviews<T: UIView>(from parentView: UIView) -> [T] {
return parentView.subviews.flatMap { subView -> [T] in
var result = getAllSubviews(from: subView) as [T]
if let view = subView as? T { result.append(view) }
return result
}
}
class func getAllSubviews(from parentView: UIView, types: [UIView.Type]) -> [UIView] {
return parentView.subviews.flatMap { subView -> [UIView] in
var result = getAllSubviews(from: subView) as [UIView]
for type in types {
if subView.classForCoder == type {
result.append(subView)
return result
}
}
return result
}
}
func getAllSubviews<T: UIView>() -> [T] {
return UIView.getAllSubviews(from: self) as [T]
}
func get<T: UIView>(all type: T.Type) -> [T] {
return UIView.getAllSubviews(from: self) as [T]
}
func get(all type: UIView.Type) -> [UIView] {
return UIView.getAllSubviews(from: self)
}
}

And call in your case:
Code Block
let allLabels = self.headerView.get(all: UILabel.self)
for sub in allLabels {
sub.removeFromSuperview()
}

And now you can safely add subview:
Code Block
headerView.addSubview(headerUILabelText)


Replies

Could you show some code ?
Are you sure you do not recreate a new label in header and foyer ?
If so, a way to solve would be to check if supplementary view already exist before creating, or delete them before recreating.

If that's OK, don't forget to close the thread (and also close other threads you have opened).
Hi,

I create UILabel by Adding it as a subview to header...

Here is my code for Header at '0'...


Code Block
override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
let reusableview = UICollectionReusableView()
if (kind == UICollectionView.elementKindSectionHeader) {
print("section \(indexPath.section)")
if indexPath.section == 0 {
let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: collectionViewFirstHeaderFooterReuseIdentifier, for: indexPath)
headerView.backgroundColor = .clear
let headerUILabelText = UILabel()
headerUILabelText.textAlignment = .left
headerUILabelText.font = UIFont.systemFont(ofSize: 20, weight: .bold)
headerUILabelText.numberOfLines = 0
headerUILabelText.text = "Your Roll Number is \(NumberInteger). Your Exam Numbers are \(examNumbers(number: "\(NumberInteger)"))"
headerUILabelText.textColor = .darkGray
headerUILabelText.lineBreakMode = .byTruncatingTail
headerView.addSubview(headerUILabelText)
headerUILabelText.setMargins()
headerUILabelText.isHidden = false
headerUILabelText.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
headerUILabelText.leadingAnchor.constraint(equalTo: headerView.leadingAnchor),
headerUILabelText.trailingAnchor.constraint(equalTo: headerView.trailingAnchor),
headerUILabelText.centerXAnchor.constraint(equalTo: headerView.centerXAnchor),
headerUILabelText.centerYAnchor.constraint(equalTo: headerView.centerYAnchor),
headerUILabelText.topAnchor.constraint(equalTo: headerView.topAnchor),
headerUILabelText.rightAnchor.constraint(equalTo: headerView.rightAnchor),
headerUILabelText.bottomAnchor.constraint(equalTo: headerView.bottomAnchor),
headerUILabelText.leftAnchor.constraint(equalTo: headerView.leftAnchor),
headerUILabelText.widthAnchor.constraint(equalToConstant: headerView.frame.width),
headerUILabelText.heightAnchor.constraint(equalToConstant: headerView.frame.height)
])
return headerView
} else if indexPath.section == 1 {
let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: collectionViewSecondHeaderFooterReuseIdentifier, for: indexPath)
return headerView
} else {
return reusableview
}
}

Here is the problem: line 8 you recreate a label and add it over if there is already an existing one:

Code Block
let headerUILabelText = UILabel()
headerUILabelText.textAlignment = .left
headerUILabelText.font = UIFont.systemFont(ofSize: 20, weight: .bold)
headerUILabelText.numberOfLines = 0
headerUILabelText.text = "Your Roll Number is \(NumberInteger). Your Exam Numbers are \(examNumbers(number: "\(NumberInteger)"))"
headerUILabelText.textColor = .darkGray
headerUILabelText.lineBreakMode = .byTruncatingTail
headerView.addSubview(headerUILabelText)

You should either:
  • remove subviews first

  • test if there is already a UILabel and not recreate if so

  • replace existing subview.

I have used this extension:
Code Block
extension UIView {
class func getAllSubviews<T: UIView>(from parentView: UIView) -> [T] {
return parentView.subviews.flatMap { subView -> [T] in
var result = getAllSubviews(from: subView) as [T]
if let view = subView as? T { result.append(view) }
return result
}
}
class func getAllSubviews(from parentView: UIView, types: [UIView.Type]) -> [UIView] {
return parentView.subviews.flatMap { subView -> [UIView] in
var result = getAllSubviews(from: subView) as [UIView]
for type in types {
if subView.classForCoder == type {
result.append(subView)
return result
}
}
return result
}
}
func getAllSubviews<T: UIView>() -> [T] {
return UIView.getAllSubviews(from: self) as [T]
}
func get<T: UIView>(all type: T.Type) -> [T] {
return UIView.getAllSubviews(from: self) as [T]
}
func get(all type: UIView.Type) -> [UIView] {
return UIView.getAllSubviews(from: self)
}
}

And call in your case:
Code Block
let allLabels = self.headerView.get(all: UILabel.self)
for sub in allLabels {
sub.removeFromSuperview()
}

And now you can safely add subview:
Code Block
headerView.addSubview(headerUILabelText)