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
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
database structure
I am trying to get an array of users(strings) from a comment, but am having trouble since it is kinda deep in my database, here is the implementation I've tried, it is returning 0 for the count.
REF_FEEDMESSAGES.child(messageKey).child("comments").observeSingleEvent(of: .value) { (commentSnapshot) in
guard let commentSnapshot = commentSnapshot.children.allObjects as? [DataSnapshot] else {return}
for comment in commentSnapshot {
let theComment = comment.value as? [String: Any]
let theContent = theComment?["content"] as? String ?? ""
let theIcon = theComment?["icon"] as? String ?? ""
let theColor = theComment?["color"] as? String ?? ""
let theDate = theComment?["date"] as? String ?? "0"
let theName = theComment?["userName"] as? String ?? ""
let theVerified = theComment?["isVerified"] as? String ?? "no"
let profileImageURL = theComment?["profileImageURL"] as? String ?? ""
let postedBy = theComment?["postedBy"] as? String ?? ""
let likes = theComment?["likes"] as? String ?? ""
let key = comment.key
let likers = comment.childSnapshot(forPath: "likedBy").value as? [String] ?? []
print(likers.count)
guard let likers = comment.childSnapshot(forPath: "likedBy").children.allObjects as? [DataSnapshot] else {return}
for like in likers {
let theLike = like.value as? [String:Any]
print(theLike!["user"] as? String ?? "")
commentLiked.append(theLike!["user"] as? String ?? "")
}
I have this function that is grabbing events from firebase that a specific user is attending. Everything seems to be working up until the point where I try to alter an element relative to the event snapshot.
I get the error
Cannot assign to property: 'event' is a 'let' constant
//will show the vents that a user is attending
static func Events(for user: User, completion: #escaping ([Event]) -> Void)
{
var currentEvents = [Event]()
//Getting firebase root directory
let ref = Database.database().reference().child("users").child(user.uid).child("Attending")
ref.observe(.value, with: { (snapshot) in
// print(snapshot)
// guard snapshot.children.allObjects is [DataSnapshot] else {
// return completion([])
// }
guard let eventDictionary = snapshot.value as? [String: Any] else {
return completion([])
}
// print(snapshot)
let dispatchGroup = DispatchGroup()
eventDictionary.forEach({ (key,value) in
// print(key)
// print(value)
EventService.show(forEventKey: key , completion: { (event) in
dispatchGroup.enter()
AttendService.isEventAttended(event, byCurrentUserWithCompletion: { (isAttended) in
//error happens here
event?.isAttending = isAttended
dispatchGroup.leave()
})
currentEvents.append(.init(currentEventKey: key , dictionary: (event?.eventDictionary)!))
completion(currentEvents)
})
})
})
}
It is really confusing to me because I can't see where I declared it as a let constant.
This is the code for the method I am using to gather event info
static func show(forEventKey eventKey: String, completion: #escaping (Event?) -> Void) {
// print(eventKey)
let ref = Database.database().reference().child("events").child(eventKey)
// print(eventKey)
//pull everything
ref.observeSingleEvent(of: .value, andPreviousSiblingKeyWith: { (snapshot,eventKey) in
// print(snapshot.value ?? "")
guard let event = Event(snapshot: snapshot) else {
return completion(nil)
}
completion(event)
})
}
Below is my model for an event object
import Foundation
import FirebaseDatabase.FIRDataSnapshot
struct Event: Keyed {
var key: String?
let currentEventName: String
let currentEventImage: String
let currentEventPromo: String?
let currentEventDescription: String
//nested properties
let currentEventStreetAddress: String
let currentEventCity: String
let currentEventState: String
let currentEventDate: String?
let currentEventTime: String?
let currentEventEndTime: String?
let currentEventZip: Int
var category: String
//nested properties stop
var currentAttendCount: Int
var isAttending = false
var eventDictionary: [String: Any]{
let dateDict = ["start:date":currentEventDate, "start:time": currentEventTime,"end:time":currentEventEndTime]
return ["event:name":currentEventName,"event:imageURL" : currentEventImage,
"event:description": currentEventDescription, "attend:count": currentAttendCount,
"event:street:address": currentEventStreetAddress,"event:zip": currentEventZip,
"event:state": currentEventState, "event:city": currentEventCity, "event:promo": currentEventPromo ?? "", "event:date": dateDict, "event:category":category]
}
init(currentEventKey: String, dictionary: [String:Any]) {
self.key = currentEventKey
self.currentEventName = dictionary["event:name"] as? String ?? ""
self.currentEventImage = dictionary["event:imageURL"] as? String ?? ""
self.currentEventDescription = dictionary["event:description"] as? String ?? ""
self.currentEventPromo = dictionary["event:promo"] as? String ?? ""
self.currentAttendCount = dictionary["attend:count"] as? Int ?? 0
self.category = dictionary["event:category"] as? String ?? ""
//nested properties
self.currentEventStreetAddress = dictionary["event:street:address"] as? String ?? ""
self.currentEventCity = dictionary["event:city"] as? String ?? ""
self.currentEventState = dictionary["event:state"] as? String ?? ""
self.currentEventZip = dictionary["event:zip"] as? Int ?? 0
let eventDate = dictionary["event:date"] as? [String: Any]
self.currentEventDate = eventDate?["start:date"] as? String ?? ""
self.currentEventTime = eventDate?["start:time"] as? String ?? ""
self.currentEventEndTime = eventDate?["end:time"] as? String ?? ""
}
init?(snapshot: DataSnapshot) {
guard let dict = snapshot.value as? [String : Any],
let currentEventName = dict["event:name"] as? String,
let currentEventImage = dict["event:imageURL"] as? String,
let currentEventDescription = dict["event:description"] as? String,
let currentEventPromo = dict["event:promo"] as? String,
let category = dict["event:category"] as? String,
let currentEventStreetAddress = dict["event:street:address"] as? String,
let currentEventCity = dict["event:city"] as? String,
let currentEventState = dict["event:state"] as? String,
let currentEventZip = dict["event:zip"] as? Int,
let currentAttendCount = dict["attend:count"] as? Int,
let eventDate = dict["event:date"] as? [String: Any],
let currentEventDate = eventDate["start:date"] as? String,
let currentEventTime = eventDate["start:time"] as? String,
let currentEventEndTime = eventDate["end:time"] as? String
else { return nil }
self.key = snapshot.key
self.currentEventName = currentEventName
self.currentEventImage = currentEventImage
self.currentEventDescription = currentEventDescription
self.currentEventStreetAddress = currentEventStreetAddress
self.currentEventCity = currentEventCity
self.currentEventState = currentEventState
self.currentEventZip = currentEventZip
self.currentAttendCount = currentAttendCount
self.currentEventPromo = currentEventPromo
self.currentEventDate = currentEventDate
self.currentEventTime = currentEventTime
self.currentEventEndTime = currentEventEndTime
self.category = category
}
}
Event is a struct, so its instances are passed by value. That is, the call completion(event) passes a copy of event to completion.
Since completion doesn't take the Event as an inout, it is treated as a let, not a var, so you cannot modify it.
You could change the type of completion to #escaping (inout Event?) -> Void. Then the Event will be treated as a var, and changes to it will be effectively copied back out to the caller.
However, that won't make a difference in your case, because you're creating a brand new Event instance for the call to completion (by saying guard let event = Event(snapshot: snapshot)). So even if you let completion modify the Event it receives, you just throw it away after. You also need to write it back to your database somehow after completion returns, if you want the change to isAttending to have any effect.
Please anyone who would show me how to include the snapshot key value along with children value that I already append to my array (forgot to include it and now remember I have to) ... aside from that something really I couldn't understand when I tried to solve my own issue, by testing the value first by using this method: print(rooms.popFirst().key!) half of my database values got nil value ?!! and if I don't include that method everything works fine anyways if you can't imagine that nonetheless I really wish your suggestion or advice for getting all data with their own key value...
This is my code so far:
Database.database().reference().child("rooms").observe(.value, with: { (snapshot) in
print()
var rooms = snapshot.value as! [String:AnyObject]
for(_,value) in rooms {
if (rooms.popFirst()?.key) != nil{
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: "XXX",title: title!, description: description!, roomPicutreURL: roomPictureUrl!, longitude: longitude!, latitude: latitude!, dateFrom: dateFrom!, dateTo: dateTo!, owner: owner!)
//print(rooms.popFirst()?.key)
self.rooms.append(myRooms)
self.tableView.reloadData()
}
}
})
Try this:
Database.database().reference().child("rooms").observe(.value, with: { (snapshot) in
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: "XXX",title: title!, description: description!, roomPicutreURL: roomPictureUrl!, longitude: longitude!, latitude: latitude!, dateFrom: dateFrom!, dateTo: dateTo!, owner: owner!)
print(roomKey)
self.rooms.append(myRooms)
self.tableView.reloadData()
}
}
})
To get the key from snapshot you can use following lines of code it will give you result like -> Kqwewsds12 -> your child Details
let dictValues = [String](snapshot.keys)
print(dictValues[0]) //Output -- Kqwewsds12
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.