UITableViewCell out of bounds but in debugging has bounds - ios

I created a tableView section for each day in my app. In simulator when I add data from beginning (tableview empty) it shows OK all the data, the section's name is the day, everything OK but when I change the date from my settings and add a new input I get an error that when I create the cell, it's out of bounds. I set some prints to see if its out of bounds and it seems to be in bounds but I don't know why I get this error
Code:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "expenseCell") as? ExpenseCell else { return UITableViewCell() }
print("SECTION: \(daySections[indexPath.section].daySection)")
print("ROWS: \(daySections[indexPath.section].contentCount)")
let budget = userBudget[indexPath.section][indexPath.row] // <- error getting here
cell.delegate = self
cell.configureCell(budget: budget)
return cell
}
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle {
return UITableViewCellEditingStyle.none
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return Int(daySections[section].contentCount)
}
func numberOfSections(in tableView: UITableView) -> Int {
return daySections.count
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return daySections[section].daySection
}
Debug:
SECTION: Optional("21.10.2017")
ROWS: 2
SECTION: Optional("21.10.2017")
ROWS: 2
SECTION: Optional("22.10.2017")
ROWS: 1
fatal error: Index out of range
2017-10-16 15:41:30.284173+0300 Expense Manager[7877:380262] fatal error: Index out of range
(lldb)
I also set prints to show me indexPath.section and indexPath.row and when I get the error they are section: 1; row: 0.

Related

Error after cell insertion: invlalid number of sections

After receiving a new object, I call this func to insert a cell:
private func addCellToTheTop(recipe: Recipe) {
guard let recipeTableView = self.recipeTableView else { return }
recipesForShow.insert(recipe, at: 0)
recipeTableView.beginUpdates()
recipeTableView.insertRows(at: [IndexPath.init(row: 0, section: 0)], with: .automatic)
recipeTableView.endUpdates()
}
But I get an error
Why the number of section does not match?
If it is important:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func numberOfSections(in tableView: UITableView) -> Int {
return recipesForShow.count
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return TableCellConfig.spaceBetweenCells
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView = UIView()
headerView.backgroundColor = UIColor.clear
return headerView
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//...
}
You are getting this exception because you are appending a new element to the array that is being used to determine the numberOfSection whereas you are inserting a new row into the tableView. To fix this you need to insert section instead of inserting new row, here's how:
recipeTableView.insertSections([0], with: .automatic)

iOS: Multiple Section in TableView not working

I am working on an app in which I need to show multiple rows with a header. In my case only one section is showing. I have searched everything but can't find a suitable solution.
Here is my code:
class Timeline: UITableViewCell {
#IBOutlet weak var timelineData: UITextView!
}
class StudenTimelineViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
let section = ["pizza", "deep dish pizza", "calzone"]
let items = [["Margarita", "BBQ Chicken", "Peproni"], ["sausage", "meat lovers", "veggie lovers"], ["sausage", "chicken pesto", "prawns & mashrooms"]]
override func viewDidLoad() {
super.viewDidLoad()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items[section].count
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return section.count
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return self.section[section]
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TimelineId", for: indexPath) as! Timeline
let gpsData = items[indexPath.section][indexPath.row]
cell.timelineData.text = gpsData
return cell
}
func tableView(tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return 40
}
What I am getting
How will I get all the sections. Thanks in advance.
This is because your method name func numberOfSectionsInTableView(tableView: UITableView) -> Int is incorrect and hence not called.
Replace the name with func numberOfSections(in tableView: UITableView) -> Int and see the magic happen.
//MARK: - Table view data source
func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return 3
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "tableviewCell", for: indexPath)
cell.selectionStyle = UITableViewCellSelectionStyle.none
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
{
return UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat
{
return UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView?
{
let cell: UITableViewCell
cell = tableView.dequeueReusableCell(withIdentifier: "tableviewHeader")!
cell.selectionStyle = UITableViewCellSelectionStyle.none
cell.backgroundColor = UIColor.white
return cell
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 32;
}

UITableView Section Index Out Of Bounds but it's not really out of bounds

Whenever I run the app, the tableView has no data, waiting for user to input. The problem is that if the numberOfSections is 1, it works just fine, but when I change it to 2 it crashes because Index out of range
func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "expenseCell") as? ExpenseCell else { return UITableViewCell() }
let budget = userBudget[indexPath.section][indexPath.row]
cell.delegate = self
cell.configureCell(budget: budget)
return cell
}
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle {
return UITableViewCellEditingStyle.none
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return userBudget[section].count // <- Crash here
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return "Practice with Sections \(section)"
}
It is because you are accessing index 1 of userBudget while i assume it contains 0 index only.
This crash happens cause your array userBudget, don't has two elements at the moment you try access his second position.
You must guard that userBudget has two elements on minimium...
You should that you must to assign value to userBudget on your ViewDidLoad.
You are saying that you will have two section to your tableView's delegate, but you have an array which contains only one array. Basically when you try to reach userBadget[1] in your numberOfRowsInSection function and it crashes because it doesn't exist.
Replace
func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
With
func numberOfSections(in tableView: UITableView) -> Int {
return userBudget.count
}

