I really need help as I am new to Swift. I am facing an issue where I don't find a way to return numberOfRowsInSection
Scenario:
I have 3 numberOfSections in tableview which I am returning from sectionArray, which is as follows:
{
"mbsdcie6_2_1": "Incomer 132 KV Parameters",
"mbsdcie6_2_2": [
3,
6,
4,
5,
8,
30,
31,
7,
18,
29,
1
]
},
{
"mbsdcie6_2_1": "SMS2 Parameters",
"mbsdcie6_2_2": [
9,
10,
11,
12,
13,
14
]
},
{
"mbsdcie6_2_1": "SMS 1 Parameters",
"mbsdcie6_2_2": [
15,
17
]
}
]
}
Using above array, I can return numberOfSections like this:
func numberOfSections(in tableView: UITableView) -> Int {
return self.sectionArray.count
}
But, how to return numberOfRowsInSection using sectionArray ??
Note:
I want numberOfRows from "mbsdcie6_2_2" key of sectionArray
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0 {
return "numberOfRows" // What to return here?
}
if section == 1 {
return "numberOfRows"
}
if section == 2 {
return "numberOfRows"
}
return 0
}
Edit 1
This is how I added data into sectionArray:
// It comes from another webservice, so I added it to userdefaults.
let headers = swiftyJSonVar["message"][0]["mbsdcie6"]["mbsdcie6_2"].arrayObject
kUserDefault.set(headers, forKey: kHeadersArray)
// In my another ViewController, I am retrieving it like this:
var sectionArray = [Dictionary<String, Any>]()
override func viewWillAppear(_ animated: Bool) {
sectionArray = kUserDefault.array(forKey: kHeadersArray) as! [Dictionary<String, Any>]
print(sectionArray)
}
I know it could be silly and It's way too easy but somehow I am stucked as I am new to it.
Any help would be appreciated, Thanks!
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if !sectionArray.isEmpty {
let sectionContent = sectionArray[section]["mbsdcie6_2_2"] as? [Int]
return sectionContent.count
} else {
return 0
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if sectionArray.indices.contains(section),
let sectionContent = sectionArray[section]["mbsdcie6_2_2"] as? [Int] {
return sectionContent.count
} else {
return 0
}
}
try this:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let singleSection = self.sectionArray[section]
if let rows = singleSection["mbsdcie6_2_2"] as? [Int] {
return rows.count
} else {
return 0
}
}
Related
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()
}
}
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
}
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
}
I have a section index that contains full alphabet - however, sections in my table contains only a few letters (e.g. C, F, N, U).
I would like to modify sectionForSectionIndexTitle to properly show right sections when sliding finger over section index. I'm still not sure how to do it using sections.append...
Thank you for help.
This is how my code looks like:
Section.swift
struct Section
{
var heading : String
var items : [String]
init(title: String, objects : [String]) {
heading = title
items = objects
}
}
ViewController.swift
func updateSections(index : Int) {
switch index {
case 0:
sections.append(Section(title: "C", objects: ["Czech Republic"]))
sections.append(Section(title: "F", objects: ["France"]))
sections.append(Section(title: "N", objects: ["Norway"]))
sections.append(Section(title: "U", objects: ["USA"]))
default: break
}
tableViewOutlet.reloadData()
}
let arrIndexSection = ["A","B","C","D", "E", "F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"]
func sectionIndexTitlesForTableView(tableView: UITableView) -> [String]? {
if segmentedControlOutlet.selectedSegmentIndex == 0 {
return arrIndexSection
} else {
return [""]
}
}
func tableView(tableView: UITableView, sectionForSectionIndexTitle title: String, atIndex index: Int) -> Int {
let temp = arrIndexSection as NSArray
return temp.indexOfObject(title)
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return sections.count
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let section = sections[section]
return section.items.count
}
func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return sections[section].heading
}
try following code in your project :
func tableView(tableView: UITableView, sectionForSectionIndexTitle title: String, atIndex index: Int) -> Int {
var tempIndex:Int = 0
for str in arrIndexSection {
if str == title {
return tempIndex
}
tempIndex += 1
}
return 0
}
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
}