I'm trying to retrieve data from my Firebase database, about the number of "effects" contained as a number
in my posts
collection. I want this data to update every time the effectIsTapped
function is called. Then, I want the array to update. Currently, I am removing all elements from the EffectsLabelArray
, before adding data. But, without fail, this produces a "Fatal Error: Index out of range", at the line:
let effects = self.effectsLabelArray[indexPath.row]
Below I detail my code:
var titleArray: [String] = []
var usernameArray: [String] = []
var contentArray: [String] = []
var postedTimeArray: [Any] = []
var effectsLabelArray: [Int] = []
var profileImageArray: [String] = []
var postIDArray: [Int] = []
var followingList: [String] = []
var documents: [DocumentSnapshot] = []
let db = Firestore.firestore()
let currentUserID = Auth.auth().currentUser?.uid
// Find the UserIDs of people following
// Where Field for those UserIDs in "Posts"
override func viewDidLoad() {
super.viewDidLoad()
// getFollowingPosts()
configureTableView()
getFollowingPosts()
}
func getFollowingPosts() {
db.collection("iAmFollowing").document(currentUserID!).getDocument { (document, error) in
if error != nil {
print("ERROR")
} else {
if let document = document, document.exists {
let followedUID = document.get("uid") as? String
self.db.collection("posts").whereField("uid", isEqualTo: followedUID!).getDocuments { (documents, error) in
for documents in documents!.documents {
let title = documents.get("Title") as! String
let content = documents.get("Content") as! String
let username = documents.get("username") as! String
let postID = documents.get("postID")
let counter = documents.get("counter")
self.titleArray.append(title)
self.contentArray.append(content)
self.usernameArray.append(username)
self.postIDArray.append(postID as! Int)
self.effectsLabelArray.append(counter as! Int)
print(self.titleArray)
self.tableView.reloadData()
}
}
}
}
}
}
func configureTableView() {
tableView.delegate = self
tableView.dataSource = self
// remove separators for empty cells
tableView.tableFooterView = UIView()
// remove separators from cells
tableView.separatorStyle = .none
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
titleArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "PostCell", for: indexPath) as! PostCell
db.collection("iAmFollowing").document(currentUserID!).getDocument { (document, error) in
if let document = document, document.exists {
let followedUID = document.get("uid") as! String
self.db.collection("posts").whereField("uid", isEqualTo: followedUID).getDocuments { (documents, error) in
for documents in documents!.documents {
let counter = documents.get("counter") as! Int
self.effectsLabelArray.append(counter)
let postID = self.postIDArray[indexPath.row]
let title = self.titleArray[indexPath.row]
let content = self.contentArray[indexPath.row]
let username = self.usernameArray[indexPath.row]
let effects = self.effectsLabelArray[indexPath.row]
cell.titleLabel.text = title
cell.contentLabel.text = content
cell.usernameLabel.text = username
cell.postIDLabel.text = String(postID)
cell.effectsLabel.text = String(effects)
}
}
//Get effects
//Append Effects
//Set title to indexPath.row
//Set them to cell label
}
}
return cell
}
@IBAction func effectsButtonIsTapped(_ sender: Any) {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) {
self.effectsLabelArray.removeAll()
self.tableView.reloadData()
}
}
// Do any additional setup after loading the view.
@IBAction func removeEffectIsTapped(_ sender: Any) {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) {
self.effectsLabelArray.removeAll()
self.tableView.reloadData()
}
}
@IBAction func logoutIsTapped(_ sender: Any) {
try! Auth.auth().signOut()
let loginDialogueViewController = storyboard?.instantiateViewController(withIdentifier: "LoginDialogueViewController")
let navigationController = UINavigationController(rootViewController: loginDialogueViewController!)
let share = UIApplication.shared.delegate as? AppDelegate
share?.window?.rootViewController = navigationController
share?.window?.makeKeyAndVisible()
navigationController.modalPresentationStyle = .fullScreen
present(navigationController, animated: false)
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
}
*/
}
If anyone can answer this for me, I would be greatly appreciative.
First, try not to call reloadData()
on a loop. That might cause unwanted side effect. Try to add everything up to the array while querying the db, after all of the data is in the array, only then you call the reloadData()
. As it will invalidate everything in the UITableView
and re-load all the necessary data and cells.
The same goes while you are displaying the cell tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
. Only set the property of the cell after everything fetched from the db, do not access the UI level repeatedly. That can cause hitch and your app un-responsive for a period of time. Will go exponentially as the data grows.
Then, effectsLabelArray
got edited in other places as well, then you can never be sure the count nor the size of that array. Instead of getting via self.effectsLabelArray[indexPath.row]
try using self.effectsLabelArray[safe: index.row]
. Then you can add extra handling when the expected value are not there.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.