Wont show like until refresh of tableview - swift & Firebase - ios

I am fetching all the posts from the users I am following like this:
func observePosts(userID: String) {
let ref = FIRDatabase.database().reference().child("Users").child(userID).child("Wall")
ref.observeEventType(.ChildAdded, withBlock: { (snapshot) in
let postId = snapshot.key
let postReference = FIRDatabase.database().reference().child("feed-items").child(postId)
postReference.observeSingleEventOfType(.Value, withBlock: { (snapshot) in
let update = Sweet(snapshot: snapshot)
self.updates.append(update)
self.updates = self.updates.reverse()
dispatch_async(dispatch_get_main_queue(), {
self.tableView.reloadData()
})
}, withCancelBlock: nil)
}, withCancelBlock: nil)
}
THe problem is, when I click like on one of the posts, the likelabel is not updates. I have a custom class for the cell and in that I have the likeButton action and it is updating the count of likes. It just does not show in the tableView until I refresh the tableview.
How can I get it update the count in real time so I do not need to pull to refresh before I can see that I liked the post?

Related

Updating tableview without reloading the view (Swift, Firebase)

So I am trying to get all of the favourites from a database to show up in a tableview. However, when I favourite a user, it only displays one.
The structure of my database looks like:
Favourites:
UserID:
key: User 1
key: User 2
and my code:
var usersArray[UserClass]()
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(true)
fetchFavourites()
}
func fetchFavourites () {
let userID = Auth.auth().currentUser?.uid
let favouriteRef = self.databaseRef.child("favourites").child(userID!)
favouriteRef.queryOrderedByKey().observe(.childAdded, with: { (snapshot) in
let favouriteID = "\(snapshot.value!)"
let usersRef = self.databaseRef.child("users")
usersRef.observe(.value, with: { (users) in
self.usersArray.removeAll()
for user in users.children {
let user = UserClass(snapshot: user as! DataSnapshot)
if favouriteID == user.uid {
self.usersArray.append(user)
}
self.tableView.reloadData()
}
})
})
}
I have tried creating another array within the function and then making the main array = to that, however it doesn't update the tableview when switching between screens. This code only works when the page view is loaded for the first time. However, I am using a back button that doesn't up date the screen.
Thanks, let me know if you want me to provide anything else.
Edited code (new problem, see below):
func fetchFavourites () {
DispatchQueue.main.async( execute: {
let userID = Auth.auth().currentUser?.uid
var tempFav = [UserClass]()
let favouriteRef = self.databaseRef.child("favourites").child(userID!)
favouriteRef.queryOrderedByKey().observe(.childAdded, with: { (snapshot) in
let favouriteID = "\(snapshot.value!)"
let usersRef = self.databaseRef.child("users")
tempFav.removeAll()
usersRef.observe(.value, with: { (users) in
self.usersArray.removeAll()
for user in users.children {
let user = UserClass(snapshot: user as! DataSnapshot)
if favouriteID == user.uid {
tempFav.append(user)
}
self.usersArray = tempFav
self.tableView.reloadData()
}
})
})
})
}
The problem has been fixed where it populates the tableview with all of the liked users and gets rid of them if I unlike them etc. However, if I unlike all of the users. The array duplicates a user twice even though it should be empty.

Completion handler Firebase observer in Swift

