my dataSource is empty, so it crash. it worked well in iOS 14
[iOS 15]The tableView(_:numberOfRowsInSection:) is called before the numberOfSections(in tableView: UITableView)
How do you set the dataSource of the table view? On the storyboard? Or setting it in viewDidLoad() with code?
i just define the dataSource in the Class
You said:
i just define the dataSource in the Class
Are you also settings the tableView's datasource to this property?
(It looks like you aren't)
Otherwise...
For both functions, zero is a valid return value...
...so that suggests there may be a problem with the property you are accessing?
You said:
my dataSource is empty
It's not clear what you mean by this.
If it's really empty, isn't a crash an appropriate response?
• Are you sure that both methods are being called?
• Have you checked the Int value that they return?
• Are you checking to see that datasource[section] exists, before you reference it?!
you declare
var dataSource = [Merchant]()
So it is empty.
Then you should crash when calling dataSource[section] where section is zero.
I do not see where you populate the dataSource.
Thanks for your replies, finally i find if i set tableView.tableHeaderView, tableView.estimatedSectionHeaderHeight tableView.delegate = self and tableView.dataSource = self before setting tableView.frame, it will call numberOfRowsInSection first and get the Index out of range error.
Then i place tableView.delegate = self and tableView.dataSource = self below the tableView.frame, it calls numberOfSections first and do not call numberOfRowsInSection. Commenting one of the tableView.tableHeaderView and tableView.estimatedSectionHeaderHeight also work well.
this is the complete code.
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
let dataSource = [[String]]()
let tableView = UITableView(frame: .zero, style: .plain)
override func viewDidLoad() {
super.viewDidLoad()
let bounds = UIScreen.main.bounds
tableView.tableHeaderView = UIView()
// tableView.tableFooterView = UIView()
tableView.estimatedSectionHeaderHeight = 0
// tableView.estimatedSectionFooterHeight = 0
// before frame
tableView.delegate = self
tableView.dataSource = self
tableView.frame = CGRect(x: 0, y: 0, width: bounds.width, height: bounds.height)
// after frame
// tableView.delegate = self
// tableView.dataSource = self
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
view.addSubview(tableView)
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dataSource[section].count
}
func numberOfSections(in tableView: UITableView) -> Int {
return dataSource.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell")!
return cell
}
}