how to set background color of the cells which are selected on section tableview

how to set background color of the cells which are selected on section tableview
every section or genre should have single selected cell only enter image description here
SEE Image description PLZ
I know how to select single cell in table view but here I wanted for every section only one select cell
this my code
var sections = [
Sections(genre: "🦁 Animation",
movies: ["The Lion King", "The Incredibles"],
expanded: false),
Sections(genre: "💥 Superhero",
movies: ["Guardians of the Galaxy", "The Flash", "The Avengers", "The Dark Knight"],
expanded: false),
Sections(genre:"👻 Horror",
movies: ["The Walking Dead", "Insidious", "Conjuring"],
expanded: false)
]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
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 {
return sections[section].movies.count
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 44
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if(sections[indexPath.section].expanded){
return 44
}else{
return 0
}
}
func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return 2
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let header = ExpandableHeaderView()
header.customInit(title: sections[section].genre, section: section, delegate: self)
return header
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "labelCell")!
cell.textLabel?.text = sections[indexPath.section].movies[indexPath.row]
return cell
}
////////////
func tableView(_ tableView: UITableView, shouldHighlightRowAt indexPath: IndexPath) -> Bool {
return true
}
func tableView(_ tableView: UITableView, didHighlightRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath)
//let cell = tableView.dequeueReusableCell(withIdentifier: "labelCell")!
cell?.contentView.backgroundColor = UIColor.red
//cell?.backgroundColor = UIColor.red
}
func tableView(_ tableView: UITableView, didUnhighlightRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath)
//let cell = tableView.dequeueReusableCell(withIdentifier: "labelCell")!
cell?.contentView.backgroundColor = UIColor.white
//cell?.backgroundColor = UIColor.blue
}
////////////
func toggleSection(header: ExpandableHeaderView, section: Int) {
sections[section].expanded = !sections[section].expanded
tableView.beginUpdates()
for i in 0 ..< sections[section].movies.count{
tableView.reloadRows(at: [IndexPath(row: i , section: section)], with: .automatic)
}
tableView.endUpdates()
}
What you can do is a complete use of the delegate functions provided by the table view:
Inside func tableView(UITableView, didSelectRowAt: IndexPath) you can check the section and row that has been selected. You will also need to check a constant check on the var indexPathsForSelectedRows: [IndexPath]? array that this returns.
Now that you have a. the current selection b. the list of seelections,
you can go ahead and delete/add data into your final array as required.
So in your case, inside func tableView(UITableView, didSelectRowAt: IndexPath) you will check if the indexPathsForSelectedRows has the section+row count already. If it does, then simply play with the highlighting in the tableView: UITableView, didHighlightRowAt indexPath: IndexPath) and then change the array that stores the list of selected movies accordingly. If not simply add it.

How to perform a dynamic creation of sections and cells to a UITableView in SWIFT 3

I've got a sample code but rows per section won't show, since numberOfRowsInSection doesn't exist in SWIFT 3 anymore.
I currently have the ff code:
let section = ["pizza", "deep dish pizza", "calzone"]
let items = [["Margarita", "BBQ Chicken", "Pepperoni"], ["sausage", "meat lovers", "veggie lovers"], ["sausage", "chicken pesto", "prawns", "mushrooms"]]
override func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? {
return self.section[section]
}
override func numberOfSections(in tableView: UITableView) -> Int {
return self.section.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "tableCell", for: indexPath)
// Configure the cell...
cell.textLabel?.text = self.items[indexPath.section][indexPath.row]
return cell
}
Result:
Can someone show the correct code for updated swift 3? Thanks!
For your information numberOfRowsInsection exists in swift3, see below
override func numberOfSections(in tableView: UITableView) -> Int {
return section.count
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items[section].count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell")
cell?.textLabel?.text = items[indexPath.section][indexPath.row]
return cell!
}
Thanks:)

Resources