I am creating a chat room app. Currently, when users signs in they are given their own table view to upload data too.
Instead of each user having their own personal table view I would like all users to be connected to one (public) table view so everyone can see what's posted. Hence a chat room app.
These are 3 separate logins and what it looks like for each user when they post a message:
This is what I want. To have each tableview cell represent a different message from a different user. All publicly viewed on one tableview. Not on separate table views:
How can I make the table view public? When I log in as a different user I would like the previous message to still be there from each user. Hence a chat room.
{
"rules": {
"Users":{
".read": "true",
".write": "true"
},
"general_room" : {
".read": "true",
".write": "true"
}
}
}
GeneralChatroom.swift
import UIKit
import Foundation
import Firebase
import FirebaseDatabase
import FirebaseStorage
struct postStruct {
let username : String!
let message : String!
let photoURL : String!
}
class GeneralChatroom: UIViewController, UITableViewDataSource, UITableViewDelegate, UITextFieldDelegate {
#IBOutlet weak var messageTextField: UITextField!
var generalRoomDataArr = [postStruct]()
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 140
let ref = FIRDatabase.database().reference()
let userID = FIRAuth.auth()?.currentUser?.uid
ref.child("general_room").child("chat").child(userID!).queryOrderedByKey().observe(.childAdded, with: {snapshot in
let snapDict = snapshot.value as? NSDictionary
let username = snapDict?["Username"] as? String ?? ""
let message = snapDict?["Message"] as? String ?? ""
let firebaseUserPhotoURL = snapDict?["photo_url"] as? String ?? ""
self.generalRoomDataArr.insert(postStruct(username: username, message: message, photoURL: firebaseUserPhotoURL), at: 0)
self.tableView.reloadData()
})
}
#IBAction func backButtonPressed(_ sender: UIButton) {
self.performSegue(withIdentifier: "BackToRoom", sender: nil)
}
//Message Send button is pressed data uploaded to firebase
#IBAction func sendButtonPressed(_ sender: UIButton) {
let message : String = self.messageTextField.text!
UploadGeneralChatRoom(message: message) //upload to general_room
self.messageTextField.text = nil
messageTextField.resignFirstResponder()//Quit keyboard
self.tableView.reloadData() //Reload tableView
//UploadUserData() //Update Rank in database
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return generalRoomDataArr.count // your number of cell here
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell")
let usernameLabel = cell?.viewWithTag(1) as! UILabel
usernameLabel.text = generalRoomDataArr[indexPath.row].username
let messageLabel = cell?.viewWithTag(2) as! UILabel
messageLabel.numberOfLines=0 // line wrap
messageLabel.lineBreakMode = NSLineBreakMode.byWordWrapping
messageLabel.text = generalRoomDataArr[indexPath.row].message
//initialize UI Profile Image
let imageView = cell?.viewWithTag(3) as! UIImageView
//Make Porfile Image Cirlce
imageView.layer.cornerRadius = imageView.frame.size.width/2
imageView.clipsToBounds = true
//User Profile image in tableview
if generalRoomDataArr[indexPath.row].photoURL != nil
{
//let imageView = cell?.viewWithTag(3) as! UIImageView
if let url = NSURL(string: generalRoomDataArr[indexPath.row].photoURL) {
if let data = NSData(contentsOf: url as URL) {
imageView.image = UIImage(data: data as Data)
}
}
}
// your cell coding
return cell!
}
}//END CLASS
Upload to firebase
import Foundation
import Firebase
import FirebaseDatabase
import FirebaseStorage
func UploadGeneralChatRoom(message : String) {
//Firebase Initialization
var ref: FIRDatabaseReference!
//var storage: FIRStorageReference!
let userID = FIRAuth.auth()?.currentUser?.uid
ref = FIRDatabase.database().reference()
//storage = FIRStorage.storage().reference()
//Get Data from database resend to database
ref.child("Users").child(userID!).observeSingleEvent(of: .value, with: {(snapshot) in
let snapDict = snapshot.value as? NSDictionary
let username = snapDict?["Username"] as? String ?? ""
let firebaseUserPhotoURL = snapDict?["photo_url"] as? String ?? ""
ref.child("general_room").child("chat").child(userID!).childByAutoId().setValue(["Username": username, "uid": userID!, "Message" : message, "photo_url" : firebaseUserPhotoURL])
})
}
I don't know how your firebase database is setup but you are posting to child("Users").child(userID!)
but reading from
child("general_room").child("chat").child(userID!)
You would need to read and write to the same location.
Also:
try to safely unwrap your optional values:
if let userId = userID {
ref.child("Users").child(userId).observeSingleEvent(of: .value, with: {(snapshot) in
let snapDict = snapshot.value as? NSDictionary
let username = snapDict?["Username"] as? String ?? ""
let firebaseUserPhotoURL = snapDict?["photo_url"] as? String ?? ""
ref.child("general_room").child("chat").child(userID!).childByAutoId().setValue(["Username": username, "uid": userID!, "Message" : message, "photo_url" : firebaseUserPhotoURL])
})
}
Related
I am creating a tableview with one cell, and retrieving data from Firebase to display as a label firstName. The data is being retrieved (I have checked by using a print statement) however the label is not showing up, even though alpha is set to 1. Any help would be much appreciated.
Here is my code:
import FirebaseDatabase
import FirebaseStorage
import FirebaseAuth
import SwiftKeychainWrapper
class userTableViewController: UITableViewController {
var profileData = [profileStruct]()
let storageRef = Storage.storage().reference()
var databaseRef = Database.database().reference()
var ref: DatabaseReference?
var firstName = ""
var lastName = ""
var email = ""
var phoneNumber = ""
override func viewDidLoad() {
super.viewDidLoad()
getProfile()
// Do any additional setup after loading the view.
// tableView.register(profileCell.self, forCellReuseIdentifier: "ProfileCell")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
struct profileStruct {
let email : String!
let phoneNumber : String!
let firstName : String!
let lastName : String!
}
#IBAction func signOut(_ sender: Any) {
KeychainWrapper.standard.removeObject(forKey: "uid")
do {
try Auth.auth().signOut()
} catch let signOutError as NSError {
print ("Error signing out: %#", signOutError)
}
dismiss(animated: true, completion: nil)
}
func getProfile() {
let databaseRef = Database.database().reference()
databaseRef.child("users").queryOrderedByKey().observeSingleEvent(of: .childAdded, with: {
snapshot in
self.firstName = ((snapshot.value as? NSDictionary)!["firstname"] as? String)!
self.lastName = ((snapshot.value as? NSDictionary)!["lastname"] as? String)!
self.email = ((snapshot.value as? NSDictionary)!["email"] as? String)!
self.phoneNumber = ((snapshot.value as? NSDictionary)!["phone number"] as? String)!
print(self.firstName)
DispatchQueue.main.async {
self.tableView.reloadData()
}
})
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
// tableView.dequeueReusableCell(withIdentifier: "PostCell")!.frame.size.height
return 500
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "ProfileCell") as? profileCell else { return UITableViewCell() }
cell.firstNameLabel?.text = "first name: " + firstName
cell.lastNameLabel?.text = "last name: " + lastName
cell.emailLabel?.text = "email: " + email
cell.phoneNumberLabel?.text = "phone number: " + phoneNumber
return cell
}
}
Add a breakpoint on guard let cell = tableView.dequeueReusableCell(withIdentifier: "ProfileCell") as? profileCell else { return UITableViewCell() }, you need to check whether the as? profileCell is successful, and check whether the Data Source is invoked.
If the first step is working, you need to check the profileCell UI layout. Open the Debug View Hierarchy, and check whether any cell on tableView.
func getProfile() {
let databaseRef = Database.database().reference()
databaseRef.child("users").queryOrderedByKey().observeSingleEvent(of: .childAdded, with: {
snapshot in
self.firstName = ((snapshot.value as? NSDictionary)!["firstname"] as? String)!
self.lastName = ((snapshot.value as? NSDictionary)!["lastname"] as? String)!
self.email = ((snapshot.value as? NSDictionary)!["email"] as? String)!
self.phoneNumber = ((snapshot.value as? NSDictionary)!["phone number"] as? String)!
print(self.firstName)
self.tableView.dataSource = self
self.tableView.delegate = self
self.tableView.reloadData()
})}
You seem to show the email instead of the first name here.
cell.emailLabel?.text = "email: " + firstName
cell.phoneNumberLabel?.text = "phone number: " + lastName
cell.firstNameLabel?.text = "first name: " + email
cell.lastNameLabel?.text = "last name: " + phoneNumber
I'm trying to fetch specific user messages from Firebase Real-Time database.I want to fill chatLogTableView with the user messages.I'm fetching user messages datas from firebase with fetchCurrentUserMessages() function.
In this function :
self.messagesDatas.append(message)
print(self.messagesDatas)
When i try to print the self.messagesDatas its okay.But when the tableview trying to retrieve self.messagesDatas.count for numberOfRowsInSection i'm getting 0 count.Why this is happening ?
Here is my code :
import UIKit
import Firebase
class ChatLogCustomCell: UITableViewCell {
#IBOutlet weak var leftLabel: UILabel!
#IBOutlet weak var rightLabel: UILabel!
}
class ChatLogViewController: UIViewController,UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var chatLogTableView: UITableView!
#IBOutlet weak var messageTextField: UITextField! // bu kismi elle yazman gerekebilir cunku xcode bu messagetextfield i sanki view in icinde oldugu icin table view icinde algilayamayabilir
#IBOutlet weak var backButton: UINavigationItem!
var usersDataFromChatScreen = [User]()
var selectedUserToIDFromChatScreen = ""
var isTeacherFromChatScreen = ""
var messagesDatas = [Message]()
var messagesDictionary = [String : Message]()
override func viewDidLoad() {
super.viewDidLoad()
chatLogTableView.delegate = self
chatLogTableView.dataSource = self
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return messagesDatas.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = chatLogTableView.dequeueReusableCell(withIdentifier: "chatLogCell") as! ChatLogCustomCell
let message = messagesDatas[indexPath.row]
cell.leftLabel.text = message.text
cell.rightLabel.text = message.text
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 80.0
}
#IBAction func sendButtonTouchOnInside(_ sender: Any) {
let ref = Database.database().reference().child("messages")
let childRef = ref.childByAutoId()
let toID = selectedUserToIDFromChatScreen
Auth.auth().addStateDidChangeListener { (auth, user) in
let fromID = auth.currentUser?.uid
let values = ["text" : self.messageTextField.text, "toID" : toID, "fromID" : fromID] as [String : Any]
childRef.updateChildValues(values) { (error, ref) in
if error != nil {
print(error ?? "")
return
}
guard let messageID = childRef.key else { return }
let userMessagesRef = Database.database().reference().child("user-messages").child(fromID!).child(messageID)
userMessagesRef.setValue(1)
let recipientUserMessagesRef = Database.database().reference().child("user-messages").child(toID).child(messageID)
recipientUserMessagesRef.setValue(1)
}
}
}
func fetchCurrentUserMessages() {
guard let uid = Auth.auth().currentUser?.uid else {
return
}
if self.isTeacherFromChatScreen == "no" {
let ref = Database.database().reference().child("user-messages").child(uid)
ref.observe(.childAdded) { (snapshot) in
let messageID = snapshot.key
let messagesRef = Database.database().reference().child("messages").child(messageID)
messagesRef.observeSingleEvent(of: .value) { (snapshot) in
guard let dictionary = snapshot.value as? [String: AnyObject] else {
return
}
let message = Message()
let toID = dictionary["toID"] as? String ?? "toID not found"
let messageText = dictionary["text"] as? String ?? "Text not found"
let fromID = dictionary["fromID"] as? String ?? "fromID not found"
message.toID = toID
message.text = messageText
message.fromID = fromID
self.messagesDatas.append(message)
print(self.messagesDatas.count)
}
}
}
else {
}
}
}
Reload your tableview when you get data from server
func fetchCurrentUserMessages() {
guard let uid = Auth.auth().currentUser?.uid else {
return
}
if self.isTeacherFromChatScreen == "no" {
let ref = Database.database().reference().child("user-messages").child(uid)
ref.observe(.childAdded) { (snapshot) in
let messageID = snapshot.key
let messagesRef = Database.database().reference().child("messages").child(messageID)
messagesRef.observeSingleEvent(of: .value) { (snapshot) in
guard let dictionary = snapshot.value as? [String: AnyObject] else {
return
}
let message = Message()
let toID = dictionary["toID"] as? String ?? "toID not found"
let messageText = dictionary["text"] as? String ?? "Text not found"
let fromID = dictionary["fromID"] as? String ?? "fromID not found"
message.toID = toID
message.text = messageText
message.fromID = fromID
self.messagesDatas.append(message)
print(self.messagesDatas.count)
DispatchQueue.main.async {
chatLogTableView.reloadData()
}
}
}
}
else {
}
}
I'm having trouble displaying all of the followers of user on a table view cell with their profile picture and full name (similar to instagram).
A snippet of my firebase JSON structure is:
"followers" : {
"FoFQDAGGX9hntBiBdXYCBHd8yas2" : {
"CjeP35ceAQZJuUPhm7U1eF3Yq4F3" : true,
"FjS4wUpXAUa5aWwXkjvujHxE4He2" : true,
"Gmg1ojNoBiedFPRNSL4sBZz2gSx2" : true,
"PqMkClaPM3W8k7ZSgzAHb3yne5D3" : true,
"buS4recuDpdg60ckFqwjoU344TC2" : true
},
"users" : {
"CjeP35ceAQZJuUPhm7U1eF3Yq4F3" : {
"email" : "bbbb#gmail.com",
"fullname" : "Bbbb",
"profileImageUrl" : "https://firebasestorage.googleapis.com/v0/b/pinion-4896b.appspot.com/o/profile_image%2FCjeP35ceAQZJuUPhm7U1eF3Yq4F3?alt=media&token=0449c633-b397-4452-b2df-41f3a5390084",
"work" : "Nottingham",
},
Code in the table view cell (FollowersTableViewCell):
#IBOutlet weak var followersProfileImage: UIImageView!
#IBOutlet weak var followersNameLabel: UILabel!
var user: UserModel? {
didSet {
updateView()
}
}
func updateView() {
followersNameLabel.text = user?.fullname
if let photoUrlString = user?.profileImageUrl {
let photoUrl = URL(string: photoUrlString)
followersProfileImage.sd_setImage(with: photoUrl, placeholderImage: UIImage(named: "placeholderImg"))
}
}
EDIT:
Code in view controller (FollowersViewController)
#IBOutlet weak var tableView: UITableView!
var users: [UserModel] = []
func loadusers() {
let ref = Database.database().reference()
guard let currentUser = Auth.auth().currentUser?.uid else { return }
var followersNames = [String]()
var profileImage = [String]()
let followersRef = ref.child("followers").child(currentUser) //retreives all nodes in the following node
followersRef.observe(DataEventType.value, with: { snapshot in
print(snapshot.children.allObjects)
for child in snapshot.children { //build the array of keys
let snap = child as! DataSnapshot
let key = snap.key
let userRef = ref.child("users").child(key) //get the user name and profile image from the users node
userRef.observeSingleEvent(of: .value, with: { snapshot in
let followersName = snapshot.childSnapshot(forPath: "fullname").value as! String
let followersProfileImageUrl = snapshot.childSnapshot(forPath: "profileImageUrl").value as! String
print(followersName)
print(followersProfileImageUrl)
followersNames.append(followersName)
profileImage.append(followersProfileImageUrl)
self.tableView.reloadData()
})
}
})
}
extension FollowersViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return users.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "FollowersTableViewCell", for: indexPath) as! FollowersTableViewCell
let user = users[indexPath.row]
cell.user = user
return cell
}
}
Now the code runs and the profile picture and fullname of the followers are printed on the console but doesn't show anything on the table view of the app - thanks in advance :)
Update:
User model definition
class UserModel {
var email: String?
var work: String?
var profileImageUrl: String?
var fullname: String?
var id: String?
}
extension UserModel {
static func transformUser(dict: [String: Any], key: String) -> UserModel {
let user = UserModel()
user.email = dict["email"] as? String
user.work = dict["work"] as? String
user.profileImageUrl = dict["profileImageUrl"] as? String
user.fullname = dict["fullname"] as? String
user.id = key
return user
}
}
Your TableView does not display any data because you don't populate users array at any point.
I might want to instantiate an UserModel object in observeSingleEvent implementation, add the object to users array and invoke reloadData (or insertRows) method also right after that. (Instead of outside the implementation block)
As requested, here is a quick (and dirty) way to create an user object and refresh the UI
let user = UserModel()
user.fullname = snapshot.childSnapshot(forPath: "fullname").value as? String
user.profileImageUrl = snapshot.childSnapshot(forPath: "profileImageUrl").value as? String
self.users.append(user)
self.tableView.reloadData()
I am building an app which uses Firebase's database service. I am trying to load the data into a table view but I am unable to do so. I can't seem to figure out what's going wrong. The code is also not giving me any errors. I've checked the database permissions on Firebase and they seem to be good. Here's my code:
import UIKit
import Firebase
struct postStruct {
let word : String!
let wordType : String!
}
class sentenceBuilderViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var wordSearchBar: UISearchBar!
#IBOutlet weak var wordsTableView: UITableView!
var posts = [postStruct]()
override func viewDidLoad() {
wordsTableView.reloadData()
getWordsFromDatabase()
super.viewDidLoad()
wordsTableView.delegate = self
wordsTableView.dataSource = self
}
func getWordsFromDatabase() {
let databaseRef = Database.database().reference()
databaseRef.child("wordList").queryOrderedByKey().observeSingleEvent(of: .childAdded, with: {
snapshot in
let word = (snapshot.value as? NSDictionary)!["word"] as? String
let wordType = (snapshot.value as? NSDictionary
)!["wordType"] as? String
self.posts.insert(postStruct(word: word, wordType: wordType), at: 0)
})
wordsTableView.reloadData()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return posts.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = wordsTableView.dequeueReusableCell(withIdentifier: "Cell")
let wordLabel = cell?.viewWithTag(1) as! UILabel
wordLabel.text = posts[indexPath.row].word
let wordTypeLabel = cell?.viewWithTag(2) as! UILabel
wordTypeLabel.text = posts[indexPath.row].wordType
return cell!
}
}
Any help and inputs would be appreciated! Thanks!
The problem is that you are just observing a single event here:
databaseRef.child("wordList").queryOrderedByKey().observeSingleEvent(of: .childAdded, with: {
snapshot in
What this does is that it justs goes through your database and once it finds any child, it displays that one without going further. What you need to do is change it to observe like this:
func getAllWordsFromDatabase() {
let databaseRef = Database.database().reference()
databaseRef.child("wordList").queryOrderedByKey().observe(.childAdded, with: {
snapshot in
let word = (snapshot.value as? NSDictionary)!["word"] as? String
let wordType = (snapshot.value as? NSDictionary)!["wordType"] as? String
self.posts.append(postStruct(word: word, wordType: wordType))
DispatchQueue.main.async {
self.wordsTableView.reloadData()
}
})
}
Try implementing this and it should work.
Move the "getWordsFromDatabase()" line in "viewDidLoad" function to AFTER you assign the delegate and data source, like this:
override func viewDidLoad() {
super.viewDidLoad()
wordsTableView.delegate = self
wordsTableView.dataSource = self
getWordsFromDatabase()
}
Also you can try to add a "reloadData()" method in the databaseRef block on the main queue, like this:
let databaseRef = Database.database().reference()
databaseRef.child("wordList").queryOrderedByKey().observeSingleEvent(of: .childAdded, with: {
snapshot in
let word = (snapshot.value as? NSDictionary)!["word"] as? String
let wordType = (snapshot.value as? NSDictionary
)!["wordType"] as? String
self.posts.insert(postStruct(word: word, wordType: wordType), at: 0)
DispatchQueue.main.async {
wordsTableView.reloadData()
}
})
I was making an app for one of my family members so that they could better manage their clients but ran into some issues. This is my first time using Firebase and I just can't seem to get my code to work! The part in which I am getting stuck involves Firebase's Realtime Database, and I am working in XCode 8.3 with Swift 3.1.
Code:
import UIKit
import FirebaseCore
import FirebaseDatabase
import FirebaseAuth
var specClientId = ""
class MyCell: UITableViewCell {
#IBOutlet var nameCell: UILabel!
#IBOutlet var statusCell: UILabel!
}
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet var tableView: UITableView!
var ref: FIRDatabaseReference!
var tableArray: [String] = []
var clientId: [String] = []
var statusArray:[String] = []
#IBAction func signOut(_ sender: Any) {
UserDefaults.resetStandardUserDefaults()
performSegue(withIdentifier: "segueBackLogin", sender: self)
}
public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tableArray.count
}
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CellFront") as! MyCell
cell.nameCell.text = tableArray[indexPath.row]
cell.statusCell.text = statusArray[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
specClientId = clientId[indexPath.row]
ref.child("Users").child(specClientId).child("lastUpdate").removeValue()
performSegue(withIdentifier: "segue", sender: self)
}
override func viewDidLoad() {
super.viewDidLoad()
if FIRApp.defaultApp() == nil {
FIRApp.configure()
}
ref = FIRDatabase.database().reference()
ref.child("Users").observeSingleEvent(of: .value, with: { (snapshot) in
let value = snapshot.value as? NSDictionary
let specificValues = value?.allKeys
self.tableArray.removeAll()
self.statusArray.removeAll()
self.clientId.removeAll()
var it = 0
for Uservalue in specificValues! {
self.tableArray.append("")
self.statusArray.append("")
self.clientId.append(Uservalue as! String)
self.ref.child("Users")
.child(Uservalue as! String)
.child("name")
.observeSingleEvent(of: .value, with: { (snapshot) in
let nameValue = snapshot.value as? String
self.tableArray.insert(nameValue!, at: it)
self.tableArray = self.tableArray.filter {$0 != ""}
self.tableView.reloadData()
}) { (error) in
print(error.localizedDescription)
}
self.ref.child("Users")
.child(Uservalue as! String)
.child("lastUpdate")
.observeSingleEvent(of: .value, with: { (snapshot) in
if let nameValue = snapshot.value as? String {
self.statusArray.insert("*", at: it)
self.tableView.reloadData()
} else {
self.statusArray.insert("", at: it)
self.tableView.reloadData()
}
}) { (error) in
print(error.localizedDescription)
}
it += 1
}
}) { (error) in
print(error.localizedDescription)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
My main issue is that when I get the user's name and their lastUpdate status, the array lists do not match up correctly and the TableView displays the wrong information in terms of which User has submitted their updates. To fix this issue, I tried to use the insert method in my arrays but now the app crashes. Previously, I was using the append method but that leads to the wrong information being displayed in the TableView. I would appreciate it if any of you could help me with this issue.
Note: The App Crashes due to the StatusArray not having the same amount of elements as the TableArray. This is caused by the TableArray having some empty elements with no names in them.
Thanks,
KPS
Edit 1:
for Uservalue in specificValues! {
self.clientId.append(Uservalue as! String)
let user = User()
self.ref.child("Users")
.child(Uservalue as! String)
.observeSingleEvent(of: .value, with: { (snapshot) in
let nameValue = snapshot.value as? NSDictionary
let specNameValue = nameValue?.allKeys
var i = 0
while i < specNameValue!.count {
if specNameValue?[i] as? String == "name" {
user.name = nameValue?.allValues[i] as! String
} else if specNameValue?[i] as? String == "lastUpdate" {
user.status = "*"
} else if specNameValue?[i] as? String != "name" && specNameValue?[i] as? String != "lastUpdate" && specNameValue?[i] as? String != "message" && specNameValue?[i] as? String != "adminMessage" && specNameValue?[i] as? String != "photoURL" {
user.status = ""
}
i += 1
}
}) { (error) in
print(error.localizedDescription)
}
self.tableArray.append(user)
self.tableView.reloadData()
}
The main reason your app is crashing is because in your cell for row you are reloading after loading the first user and the cell expects the statusArray to have elements already.
cell.nameCell.text = tableArray[indexPath.row]
cell.statusCell.text = statusArray[indexPath.row] // fails here I assume
There a few issues going on here that I'll try to address.
You are reloading the table immediately for each child that is iterated through. It would be smart to append elements to each array then once completed display all elements by calling tableView.reloadData()
Are status' independent of the name that you are expecting? If the data is correlated, it would be smart to create a simple Object to house this data and have a single array of data that the tableView will use for it's dataSource
Once your data is fully loaded, you could sort the data accordingly then reload the datasource to solve the issue of pulling data from the server that is out of order. This is why the append(element: ) is simple and useful
Hopefully this helps! It may seem like a bit more work but it would definitely be beneficial to performance, organization and readability for yourself.