I made API Request and wanted to add it in Table View. Is realoadData() being called earlier than the loading of data?. There is an issue with tableView because the API call is working fine. Below is the code :
class ViewController: UIViewController {
var tableView : UITableView!
var listOfHolidays = [HolidayDetails](){
didSet{
DispatchQueue.main.async{
self.tableView.reloadData()
self.navigationItem.title = "(self.listOfHolidays.count) Holidays found"
}
}
}
calling Fetch Function in ViewDidLoad.
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
DataFetch { (holidaydetails) in
for items in holidaydetails{
self.listOfHolidays.append(items)
print(items)
}
}
}
Fetch Function for API Call.
func DataFetch(completionHandler : @escaping ([HolidayDetails]) -> Void){
guard let url = URL(string: "https://holidayapi.com/v1/holidays? pretty&country=IN&year=2020&key=457d9815-2e0a-4140-9515-0f6ef0d5f8b9") else{return(print("Error"))}
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
guard let data = data else{ return print("Error")}
do{
let holidayData = try JSONDecoder().decode(Holidays.self, from: data)
let holidayDetail = holidayData.holidays
completionHandler(holidayDetail)
}
catch{
let error = error
print(error.localizedDescription)
}
}
task.resume()
}
}
Extensions:
extension ViewController : UITableViewDataSource,UITableViewDelegate {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return listOfHolidays.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell",for: indexPath)
let holidays = listOfHolidays[indexPath.row]
cell.textLabel?.text = holidays.name
cell.detailTextLabel?.text = holidays.date
return cell
}
}
I also have another file with Data Model :
import Foundation
struct Holidays : Codable {
var holidays : [HolidayDetails]
}
struct HolidayDetails : Codable {
var name : String
var date : String
}
2
Answers
Your tableView is nil:
var tableView : UITableView!
You just need to initialize it, for example like this:
var tableView = UITableView()
Also you just learned that it is not good practice to use !.
As @Larme commented, the problem is very likely in your
didSet
oberserver.Somewhere, you set the listOfHolidays to a value before the view of that controller did load, e.g. before the
tableView
outlet is connected to theUITableView
.Updating the UI from within a setter is not always a good idea. But if you really want it, you could circumvent the crash by checking if the tableView is
nil
:There should be no reload issue with this code: if
tableView
isnil
,reloadData
will not be called, but this does not matter, because as soon as the outlet is connected (beforeviewDidLoad
), it reloading will be triggered by itself.