I am making a completion handler for a function which will return a list of objects. When it return value for first time, it works well. But when any change happen into firebase database and again observe gets called, array size gets doubled up. Why it's getting doubled up?
func getStadiums(complition: #escaping ([Stadium]) -> Void){
var stadiums: [Stadium] = []
let stadiumRef = Database.database().reference().child("Stadium")
stadiumRef.observe(.value, with: { (snapshot) in
for snap in snapshot.children {
guard let stadiumSnap = snap as? DataSnapshot else {
print("Something wrong with Firebase DataSnapshot")
complition(stadiums)
return
}
let stadium = Stadium(snap: stadiumSnap)
stadiums.append(stadium)
}
complition(stadiums)
})
}
And calling like this
getStadiums(){ stadiums
print(stadiums.count) // count gets doubled up after every observe call
}
The code you're using declares stadiums outside of the observer. This means any time a change is made to the value of the database reference, you're appending the data onto stadiums without clearing what was there before. Make sure to remove the data from stadiums before appending the snapshots again:
func getStadiums(complition: #escaping ([Stadium]) -> Void){
var stadiums: [Stadium] = []
let stadiumRef = Database.database().reference().child("Stadium")
stadiumRef.observe(.value, with: { (snapshot) in
stadiums.removeAll() // start with an empty array
for snap in snapshot.children {
guard let stadiumSnap = snap as? DataSnapshot else {
print("Something wrong with Firebase DataSnapshot")
complition(stadiums)
return
}
let stadium = Stadium(snap: stadiumSnap)
stadiums.append(stadium)
}
complition(stadiums)
})
}
This line stadiumRef.observe(.value, with: { (snapshot) in ... actually adding an observer that will be called everytime your stadium data is changed.
Because you called it twice by using getStadiums(){ stadiums ..., the total observer added will be 2.
That makes the line stadiums.append(stadium) called twice in the second call.
My suggestion would be to use stadiumRef.observe() once without calling it from getStadiums().
Create a Model as below
class OrderListModel: NSObject {
var Order:String?
var Date:String?
}
Use the below code in the view controller and you should be able to see content in your tableview
func getOrdersData() {
self.orderListArr.removeAll()
let ref = Database.database().reference().child(“users”).child(user).child("Orders")
ref.observe(.childAdded, with: { (snapshot) in
print(snapshot)
guard let dictionary = snapshot.value as? [String : AnyObject] else {
return
}
let orderObj = OrderModel()
orderObj.Order = dictionary[“Order”] as? String
orderObj.Date = dictionary[“Date”] as? String
self.orderListArr.append(orderObj)
self.tableView.delegate = self
self.tableView.dataSource = self
self.tableView.reloadData()
}, withCancel: nil)
}
func ListenForChildrenAdded() {
let registerToListenTo = "YourPathHere"
ref.child(registerToListenTo).observeSingleEvent(of: .value) { (snapshot) in
let initialChildren = snapshot.childrenCount
var incrementer = 0
ref.child(registerToListenTo).observe(.childAdded, with: { (snapshot) in
incrementer += 1
print("snapshot: \(snapshot.key) #\(incrementer)")
if incrementer == initialChildren {
print("-> All children found")
} else if incrementer > initialChildren {
print("-> Child Was Added - Run Some Code Here")
}
})
}}

swift 3 firebase how to compare current user with information in database

I created database with firebase, I got events block and I try to retrieve information which events my user is joined, but I didn't get any answer, could you help me with that?
function to fetch witch events user joined:
func startObersvingDBJoined() {
FIRDatabase.database().reference().child("events").child("peopleWhoJoin").queryOrdered(byChild:"userID").queryEqual(toValue: FIRAuth.auth()!.currentUser!.uid).observe(.value, with: { (snapshot: FIRDataSnapshot) in
var newUpdates = [Event]()
for update in snapshot.children {
let updateObject = Event(snapshot: update as! FIRDataSnapshot)
newUpdates.append(updateObject)
}
self.updates2 = newUpdates
self.sectionData[1] = self.updates2
self.tableView.reloadData()
}) { (err) in
print(err.localizedDescription)
}
}
I am tring to compare uid in DB peopleWhoJoined and current user uid, but I didn't get anything.
DB:

How to cancel a firebase observe single event database call

In my iOS app, a user is able to add friends by searching for there unique username.
The user types the username in a textField and I have a textFieldDidChange notification which is fired every time the text changes.
Within that method I then call the Firebase method below to check if the username exists.
func searchFor(_ username: String) {
guard let uid = FIRAuth.auth()?.currentUser?.uid else {
return
}
let lowercaseUsername = username.lowercased()
let ref = FIRDatabase.database().reference()
ref.child(FirebaseDatabaseBranchNames.usernames.rawValue).child(lowercaseUsername).observeSingleEvent(of: .value, with: { [unowned self](snapshot) in
if snapshot.exists() {
if let usernameUid = snapshot.value as? String {
self.isUserAlreadyAFriend(ref, uid: uid, usernameUid: usernameUid)
}
} else {
// username doesn't exist
}
}, withCancel: nil)
}
How can I cancel this method, before performing it again?
When you attach a listener/observer, Firebase returns a handle for that observer. You can subsequently remove the listener/observer by calling ref.removeObserverWithHandle().
So assuming you want at most one observer, you can keep the reference and observer handle in a member field of you class and then use this code in the searchFor method:
if (self.searchHandle != nil) {
self.searchRef.removeObserverWithHandle(searchHandle)
}
self.searchRef = ref.child(FirebaseDatabaseBranchNames.usernames.rawValue).child(lowercaseUsername)
self.searchHandle = self.searchRef.observeSingleEvent(of: .value, with: { [unowned self](snapshot) in
if snapshot.exists() {
if let usernameUid = snapshot.value as? String {
self.isUserAlreadyAFriend(ref, uid: uid, usernameUid: usernameUid)
}
} else {
// username doesn't exist
}
}, withCancel: nil)
Be aware that you won't be saving data transfer with this though, as the most likely result is that the database client simply drops the data that it gets back from the server.
Better you add the "removeAllObservers()" after the observe single event block. It is working for me.
let ref = Database.database().reference().ref.child(XXXX).child(YYYYY)
ref.observeSingleEvent(of: .value, with: { (snapshot) in
}else{
}
}) { (error) in
print(error.localizedDescription)
}
ref.removeAllObservers()

Weird error when getting posts from Firebase - swift

I have a weird error that I do not know how to solve, let me explain:
(I should say there is more code before the following, if you want to see)
for i in 0..<self.followings.count {
let following = self.followings[i]
print("\(following.Id) and \(self.followings.count)")
FIRDatabase.database().reference().child("feed-items").queryOrderedByChild("profilePhoto").queryEqualToValue(following.Id).observeEventType(.Value, withBlock: { (snapshot: FIRDataSnapshot) in
var newUpdates = [Sweet]()
for update in snapshot.children {
let updateObject = Sweet(snapshot: update as! FIRDataSnapshot)
newUpdates.append(updateObject)
}
self.updates = newUpdates.reverse()
print(self.updates.count)
self.tableView.reloadData()
}) { (error: NSError) in
print(error.description)
}
}
This is my code for showing posts from users that currentUser is following, in my feed (UITableView). The problem is when someone is clicking the like button, the person which post was liked will double every time currentUser clicks like.
I can prevent that from happening if I mode this line of code: var newUpdates = [Sweet]() up before viewDidLoad. But if I do so then the feed will only show posts from one of the users that currentUser is following - even if I am following two users or more.
So how can I show all posts from users I am following and NOT duplicate when clicking like on one of their posts? Let me know if you need more code :-)

Resources