I tried to solve this problem since hours and didn't find a proper solution. I want to have a custom UICollectionView with a segmented control in the header. Changing the segmented control index should render the cells differently. So far I can display the segmented control in the header of my collectionView but changing the content of the collectionView inside of my UserSearchHeader doesn't work.
I created a custom UICollectionView called UserSearchController which is a Subclass of UICollectionView and conforms the UICollectionViewDelegateFlowLayout protocol.
class UserSearchController: UICollectionViewController,
UICollectionViewDelegateFlowLayout, UISearchBarDelegate { ....
My custom collectionView UserSearchController has a custom header (UserSearchHeader) and custom cells (UserSearchCell).
collectionView?.register(UserSearchCell.self, forCellWithReuseIdentifier: cellId)
collectionView?.register(UserSearchHeader.self, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "headerId")
The UserSearchHeader contains the segmented control.
class UserSearchHeader: UICollectionViewCell {
var segmentedControl: UISegmentedControl = {
let sc = UISegmentedControl(items: ["Username", "Hashtag"])
sc.translatesAutoresizingMaskIntoConstraints = false
sc.tintColor = UIColor.black
sc.selectedSegmentIndex = 0 // automatically highlight
// sc.addTarget(self, action: #selector(segmentedChange), for: .valueChanged)
return sc
}() .....
If the segmentedIndex is 0 I want to render the cells with the UserSearchCell class if the segmentedIndex is 1 I want to render it with a different cellClass (Clicking the segmented control). How can I achieve this behavior with these different classes. shall I use the cellForItem at method inside of the UserSearchController to check the status of the segmented control. But how can I do this when the segmented control is defined in the UserSearchHeader class .
override func collectionView(_ collectionView:
UICollectionView, cellForItemAt indexPath: IndexPath) ->
UICollect. ionViewCell { if segmentedControl.segmentedIndex = 0 ....}
tried using Use the scopeButtonTitles
property?
mySearchController.searchBar.scopeButtonTitles = ["Username", "Hashtag"]
Have a look at this question for more details. Basically you use the
func searchBar(_ searchBar: UISearchBar, selectedScopeButtonIndexDidChange selectedScope: Int) {
// respond to your scopeBar selection here
switch selectedScope {
case 0:
print("Username tab selected")
// do your stuff for Username here
case 1:
print("Hashtag tab selected")
// do your stuff for Hashtag here
default:
print("Someone added a tab!")
// you shouldn't have more than 2 tabs
}
EDIT:
Please find below the missing pieces described in the link provided initially. There is no need to add the header from a NIB.
First, you add properties for your search & results controllers:
typealias ResultVC = UserResultController //The class to show your results
var searchController: UISearchController!
var resultController: ResultVC?
Then, in viewDidLoad
you add this:
// Search Results
resultController = ResultVC()
setupSearchControllerWith(resultController!)
if #available(iOS 9.0, *) {
searchController?.loadViewIfNeeded()
}
Then you need to add this function to your class:
func setupSearchControllerWith(_ results: ResultVC) {
// Register Cells
results.tableView.register(TableCell.self, forCellReuseIdentifier: "\(TableCell.self)")
results.tableView.register(UINib(nibName: "\(TableCell.self)", bundle: Bundle.main), forCellReuseIdentifier: "\(TableCell.self)")
// We want to be the delegate for our filtered table so didSelectRowAtIndexPath(_:) is called for both tables.
results.tableView.delegate = self
searchController = UISearchController(searchResultsController: results)
// Set Scope Bar Buttons
searchController.searchBar.scopeButtonTitles = ["Comics only", "Digital too"]
// Set Search Bar
searchController.searchResultsUpdater = self
searchController.searchBar.sizeToFit()
tableView.tableHeaderView = searchController.searchBar
// Set delegates
searchController.delegate = self
searchController.searchBar.delegate = self // so we can monitor text & scope changes
// Configure Interface
searchController.dimsBackgroundDuringPresentation = false
searchController.hidesNavigationBarDuringPresentation = true
if #available(iOS 9.1, *) {
searchController.obscuresBackgroundDuringPresentation = false
}
// Search is now just presenting a view controller. As such, normal view controller
// presentation semantics apply. Namely that presentation will walk up the view controller
// hierarchy until it finds the root view controller or one that defines a presentation context.
definesPresentationContext = true
}
Finally, you add the function I was describing initially: searchBar:selectedScopeButtonIndexDidChange: