Issue when filtering with UISearchResults - ios

So I have a list of friends coming from the API and I've tried to implement also the search functionality. So far, so good, the filtering is good, but my first section is actually a button that sends me to another VC and it 's getting irritating that that cell always appears when I try to search through the friend list. Actually, i want it to be hidden when I search for friends.
I added some pictures to make it more clear
As can be seen the third picture shows clearly the problem.
My code looks like.
var friendList = [Conversations]()
var filteredFriends = [Conversations]()
func numberOfSections(in tableView: UITableView) -> Int {
return friendList.count + 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if isFiltering() {
return filteredFriends.count
}
if section == 0 {
return 1
} else if section == 1 {
return friendList.count
}
return 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "NewGroupConversationCell") as! NewGroupConversationTableViewCell
return cell
} else if indexPath.section == 1 {
let cell = tableView.dequeueReusableCell(withIdentifier: "NewConversationCell") as! NewConversationTableViewCell
var friendList: Conversations
if isFiltering() {
friendList = filteredFriends[indexPath.row]
} else {
friendList = self.friendList[indexPath.row]
}
cell.populate(friendList)
return cell
}
return UITableViewCell()
}
func searchBarIsEmpty() -> Bool {
// Returns true if the text is empty or nil
return searchController.searchBar.text?.isEmpty ?? true
}
func filterContentForSearchText(_ searchText: String, scope: String = "All") {
filteredFriends = friendList.filter({( friend : Conversations) -> Bool in
return (friend.name?.lowercased().contains(searchText.lowercased()))!
})
mainTableView.reloadData()
}
func isFiltering() -> Bool {
return searchController.isActive && !searchBarIsEmpty()
}
extension NewConversationViewController: UISearchResultsUpdating {
// MARK: - UISearchResultsUpdating Delegate
func updateSearchResults(for searchController: UISearchController) {
filterContentForSearchText(searchController.searchBar.text!)
}
Pls tell me if you need more explanation.

Your the numberOfSection is equal to number of friends, that's why you have the number of action button equals to number of friends, try
func numberOfSections(in tableView: UITableView) -> Int {
return 2 // your button, and your friend list
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0 {
if isFiltering() {
return 0 // hide button
}
return 1
} else if section == 1 {
if isFiltering() {
return filteredFriends.count
}
return friendList.count
}
return 0
}

Hide section 0 when you are using filtered list.
func numberOfSections(in tableView: UITableView) -> Int {
return 2 // Default 2 sections
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0 {
if isFiltering() {
return 0
}
return 1
} else {
return friendList.count
}
return 0
}

Related

How to do section title in TableView if there is no sections in data from json?

just like title says, I would like to categorize my data by some property which I get from json.
Here is example of my json:
{
"rows": [
{
"id": 1,
"name": "Trip to London",
"status": "CURRENT",
"companyId": 395,
"approvedBy": null,
"start": "2021-01-12T00:00:00.000Z",
"end": "2021-01-13T00:00:00.000Z",
"approvedAt": null,
"updatedBy": null,
"createdAt": "2021-01-04T13:32:45.816Z",
"updatedAt": "2021-01-04T13:32:45.816Z",
"services": "Flight"
}
]
}
I have 3 states of my response, which is status: String in json response and possible values are: upcoming, current and previous. I would like to categorize my data by status property, if I get that trip is current, then put it under section title of current.
What I tried so far is this:
In numberOfRowsInSection:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if isSearching {
return self.filteredData.count
}
return bookedTrips.count
}
In viewForHeaderInSection:
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let cell = tableView.dequeueReusableHeaderFooterView(withIdentifier: Cells.sectionTitle) as! TripsListHeaderCell
if section == 0 {
cell.configure(trips: "CURRENT")
} else if section == 1 {
cell.configure(trips: "UPCOMING")
} else {
cell.configure(trips: "PREVIOUS")
}
return cell
}
EDIT:
In cellForRowAt:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: Cells.tripInfo) as! TripsListDetailCell
if isSearching {
cell.configure(trips: filteredData[indexPath.row])
} else {
cell.configure(trips: bookedTrips[indexPath.row])
}
return cell
}
And if I return number 3 in function numberOfSections, I have my section titles displayed, but since I returned count in numberOfRowsInSection, everything is duplicated. What should I do to categorize my data by status prop from json, since I don't have 2D array so I could work with sections?
And of course, if there is better way how to write viewForHeaderInSection, which I am pretty sure there is, please give me advice.
I can post some screenshots if needed if my question is not properly written and its hard to understand what I am trying to say.
Step 1 : You need to create struct for Trip like as below
struct TripStruct
{
var sectionName : String
var tripArray : [TripModel] = [] // Here TripModel == Your Trip Model
}
Step 2 : You need to group data into section
var tripStructList : [TripStruct] = [] //Here this Global Variable
var filterTripStructList : [TripStruct] = [] //Here this Global Variable
let groupedDictionary = Dictionary(grouping: allTripArray, by: { $0. status }) // Here allTripArray == Your trip array from json
let keys = groupedDictionary.keys.sorted()
self.tripStructList = keys.map({ TripStruct(sectionName: $0, tripArray: groupedDictionary[$0]!)})
Step 3 : Set data in tableView delegate and datasoure method like as below
func numberOfSections(in tableView: UITableView) -> Int
{
return isSearching ? self.filterTripStructList.count : self.tripStructList.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return isSearching ? self.filterTripStructList[section].tripArray.count : self.tripStructList[section].tripArray.count
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView?
{
let cell = tableView.dequeueReusableHeaderFooterView(withIdentifier: Cells.sectionTitle) as! TripsListHeaderCell
let sectionRow = isSearching ? filterTripStructList[section] : tripStructList[section]
cell.configure(trips: sectionRow.sectionName)
return cell
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: Cells.tripInfo) as! TripsListDetailCell
let sectionRows = isSearching ? filterTripStructList[indexPath.section] : tripStructList[indexPath.section]
let row = sectionRows.tripArray[indexPath.row]
cell.configure(trips: row)
return cell
}
Step 4 : Search your data
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
if searchText == ""
{
isSearching = false
filterTripStructList.removeAll()
self.tableView.reloadData()
return
}
else
{
isSearching = true
let filterAllTripArray = self.allTripArray.filter({$0.tripName.lowercased().contains(searchText.lowercased())}) // Here allTripArray == Your trip array from json
let groupedDictionary = Dictionary(grouping: filterAllTripArray, by: { $0.status })
let keys = groupedDictionary.keys.sorted()
self.filterTripStructList = keys.map({ TripStruct(sectionName: $0, tripArray: groupedDictionary[$0]!)})
self.tableView.reloadData()
}
}

Swift: fatal error: Index out of range

I'm getting an "Index out of range" when populating a UITableView.
I don't know why it gives me error. I have a condition statement on my cell creation function which checks for the count of each array and then adds a custom cell on index 0.
If anyone knows about this problem, please tell me the solution. I've been working on it for days and can't seem to figure this one out.
var homeArr: [services] = []
var autoArr: [services] = []
Alamofire.request(url_specialist_request_url, method: .post, parameters: parameters).responseJSON {
response in
if response.data != nil {
let json = JSON(data: response.data!)
let json_count = json.count
// print(json)
self.homeArr.append(services(service_name:"",service_icon:"",service_category:""))
self.autoArr.append(services(service_name:"",service_icon:"",service_category:""))
self.personalArr.append(services(service_name:"",service_icon:"",service_category:""))
for i in 0 ..< json_count {
let categoryId = json[i]["category_id"].string!
if(categoryId == "1") {
self.homeArr.append(services(service_name:json[i]["service_name"].string!,service_icon:"\(json[i]["service_icon"].string!)Icon",service_category:json[i]["category_id"].string!))
} else if(categoryId == "2") {
self.autoArr.append(services(service_name:json[i]["service_name"].string!,service_icon:"\(json[i]["service_icon"].string!)Icon",service_category:json[i]["category_id"].string!))
} else {
self.personalArr.append(services(service_name:json[i]["service_name"].string!,service_icon:"\(json[i]["service_icon"].string!)Icon",service_category:json[i]["category_id"].string!))
}
}
self.tableView.reloadData()
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "serviceCell",for:indexPath) as! servicesCell
let home_dict = self.homeArr[indexPath.row]
// ** Index out of range on the following line **
let auto_dict = self.autoArr[indexPath.row]
if(self.homeArr.count > 1) {
if (indexPath.row == 0)
{
cell.serviceLabel!.text = "Home"
cell.contentView.backgroundColor = UIColor.blue
} else {
cell.serviceLabel!.text = home_dict.service_name
cell.serviceIcon!.image = UIImage(named:"\(home_dict.service_icon)")
}
}
if(self.autoArr.count > 1) {
if (indexPath.row == 0)
{
cell.serviceLabel!.text = "Personal"
cell.contentView.backgroundColor = UIColor.blue
} else {
cell.serviceLabel!.text = auto_dict.service_name
cell.serviceIcon!.image = UIImage(named:"\(auto_dict.service_icon)")
}
}
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return(homeArr.count + arrAuto.count)
}
This is what I want to achieve
Home Arr cell
value1
value2
Auto Arr cell
value1
value2
Create two sections One for HomeArr and one for AutoArr. I believe for each section you wanna show a additional cell with some title. So below code should help you.
extension ViewController : UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0 {
return (homeArr.count > 0) ? homeArr.count + 1 : 0
}
else {
return (autoArr.count > 0) ? autoArr.count + 1 : 0
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "serviceCell",for:indexPath) as! servicesCell
if indexPath.section == 0 {
if (indexPath.row == 0)
{
cell.serviceLabel!.text = "Home"
cell.contentView.backgroundColor = UIColor.blue
} else {
let home_dict = self.homeArr[indexPath.row - 1]
cell.serviceLabel!.text = home_dict.service_name
cell.serviceIcon!.image = UIImage(named:"\(home_dict.service_icon)")
}
}
else {
if (indexPath.row == 0)
{
cell.serviceLabel!.text = "Personal"
cell.contentView.backgroundColor = UIColor.blue
} else {
let auto_dict = self.autoArr[indexPath.row - 1]
cell.serviceLabel!.text = auto_dict.service_name
cell.serviceIcon!.image = UIImage(named:"\(auto_dict.service_icon)")
}
}
return cell
}
}
EDIT:
As pointed out by rmaddy in comments below
Why the extra row in each section? Why not use a section header
instead?
As we are not aware of OP's exact requirement I am updating my code to show section title as well.
extension ViewController : UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0 {
return homeArr.count
}
else {
return autoArr.count
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "serviceCell",for:indexPath) as! servicesCell
if indexPath.section == 0 {
let home_dict = self.homeArr[indexPath.row]
cell.serviceLabel!.text = home_dict.service_name
cell.serviceIcon!.image = UIImage(named:"\(home_dict.service_icon)")
}
else {
let auto_dict = self.autoArr[indexPath.row]
cell.serviceLabel!.text = auto_dict.service_name
cell.serviceIcon!.image = UIImage(named:"\(auto_dict.service_icon)")
}
return cell
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
if section == 0 {
return "Home Arr cell"
}
else {
return "Auto Arr cell"
}
}
}

