Reputation: 67
I am creating an app that uses a database, and am using labels to display the information. I first created a label that has date information, and when I ran the app it worked properly. When I added a second label for the away team information, I ran it and got an error that said : "Thread 1 Fatal Error : Index Out Of Range." Would this be related to the database, or the table view itself?
import UIKit
import Firebase
class srFootballViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var ref = DatabaseReference()
var Date = [String]()
var awayTeam = [String]()
var databaseHandle:DatabaseHandle = 0
var databaseHandle2:DatabaseHandle = 0
@IBOutlet var footballTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
ref = Database.database().reference()
databaseHandle = ref.child("Dates").observe(.childAdded) { (snapshot) in
let post = snapshot.value as? String
if let actualPost = post {
self.Date.append(actualPost)
self.footballTableView.reloadData()
}
}
databaseHandle2 = ref.child("awayTeams").observe(.childAdded) { (snapshot) in
let post2 = snapshot.value as? String
if let actualPost2 = post2 {
self.awayTeam.append(actualPost2)
self.footballTableView.reloadData()
}
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return Date.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let footballCell = tableView.dequeueReusableCell(withIdentifier: "footballCell") as! srFootballCell
footballCell.date.text = Date[indexPath.row]
footballCell.awayTeam.text = awayTeam[indexPath.row]
return(footballCell)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Upvotes: 1
Views: 485
Reputation: 285069
First of all do not use Date
as a variable name. Date
is a reserved word for a Swift struct. Swift variable names are supposed to start with a lowercase letter anyway.
The error occurs because the observe
methods work asynchronously and you are using two different arrays at data source.
At the moment you are calling reloadData
in the first observe
completion block awayTeam
is still empty and accessing item 0 causes the crash.
The solution is to call reloadData()
only in the second ovserver or – more reliable – use DispatchGroup
to notify when all database operations are completed. Apart from that it's highly recommended to use a custom struct as data source rather than multiple arrays.
Upvotes: 1
Reputation: 7948
Your awayTeam
and Date
arrays have different count of items - be sure to have same amount in order to prevent this crash - even better, create an object that will contain both of them.
Also, do NOT name your variable Date
as it would conflict with Date class.
Upvotes: 1
Reputation: 1507
First you don't name a variable starting with capital letter. Second since you're using two different arrays for loading data in table view, awayTeam is crashing your app, because it doesn't have as many elements as Date array, because you're using Date.count for number of rows in section.
Change
databaseHandle = ref.child("Dates").observe(.childAdded) { (snapshot) in
let post = snapshot.value as? String
if let actualPost = post {
self.Date.append(actualPost)
self.footballTableView.reloadData()
}
}
to
databaseHandle = ref.child("Dates").observe(.childAdded) { (snapshot) in
let post = snapshot.value as? String
if let actualPost = post {
self.Date.append(actualPost)
}
}
So you won't reload table view data before loading awayTeam data.
Upvotes: 1