Reputation: 387
I am trying to change the data of a collectionView based on the index of a segment control. When I run my code I get a crash. Can someone tell me what I did wrong here? I was following different methods I found. The error code I get with the crash is
Thread 1: EXC_BREAKPOINT (code=1, subcode=0x1da72fde0)
The error occurs when I try switching between segment indexes. and happens on the line
cell.trendsLabel.text = maleTrends[indexPath.row]
of
func handleSegControlTapped(for header: HomeViewHeaderReusableView)
var header: HomeViewHeaderReusableView?
func handleSegControlTapped(for header: HomeViewHeaderReusableView) {
collectionView.reloadItems(at: collectionView.indexPathsForVisibleItems)
switch header.segmentedControl?.selectedSegmentIndex {
case 0:
print("Display female trends")
header.segmentedControl?.selectedSegmentIndex = 0
let indexPath = IndexPath()
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "homeViewCell", for: indexPath) as! CurrentTrendsCell
cell.trendsLabel.text = femaleTrends[indexPath.row]
cell.trendsImageView.image = femaleImages[indexPath.row]
case 1:
print("Display male trends")
header.segmentedControl?.selectedSegmentIndex = 1
let indexPath = IndexPath()
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "homeViewCell", for: indexPath) as! CurrentTrendsCell
cell.trendsLabel.text = maleTrends[indexPath.row]
cell.trendsImageView.image = maleImages[indexPath.row]
default:
break
}
collectionView.reloadData()
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
let segmentedOutlet = header?.segmentedControl
switch segmentedOutlet?.selectedSegmentIndex {
case 0: return femaleTrends.count
case 1: return maleTrends.count
default: print("opps, cant load data")
}
return 0
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "homeViewCell", for: indexPath) as! CurrentTrendsCell
let segmentedOutlet = header?.segmentedControl
switch segmentedOutlet?.selectedSegmentIndex {
case 0: cell.trendsLabel.text = femaleTrends[indexPath.row]
cell.trendsImageView.image = femaleImages[indexPath.row]
case 1: cell.trendsLabel.text = maleTrends[indexPath.row]
cell.trendsImageView.image = maleImages[indexPath.row]
default: break
}
return cell
}
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "homeViewReuseCell", for: indexPath) as! HomeViewHeaderReusableView
headerView.delegate = self
return headerView
}
Edit
Here is the code in the header
class HomeViewHeaderReusableView: UICollectionReusableView {
@IBOutlet weak var segmentedControl: UISegmentedControl?
var delegate: HomeSegmentedControl?
// MARK: Handler
@objc func handleSegTapped() {
delegate?.handleSegControlTapped(for: self)
}
@IBAction func segmentedTapped(_ sender: Any) {
handleSegTapped()
// change data based on female / male
}
override func awakeFromNib() {
super.awakeFromNib()
segmentedControl?.tintColor = .clear
segmentedControl?.layer.borderColor = UIColor.clear.cgColor
segmentedControl?.setBackgroundImage(UIImage(), for: .normal, barMetrics: .default)
segmentedControl?.setTitleTextAttributes([
NSAttributedString.Key.font : UIFont.boldSystemFont(ofSize: 11),
NSAttributedString.Key.foregroundColor: UIColor.lightGray
], for: .normal)
segmentedControl?.setTitleTextAttributes([
NSAttributedString.Key.font : UIFont.boldSystemFont(ofSize: 11) ,
NSAttributedString.Key.foregroundColor: UIColor.white
], for: .selected)
segmentedControl?.selectedSegmentIndex = 0
}
Upvotes: 0
Views: 531
Reputation: 285072
Never, never ever call dequeueReusableCell
outside of cellForRow/ cellForItem
. The cell is dequeued but gets deallocated when the method exits. Unlike the collection/table view data source method the cell is not returned anywhere.
Edit:
Replace
var header: HomeViewHeaderReusableView?
with
var selectedSegmentIndex = 0
Then replace the entire method handleSegControlTapped
with
func handleSegControlTapped(for header: HomeViewHeaderReusableView) {
selectedSegmentIndex = header.segmentedControl!.selectedSegmentIndex
collectionView.reloadData()
}
As the data source methods handle the state of the segmented control simply reloading the collection view is sufficient.
Then change numberOfItemsInSection
to
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
switch selectedSegmentIndex {
case 0: return femaleTrends.count
case 1: return maleTrends.count
default: print("opps, cant load data")
return 0
}
}
and change the other data source methods accordingly.
Upvotes: 2
Reputation: 4096
Based on your selection on segment just reload the collectionView only and configure the CollectionViewCell
inside the cellForItemAt
.
No matter where you have added the segment control just truly react on the action method and update the collection accordingly.
Upvotes: 0