TableViewController numberOfRowsInSection section

I have a controller with buttons and a TableViewController with 10 arrays. Each button has an index, which pass to TableViewController.
In TableViewController code looks like this:
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if buttonIndex == 0 {
return array0.count
}
else if buttonIndex == 1 {
return array1.count
}
else if buttonIndex == 2 {
return array2.count
}
else if buttonIndex == 3 {
return array3.count
}
else if buttonIndex == 4 {
return array4.count
}
else if buttonIndex == 5 {
return array5.count
}
else if buttonIndex == 6 {
return array6.count
}
else if buttonIndex == 7 {
return array6.count
}
else if buttonIndex == 8 {
return array6.count
}
return array0.count
}
I want to automatically define current index to do this:
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
//return array(currentIndex).count
}
How to do it?
One way to achieve what you want is by creating a map, with index as key and array as value.
So your code should look something like this:
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return indicesArray[index].count
}
You can make nested array where to store your arrays like:
var mainArray = [array0,array1,array2 ... ]
Then in
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return mainArray[section].count
}
You have to make the collection of your array in the array and you could be able to return as your requirement.
At class level:
var arrOfArrayData = []
Just like that:
let array0 = [""]
let array1 = [""]
let array2 = [""]
let array3 = [""]
let array4 = [""]
let array5 = [""]
let array6 = [""]
arrOfArrayData = [array0,array1,array1,array3,array4,array5,array6]
return arrOfArrayData[section].count //numberOfRowsInSection
Your list which contains 10 values as an array:
let listData = [["value11", "value12"], ["value21", "value22"], ["value31", "value32"] ...]
Inside UITableViewDataSource delegate method:
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return listData[section].count
}

Swift/iOS: Collapsing a section in a UITableView

