I am working on a Forum that will have an unlimited number of topics created by users. So for performance I'd like to fetch only 20 topics or so at a time. When the user goes to the bottom of the Table View we should fetch 20 more and so on.
The problem is I am currently sorting the topics AFTER I fetch all of them from Firebase and I am having a hard time having them ordered correctly directly on Firebase BEFORE I fetch them and that's the only way I can see this working.
The topics are ordered by "last-post" which is a string on Firebase that I convert to Date and reorder after I pull from Firebase.
func fetchTopicsFromFirebase(){
guard let cat = self.currentCategory else {return}
DataService.ds.Topics_Base.child(cat.key).observe(.value, with: { (snapshot) in
if let snapshots = snapshot.children.allObjects as? [FIRDataSnapshot] {//snapshots = all topics
self.allTopics = []
for top in snapshots{
if let dict = top.value as? Dictionary<String,AnyObject>{
guard let title = dict["title"] as? String else {continue}
guard let text = dict["text"] as? String else {continue}
guard let time = dict["time"] as? String else {continue}
guard let username = dict["username"] as? String else {continue}
let newTopic = Topic(subject: title, text: text, time: time, topicKey: top.key, username: username)
if let lastPost = dict["last-post"] as? String{
newTopic.lastPostTime = HelperMethods.convertStringToDate(myString: lastPost)
}
if let email = dict["email"] as? String{
let validEmail = HelperMethods.removeSpecialCharactersFromEmail(email: email)
DataService.ds.Users_Base.child(validEmail).observeSingleEvent(of: .value, with: {(snapshot) in
if let userDict = snapshot.value as? Dictionary<String,AnyObject>{
if let imgUrl = userDict["profile_image_url"] as? String{
newTopic.opImageUrl = imgUrl
}
self.allTopics.append(newTopic)
self.allTopics.sort { $0.lastPostTime! > $1.lastPostTime!}//lastPostTime is a Date object
if (self.allTopics.count == snapshots.count){
self.tableView.reloadData()
}
}
})
}
}
}
}
}
)
}
Thanks in advance for any help.
Related
Hello i am creating Chat App Using Swift And Firebase i am fetching messages and populating in tableview but when i send new message then tableview dislplaying multiple entry i am useing below code for fetching messages
func fetchAllMessage(){
guard let uid = Auth.auth().currentUser?.uid else { return }
let fetchMsgGroup = Database.database().reference().child("user-messages_group_iOS").child(uid).child(self.chatID)
fetchMsgGroup.observe(.value, with: { (snapshot) in
if snapshot.exists(){
if let dictonary = snapshot.value as? [String:AnyObject]{
self.groupMessageData.removeAll()
if let userMessages = dictonary["userMessages"] as? [String:AnyObject]{
for (key, _) in userMessages{
let messagesFrtchRef = Database.database().reference().child("messages_iOS").child(key)
messagesFrtchRef.observe(.value, with: { (snapshot1) in
if snapshot1.exists(){
if let dict = snapshot1.value as? [String:AnyObject]{
let fromId = dict["fromId"] as! String
let messageUID = dict["messageUID"] as! String
let seen = dict["seen"] as! Bool
let status = dict["status"] as! String
let text = dict["text"] as! String
let timestamp = dict["timestamp"] as! Double
let told = dict["told"] as! String
let messages = GroupMessage(fromId: fromId, messageUID: messageUID, seen: seen, status: status, text: text, timestamp: timestamp, told: told)
self.groupMessageData.insert(messages, at: 0)
}
self.tblListView.reloadData()
}else{
}
}, withCancel: nil)
}
}
}
}else{
}
}, withCancel: nil)
}
i have tried everything like clearing removing also clearing observer when needed but its not work enough for me is their anyone have any solution for this then please help me
can anyone help me to solve this out
I am manually entering in data into my database and the only variable not getting passed from my database is the author and I do not know where I am going wrong.
func getAllArticles(handler: #escaping (_ articles: [Article])-> ()){
var articleArray = [Article]()
REF_ARTICLES.observeSingleEvent(of: .value) { (articleMessageSnapshot) in
guard let articleMessageSnapshot = articleMessageSnapshot.children.allObjects as? [DataSnapshot] else {return}
for article in articleMessageSnapshot {
let content = article.childSnapshot(forPath: "content").value as? String ?? "no content"
let author = article.childSnapshot(forPath: "author").value as? String ?? "no author"
let twitterHandle = article.childSnapshot(forPath: "twitterHandle").value as? String ?? "none"
let articleTitle = article.childSnapshot(forPath: "articleTitle").value as? String ?? "no title"
let date = article.childSnapshot(forPath: "date").value as? String ?? "no date"
let article = Article(content: content, author: author, twitterHandle: twitterHandle, ArticleTitle: articleTitle, date: date)
articleArray.append(article)
}
handler(articleArray)
}
}
Please check out below code
var articleArray = [Article]()
//REF_ARTICLES
let ref = Database.database().reference().child(“articles”)
ref.observe(.childAdded, with: { (snapshot) in
print(snapshot)
guard let dictionary = snapshot.value as? [String : AnyObject] else {
return
}
let articleObj = Article()
articleObj.Content = dictionary["content"] as? String
articleObj.Author = dictionary["author"] as? String
articleObj.Twitterhandle = dictionary["twitterHandle"] as? String
articleObj.Title = dictionary["articleTitle"] as? String
articleObj.Date = dictionary["date"] as? String
self. articleArray.append(articleObj)
}, withCancel: nil)
}
I am also working on similar app where i am storing data to firebase and retrieving. Below approach i used to fetch the data from firebase database. Please try once.
func getAllArticles(handler: #escaping (_ articles: [Article])-> ()) {
Database.database().reference().child("Articles").observe(.childAdded, with: { (snapshot) in
print("articles = \(snapshot)")
if let dict = snapshot.value as? [String: Any] {
let article = Article()
article.articleTitle = dict["articleTitle"] as? String
article.author = dict["author"] as? String
article.twitterHandle = dict["twitterHandle"] as? String
article.date = dict["date"] as? String
article.content = dict["content"] as? String
self.articleArray.append(article)
}
handler(articleArray)
}, withCancel: nil)
}
im not sure what the underlying issue was, but i fixed it by deleting "author" from the firebase tree and then adding it back
I was trying to retrieve data from firebase. I can retrieve data from a single child. But how can I retrieve data from many child?
I tried this way
func fatchSchdual(){
ref.child("Products").child(productdetailes[myIndex].userId!).child("Schedule").child("0").observeSingleEvent(of: .value) { (snapshot) in
if snapshot.childrenCount > 0{
for Schdu in snapshot.children.allObjects as! [DataSnapshot]{
let schdual = Schdu.value as? [String: AnyObject]
let startTime = schdual?["start"]
let endTime = schdual?["end"]
if let StartTime = startTime{
self.publishTime.text = StartTime as? String
}
}
}
}
}
but I didn't get any data.
func fatchFacilities(){
ref.child("Products").child(productdetailes[myIndex].userId!).child("Facility").observeSingleEvent(of: .value) { snapshot in
for child in snapshot.children {
if let value = (child as! DataSnapshot).value as? [String : Any] {
let name = value["name"] as? String
let unit = value["unit"] as? String
let facility = Facility(name: name, unit: unit)
facilities.append(facility)
}
}
}
}
I'm Trying to check if the rooms's value 'Owner' equals to the current user id if so then fetch all data including the key value and continue checking other children of 'rooms'
I was trying, but I fail finding the solution though it might seem easy so please help me with your suggestions or ideas. My code so far :
Database.database().reference().child("rooms").queryOrdered(byChild: "Owner").observeSingleEvent(of: .value, with: { (snapshot) in
let currentUser = Auth.auth().currentUser?.uid
if !snapshot.exists() {
print("No data found")
return
}
var rooms = snapshot.value as! [String:AnyObject]
let roomKeys = Array(rooms.keys)
for roomKey in roomKeys {
guard
let value = rooms[roomKey] as? [String:AnyObject]
else
{
continue
}
let title = value["title"] as? String
let description = value["description"] as? String
let roomPictureUrl = value["Room Picture"] as? String
let longitude = value["Longtitude"] as? String
let latitude = value["Latitude"] as? String
let dateFrom = value["Date From"] as? String
let dateTo = value["Date To"] as? String
let owner = value["Owner"] as? String
let myRooms = Room(roomID: roomKey,title: title!, description: description!, roomPicutreURL: roomPictureUrl!, longitude: longitude!, latitude: latitude!, dateFrom: dateFrom!, dateTo: dateTo!, owner: owner!)
self.rooms.append(myRooms)
self.tableView.reloadData()
print(snapshot.value)
}
})
You're missing the value in your query:
Database.database().reference()
.child("rooms")
.queryOrdered(byChild: "Owner")
.queryEqual(toValue: "STbz...")
.observeSingleEvent(of: .value, with: { (snapshot) in
See for this and more query operators, the documentation on filtering data.
Mark:- Swift 5
Database.database().reference().child("user")
.queryOrdered(byChild: "UserPhoneNumber") //in which column you want to find
.queryEqual(toValue: "Your phone number or any column value")
.observeSingleEvent(of: .value, with: { (snapshot) in
if snapshot.childrenCount > 0
{
if let snapShot = snapshot.children.allObjects as? [DataSnapshot] {
//MARK:- User Exist in database
for snap in snapShot{
//MARK:- User auto id for exist user
print(snap.key)
break
}
}
}
else if snapshot.childrenCount == 0
{
//MARK:- User not exist no data found
}
})
How do I get data from a child deeper into a database that has an unknown name?
My example structure is below.
This code works (to get the snapshot data) but I am hardcoding the second child. I will not always know this value (Bus 1).
let ref = FIRDatabase.database().reference()
let usersRef = ref.child("Trips").child("Bus 1")
usersRef.observeSingleEvent(of: .value, with: { (snapshot) in
for snap in snapshot.children {
let userSnap = snap as! FIRDataSnapshot
let uid = userSnap.key //the uid of each user
let userDict = userSnap.value as! [String:AnyObject] //child data
let personOn = userDict["getOn"] as! String
print("key = \(uid) is at getOn = \(personOn)")
}
})
This will print:
key = Stop 1 is at getOn = 3
key = Stop 2 is at getOn = 7
Should I be structuring this differently? Flatter?
Thanks and let me know of any questions.
This is a more preferable way as I have a class for TripDetails which goes into an array to load into the table. But again, I do not know what the second child's name is.
FIRDatabase.database().reference().child("Trips").child("Bus 1").observe(.childAdded, with: { (snapshot) in
if let dictionary = snapshot.value as? [String: AnyObject] {
let trip = TripDetails()
trip.setValuesForKeys(dictionary)
self.trips.append(trip)
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
print(snapshot)
}, withCancel: nil)
I'm still not super sure what data you want exactly. If all you want is all the data you can just do this.
let ref = FIRDatabase.database().reference().child("Trips")
ref.observeSingleEvent(of: .value, with: { snapshot in
let enumerator = snapshot.children
while let bus = enumerator.nextObject() as? FIRDataSnapshot {
print("\(bus.key)")
let enumerator = bus.children
while let stop = enumerator.nextObject() as? FIRDataSnapshot {
let stopDict = stop.value as? [String: Any]
let uid = stop.key
let personOn = stopDict?["getOn"] as? String
print("key = \(uid) is at getOn = \(personOn)")
}
}
})