I have a problem that I want to show a tableview, but separated in sections by the "status" of each item. I know how to do it with a simple string array, but I can't get to make this work with a class (Aluno) array, here's my code so far:
import UIKit
class DeliveriesTVC: UITableViewController {
let sections = ["Delivered", "Not Delivered"]
var studentList: [Array<Student>] = [[], []]
override func viewDidLoad() {
super.viewDidLoad()
for i in 0...5{
studentList[0].append(Student(alunoNome: "Aluno \(i)", alunoImg: "dani_test", alunoStatus: "Delivered"))
}
for i in 6...10{
studentList[1].append(Student(alunoNome: "Aluno \(i)", alunoImg: "dani_test", alunoStatus: "Not Delivered"))
}
self.title = "Deliveries"
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cellEntrega = tableView.dequeueReusableCell(withIdentifier: "EntregaCell", for: indexPath) as? EntregaCell {
let entregaCell = studentList[indexPath.section][indexPath.row]
// here i call a function in my TableViewCell class that update the cell itself
cellEntrega.updateAlunoUI(Aluno: entregaCell)
return cellEntrega
} else {
return UITableViewCell()
}
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return listaAlunos[section].count
}
func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return self.sections[section]
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 2
}
}
In the output, i just get the "first section" showing, and without a name, even with me setting the name of each section and the number of sections. I've looked everywhere but i couldn't find a solution.
Your numberOfSections and titleForHeader methods are wrong, it should be
override func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return self.sections[section]
}
Additionally, you should return self.sections.count instead of return 2 in numberOfSections being hardcoded as in case you add another object to the array, you will have to change the 2 to whatever elements the array has now.
For your numberOfSectionInTableView function, shouldn't it be override func numberOfSectionsInTableView(in tableView: UITableView) -> Int {
return 2
} with a in in front of the tableView: UITableView?
I don't see where you connect your UITableView's delegate and datasource.
Here is a tutorial to show your about using UITableView.
Take a look at "Basic Table View" - "Step 3: Set the datasource and delegate"
Related
When I try to run my code, the cellForRowAtIndexPath function does not run for some reason.
The numberOfSections function works perfectly. I was thinking it was the dataSource/delegate function or a problem with the cell.
Would really appreciate finding solution to this problem.
import UIKit
class MoviesTableViewController: UITableViewController {
#IBOutlet weak var searchBar: UISearchBar!
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
MovieController.getAllMovies(name: "blue") { (sucess) in
if sucess {
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
}
tableView.reloadData()
}
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return MovieController.movies.count
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 148
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "movieCell", for: indexPath) as! MoviesTableViewCell
let movie = MovieController.movies[indexPath.row]
cell.movieRating.text = String(movie.vote_average)
cell.movieRating.text = movie.overview
cell.movieTitle.text = movie.title
return cell
}
Print Debugging
override func numberOfSections(in tableView: UITableView) -> Int {
print("Number of section called")
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print("Number of rows in section called")
print("Movies count: ", MovieController.movies.count)
return MovieController.movies.count
}
If Number of section called not printed to console: you have issue with tableView and It's DataSource
else if Movies Count: 0: tableView datasource working well and It's your MoviewController.movies issue. Check your MovieController
For the next step I need to see MoviewController content.
First you don't need to make tablevew.delegate = self in UItableViewController its already known , but this not the issue
You should make sure that your datasource MovieController.movies
have data before you call , just print movies before you call
self.tableview.reloadData()
There are number of cases which prevent your cellForRowAt to be called.
If your array MovieController.movies has 0 objects/elements, which you have return as MovieController.movies.count in your numberOfRowsInSection.
If you have placed your UITableView in storyboard or xib and because of any reason your UITableView don't get enough height to show your content in that case also your cellForRowAt will never be called. In most of the cases the height is 0.
I not find what is my problem.
I need to give space between one cell and another.
I wrote self.tableView Storyline.delegate = self because I read that this could be the problem, but not know if it is correct.
This is my code:
class ClassName: UIViewController, UITableViewDataSource, UITabBarControllerDelegate, UITableViewDelegate {
public var notifications: [APINotification] = []
override func viewDidLoad() {
super.viewDidLoad()
self.tabBarController?.delegate = self
tableViewStoryline.rowHeight = UITableViewAutomaticDimension
tableViewStoryline.estimatedRowHeight = 140
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewDidAppear(_ animated: Bool) {
self.notifications = []
self.getLastNotifications()
APIAuth.shared.count_badge = 0
self.tabBarController?.tabBar.items![0].badgeValue = nil
}
public func getLastNotifications() {
let req = Notification()
req.getLastNotifications(onComplete: {events in
self.notifications = events
DispatchQueue.main.async(execute: {
self.tableViewStoryline.delegate = self
self.tableViewStoryline.dataSource = self
self.tableViewStoryline.sectionHeaderHeight = 10
self.tableViewStoryline.reloadData()
})
})
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
// There is just one row in every section
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if self.notifications.count > 4 {
return 4
} else {
return self.notifications.count
}
}
// Set the spacing between sections
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 10
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
cell = tableView.dequeueReusableCell(withIdentifier: "controller")! as UITableViewCell
titleLbl.text = notifications[indexPath.row].title
bodyLbl.text = notifications[indexPath.row].description
typeLbl.text = notifications[indexPath.row].type
return cell!
}
}
Does anyone have any idea what the problem is?
Is there some code missing?
Thanks!
I think this is what you want:
func numberOfSections(in tableView: UITableView) -> Int {
if self.notifications.count > 4 {
return 4
} else {
return self.notifications.count
}
}
// There is just one row in every section
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
Then you have to change also cellForRowAt to take this into account.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
cell = tableView.dequeueReusableCell(withIdentifier: "controller")! as UITableViewCell
titleLbl.text = notifications[indexPath.section].title
bodyLbl.text = notifications[indexPath.section].description
typeLbl.text = notifications[indexPath.section].type
return cell!
}
Instead of having one section with notifications.count rows, you want notifications.count sections and each section with one row. Now setting 10 points as height for section header will make cells appear as having spaces between them.
There are some other options that you can consider, see my other answer.
you are using wrong delegate function.
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat
is used for the hieght of header not for height of cell.
use func tableView(UITableView, heightForRowAt: IndexPath)
you will get correct sized cells.
Hope this helps!
// MARK: UITableViewDelegate
override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String {
print("titleForHeaderInSection: \(collation.sectionTitles[section])")
return collation.sectionTitles[section]
}
override func sectionIndexTitlesForTableView(tableView: UITableView) -> [String] {
print("sectionIndexTitlesForTableView: \(collation.sectionIndexTitles)")
return collation.sectionIndexTitles
}
override func tableView(tableView: UITableView, sectionForSectionIndexTitle title: String, atIndex index: Int) -> Int {
print("sectionForSectionIndexTitle: \(sections.count)")
return collation.sectionForSectionIndexTitleAtIndex(index)
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return (self.results.count > 0) ? self.results.count : 0
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
let numberOfSections = UILocalizedIndexedCollation.currentCollation().sectionTitles.count
print("numberOfSections: \(numberOfSections)")
return numberOfSections
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell:UITableViewCell = tableView.dequeueReusableCellWithIdentifier("contactscell") as UITableViewCell!
let label = cell.viewWithTag(1) as? UILabel
label?.text = self.results[indexPath.row].givenName
return cell
}
It Display all contacts in every sections. I want to show contacts in sorted order with alphabetical index a to z
You're returning self.results.count in numberOfRowsInSection regardless of which section you are in. You have to return the number of rows for each letter. Consider using a dictionary with letters as the keys and contacts as the values.
I'm trying to present an array of names into cells of tableview controller.
Here's the code:
import UIKit
class TableViewController: UITableViewController
{
var names = ["aA", "aB", "cC"]
override func numberOfSectionsInTableView(tableView: UITableView) -> Int
{
return 0
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return names.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCellWithIdentifier("MyCell", forIndexPath: indexPath)
cell.detailTextLabel!.text = names[indexPath.row]
return cell
}
}
When I simulate it, nothing has appeared into the cells!
What's wrong with my Code!
The compiler did not give me any errors.
Update number of sections. Your problem will be solved.
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
why titleForheaderInsection method in different table view controller not work?
I create two table view controllers in one storyboard for my app, with different function, one is SettingsTableViewControlelr, one is CitylistTableViewControlelr, and they should have different section titles.
tableView:titleForHeaderInSection method is used to name section title, but unfortunately only the method in SettingsTableViewControlelr has been appeared correctly in iOS simulator, but the method in CitylistTableViewControlelr is not work, i put a breakpoint on tableView:titleForHeaderInSection method, and find the method even not be called in CitylistTableViewControlelr. Here is my code below:
SettingsTableViewController
import UIKit
class SettingsTableViewController: UITableViewController, UITableViewDataSource, UITableViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, titleForHeaderInSection section:Int) -> String? {
switch section{
case 0:
return"Settings"
default:
return nil
}
}
//the "tableView:titleForHeaderInSection" method in class SettingsTableViewController
//is called and section title appears on simulator.
override func tableView(tableView: UITableView,heightForHeaderInSection section:Int) -> CGFloat {
return 44
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("settingsIdentifier", forIndexPath: indexPath) as! UITableViewCell
return cell
}
}
CitylistTableViewControlelr
import UIKit
class CityListTableViewController: UITableViewController, UITableViewDataSource, UITableViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 2
}
func tableView(tableView: UITableView, titleForheaderInsection section: Int) -> String? {
switch section {
case 0:
return "Top Cities"
case 1:
return "Other Cities"
default:
return nil
}
}
//Putting a breakpoint here, and find "tableView:titleForHeaderInSection" method in
//CityListTableViewController is not even been called, thus the section titles, "Top Cities" & "Other Cities",
//do not appear in simulator.I have tried to add "override" keyword before the method, but the
//complier report error says "Method does not override any method from its superclass".
override func tableView(tableView: UITableView,heightForHeaderInSection section:Int) -> CGFloat {
return 44
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
switch section{
case 0:
return 12
case 1:
return 15
default:
return 0
}
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cityListIdentifier", forIndexPath: indexPath) as! UITableViewCell
switch indexPath.section{
case 0:
cell.textLabel!.text=topCitiesList[indexPath.row]
case 1:
cell.textLabel!.text=otherCitiesList[indexPath.row]
default:
cell.textLabel!.text="unknown"
}
return cell
}
}
My questions are:
Why tableView:titleForHeaderInSection method not be called in CityListTableViewController?
How can I correct my code to make the section title appear on simulator/iPhone respectively?
Have a look at the differences between the two:
In the first view controller where it is being called, the function is being declared like this:
override func tableView(tableView: UITableView, titleForHeaderInSection section:Int) -> String? {
switch section{
Whereas in the one it isn't called it is being declared like this:
func tableView(tableView: UITableView, titleForheaderInsection section: Int) -> String? {
switch section {
You are missing the override declaration. Also, you didn't capitalize the "header" in the second declaration (Thanks for pointing that out Jesper).