I have a UITableView with about 5 sections. I am trying to collapse and expand one of those section by the click of a button, but I am seeing an issue where the code I'm using to do so results in the collapsing of other sections as well. Specifically, the first row of all visible sections are collapsed.
Here is what that code looks like:
func didClickSectionCollapseButton() {
shouldCollapseSection = !shouldCollapseSection
tableView.beginUpdates()
tableView.reloadSections(NSIndexSet(index: 1), withRowAnimation: .Fade)
tableView.endUpdates()
}
And here is the numberOfRowInSection method:
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
switch section {
case 0:
return 1
case 1:
// collapsible section
return shouldCollapse ? 0 : collapsibleSectionCellCount
case 2:
return getCellCount()
case 3:
return 1
case 4:
return 1
default:
return 0
}
}
Is there anything I'm missing here? I've gone through various tutorials and questions, but I haven't been able to find a solution yet.
Hi after a lot of research, i found a solution which worked for me perfectly using storyboard.
View controller code:
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tblView: UITableView!
var sections = ["section1","section2","section3"]
var cells = ["cell1","cell2","cell3","cell4"]
var selectedIndx = -1
var thereIsCellTapped = false
override func viewDidLoad() {
super.viewDidLoad()
tblView.reloadData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func numberOfSections(in tableView: UITableView) -> Int {
return sections.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
switch section {
case 0:
return 2
case 1:
return 3
default:
return 4
}
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 50
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath.section == selectedIndx && thereIsCellTapped{
return 50
}else{
return 0
}
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerCell = tableView.dequeueReusableCell(withIdentifier: "SectionTableViewCell") as! SectionTableViewCell
headerCell.lblHeader.text = sections[section]
headerCell.btnSelection.tag = section
headerCell.btnSelection.addTarget(self, action: #selector(ViewController.btnSectionClick(sender:)), for: .touchUpInside)
return headerCell
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ExpandeTableViewCell") as! ExpandeTableViewCell
cell.lblCell.text = cells[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print(indexPath.section)
}
#objc func btnSectionClick(sender:UIButton!){
print("selected index",sender.tag)
if selectedIndx != sender.tag {
self.thereIsCellTapped = true
self.selectedIndx = sender.tag
}
else {
// there is no cell selected anymore
self.thereIsCellTapped = false
self.selectedIndx = -1
}
tblView.reloadData()
}
}
If you don't want to do select and unselect on the same selection then, see code below.
#objc func btnSectionClick(sender:UIButton!){
print("selected index",sender.tag)
selectedIndx = sender.tag
tblView.reloadData()
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath.section == selectedIndx{
return 50
}else{
return 0
}
}
It works for me, i referred lot of answers and made it. I hope it will help you.
I've Used this code long time ago it is in Swift 2.3. I don't know if this will help or not but worth to mention it.
class DriversVC : UIViewController , UITableViewDelegate , UITableViewDataSource {
//-----------------------------------------------------------------------
//MARK: - Outlets
#IBOutlet var tvDriverList: UITableView! {
didSet {
tvDriverList.delegate = self
tvDriverList.dataSource = self
}
}
//-----------------------------------------------------------------------
//MARK: - Variables
var arrDriverList : NSArray? //Section data
var arrWorkerList : NSArray? //Section data
var collapseSection0 : Bool = false
var collapseSection1 : Bool = false
var btnSection0Headder : UIButton = UIButton()
var btnSection1Headder : UIButton = UIButton()
//------------------------------------------------------
func btnSection0HeadderTapped () {
if collapseSection0 {
collapseSection0 = false
} else {
collapseSection0 = true
}
tvDriverList.reloadSections(NSIndexSet(index: 0), withRowAnimation: UITableViewRowAnimation.Fade)
}
//------------------------------------------------------
func btnSection1HeadderTapped () {
if collapseSection1 {
collapseSection1 = false
} else {
collapseSection1 = true
}
tvDriverList.reloadSections(NSIndexSet(index: 1), withRowAnimation: UITableViewRowAnimation.Fade)
}
//-----------------------------------------------------------------------------------
//MARK:- Table delegate and data sources
func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 50
}
//------------------------------------------------------
func tableView(tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return 20
}
//------------------------------------------------------
func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let view = UIView(frame: CGRect(x: 0, y: 0, width: UIScreen.mainScreen().bounds.width, height: 50))
view.backgroundColor = OrangeColor //Set your color
let lbl = UILabel(frame: CGRect(x: 10, y: 5, width: UIScreen.mainScreen().bounds.width - 20, height: 40))
lbl.font = UIFont(name: OpenSansRegular, size: 18) //Set your font
lbl.textColor = UIColor.whiteColor()
view.addSubview(lbl)
if section == 0 {
lbl.text = "D R I V E R"
btnSection0Headder.addTarget(self, action: #selector(self.btnSection0HeadderTapped), forControlEvents: .TouchUpInside)
btnSection0Headder.frame = view.frame
view.addSubview(btnSection0Headder) // uncomment to apply collapse effect
} else {
lbl.text = "W O R K E R"
btnSection1Headder.addTarget(self, action: #selector(self.btnSection1HeadderTapped), forControlEvents: .TouchUpInside)
btnSection1Headder.frame = view.frame
view.addSubview(btnSection1Headder) // uncomment to apply collapse effect
}
return view
}
//------------------------------------------------------
func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
return UIView()
}
//------------------------------------------------------
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
if arrWorkerList != nil && arrWorkerList?.count > 0 {
return 2
}
return 1
}
//------------------------------------------------------
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0 {
if !collapseSection0 {
guard arrDriverList != nil else {return 0}
return arrDriverList!.count
} else {
return 0
}
} else {
if !collapseSection1 {
guard arrWorkerList != nil else {return 0}
return arrWorkerList!.count
} else {
return 0
}
}
}
//------------------------------------------------------
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCellWithIdentifier(NSStringFromClass(DriversCVC).componentsSeparatedByString(".").last!) as? DriversCVC else { fatalError("unexpected DriversCVC dequeued from tableView") }
cell.superViewController = self
if indexPath.section == 0 {
guard let dict = arrDriverList![indexPath.row] as? NSDictionary else {return cell}
cell.data = dict
} else {
guard let dict = arrWorkerList![indexPath.row] as? NSDictionary else {return cell}
cell.data = dict
}
cell.setup()
return cell
}
//----------------------------------------------------------------------
//MARK: - Action Method
#IBAction func btnBackTapped(sender: AnyObject) {
guard self.navigationController != nil else {
self.dismissViewControllerAnimated(true, completion: nil)
return
}
guard self.navigationController?.popViewControllerAnimated(true) != nil else {
guard self.navigationController?.dismissViewControllerAnimated(true, completion: nil) != nil else {
AppDelegate.sharedInstance().loginCall()
return
}
return
}
}
//-----------------------------------------------------------------------
//MARK: - View Life Cycle Methods
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
//----------------------------------------------------------------------
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
setUpVC()
}
//----------------------------------------------------------------------
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
} }
You can use:
func didClickSectionCollapseButton() {
shouldCollapseSection = !shouldCollapseSection
tableView.beginUpdates()
tableView.deleteSections(NSIndexSet(index: 1), withRowAnimation: .Fade)
tableView.endUpdates()
}
beginUpdates() and endUpdates() works in pair if you want subsequent insertions, deletion, and selection operations, but not for the reloadData.
In your code, remove beginUpdates() and endUpdates().
Is there a difference between the shouldCollapseSection variable being set in the button action and the shouldCollapse variable used in the numberOfRowsInSection method ?
It would seem that you are not setting the same variable you are using in the data source delegate.

Group and sort Backendless data in UITableview with Swift

I'm looking to group and sort a list of users from backendless, similar to iPhone contacts. I want to add sectionIndexTitlesForTableView(_:), titleForHeaderInSection(_:), and sectionForSectionIndexTitle(_:). I haven't found a tutorial on how to do this, and I have been stuck for weeks.
So far, I'm able to retrieve users and populate the table view. I also implemented UISearchBarDelegate.
var users: [BackendlessUser] = []
var filteredUsers : [BackendlessUser] = []
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if tableView == self.tableView {
return users.count
} else {
return self.filteredUsers.count
}
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = UITableViewCell()
if tableView == self.tableView {
let user = users[indexPath.row]
cell.textLabel?.text = user.name
} else {
let filteredUser = filteredUsers[indexPath.row]
cell.textLabel?.text = filteredUser.name
}
return cell
}
You must have a dictionary of array (name 'data' for example)
data["A"] = ["Ananas", "Anaconda", "Apple"]
data["B"] = ["Banana", "Baby"]
...
data["Z"] = ["Zoro"]
begin:
let letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
var headers: [String] = []
var data : [String: [String]] = [:] // Choose your type
override func viewDidLoad(){
// Do your stuff...
headers = letters.keys.sort()
// init your data var
data = ...
tableView.reloadData()
}
for header:
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return headers.count
}
func sectionHeaderTitlesForTableView(tableView: UITableView) -> [String]?{
return headers
}
func tableView: UITableView, titleForHeaderInSection section: Int) -> String?{
return headers[section];
}
cell
func tableView(tableView: UITableView, numberOfRowInSection section: Int) -> Int {
// Exemple
return data[section].count
}

Resources