I am trying to list all the users from a firebase node in a table view (this is working) but would then like to remove the current user from the list (this is not working).
I've tried to use removeValue() but it still ran with the current user on the table view - also I don't want to remove the user from firebase
I then tried to make it run only if the the user autoId is not equal to the current users Id but it still shows up on the table view cell
Would appreciate any help :)
My firebase structure is like this:
"users" : {
"8x1SGi2P0KVOKm4i60JQLP1bdU63" : {
"fullname" : "bbbb",
"profileImageUrl" : "https://firebasestorage.googleapis.com/v0/b/pinion-4896b.appspot.com/o/profile_image%2F8x1SGi2P0KVOKm4i60JQLP1bdU63?alt=media&token=7932b14f-c2d8-46fd-9dd1-c607217fe8d3",
},
"B7rwHiCTlphZjKXfPSEzkIwl8RH2" : {
"fullname" : "Aaaa ",
"profileImageUrl" : "https://firebasestorage.googleapis.com/v0/b/pinion-4896b.appspot.com/o/profile_image%2FB7rwHiCTlphZjKXfPSEzkIwl8RH2?alt=media&token=072e1f41-935e-430d-af99-dc640381f8e6",
},
"FRuuk20CHrhNlYIBmgN4TTz3Cxn1" : {
"fullname" : "eeee",
"profileImageUrl" : "https://firebasestorage.googleapis.com/v0/b/pinion-4896b.appspot.com/o/profile_image%2FFRuuk20CHrhNlYIBmgN4TTz3Cxn1?alt=media&token=bf89b903-a51a-4d6d-bdef-fe2667d78842",
},
Code to which lists users:
func observeUsers(completion: #escaping (UserModel) -> Void) {
REF_USERS.observeSingleEvent(of: .childAdded, with: { snapshot in
if let dict = snapshot.value as? [String: Any] {
let user = UserModel.transformUser(dict: dict, key: snapshot.key)
//line below used first to remove value from listing on table view
//Api.User.REF_USERS.child("users").child(Api.User.CURRENT_USER!.uid).removeValue()
//line below - if user autoID is not equal to the current user then list
if user.id != Api.User.CURRENT_USER?.uid {
completion(user)
}
}
})
}
EDIT:
func loadUsers() {
var allUsers = [String]()
Api.User.REF_USERS.observe(.value, with: { snapshot in
for child in snapshot.children { //build the array of keys
let snap = child as! DataSnapshot
let key = snap.key
allUsers.append(key)
print(allUsers)
}
})
}
instead of removing try this
create model of your tabledata
then create an empty array of it
while fetching the data append all except that which has same currentuser.uid
then reload the tableview this will show all the data except the current user
this is the code as promised:
but this need a little modification in your database
make your database like this
"users":{
"childbyautid":{
"fullname": "name",
"profileimageurl": "your url",
"userid": "userid"
}
then you can write like this
var myArr = [String]()
Database.database().reference.child("users").observe(.value){(snapshot) in
if snapshot.childcount > 1 { self.myArr.removeAll()
for data in snapshot.children.allObjects as! [DataSnapshot]{
if let d = data.value as? [string: any]{
if Auth.auth.currentuser.uid != d["userid"]{
myArr.append(d["name"]}else{print("this is the user itself"}}}
You can control this in you loadUsers by adding userId check like below
func loadUsers() {
var allUsers = [String]()
Api.User.REF_USERS.observe(.value, with: { snapshot in
for child in snapshot.children { //build the array of keys
let snap = child as! DataSnapshot
let key = snap.key
if key != currentUser.id{
allUsers.append(key)
}
print(allUsers)
}
})
}
Related
Im trying to retrieve a specific node in all my children and want to collect all the "role" in every child under "Users"
Here is the database setup:
Users:
25TWFD7SLmQ3onRUdffvfx6Nfmw1:
role: "officer"
9OwM6FIPZgOKu3zzVYSrkPWR0Ij2
role: "advisor"
How can I retrieve all of the "role" nodes?
here you can get the particular node "role".
//To get the all record
let ref = Database.database().reference()
ref.child("Users").childByAutoId().queryOrdered(byChild: "role").observeSingleEvent(of: .value) { (snapshot) in
//To check the data
guard let userDict = snapshot.value as? [String:Any] else {
return
}
let keyArray = [String] (userDict.keys)
for key in keyArray {
if var dataDict = userDict[key] as? [String:Any] {
self.userRoleArray.append(dataDict)
}
}
}
Hopefully this will work for you.
happy coding...
I have an array of strings which is the "uid's" of users. I am trying to append data/children to these multiple "uid's". Adding children or updating children to individual parents/users is easy and I understand how to do it. The problem is that this array can either contain 1 uid or 50 uid's. Is it possible for me to take these uid's and then update them with the same value? I am unsure what code to provide since I am just trying everything to attack this.
With the code below, this is me send a message to other users.
Array of uid strings
var data = [String]()
Sample code of me sending a message to 2 users, just wanted to provide something here to show I know how to update/save data
private func sendMessageWithProperties(_ properties: [String: Any]) {
let businessRef = Database.database().reference().child("Business Group Chats Messages").child((group?.uid)!).child((Auth.auth().currentUser?.uid)!)
let ref = Database.database().reference().child("Business Group Chats Messages").child((Auth.auth().currentUser?.uid)!).child((group?.businessName)!)
let businesChildRef = businessRef.childByAutoId()
let childRef = ref.childByAutoId()
let fromID = Auth.auth().currentUser!.uid
let timeStamp = Int(Date().timeIntervalSince1970)
var value:[String: Any] = ["fromId" : fromID, "timeStamp" : timeStamp, "name": self.loggedInUserData?["name"] as? String]
properties.forEach { (k,v) in
value[k] = v
}
childRef.updateChildValues(value) { (err, ref) in
if err != nil {
print(err!)
return
}
Database.database().reference().child("Business Group Chats").child((self.group?.uid)!).child((Auth.auth().currentUser?.uid)!).updateChildValues(["last message" : childRef.key!, "timestamp" : timeStamp, "businessName":(self.group?.businessName)!])
Database.database().reference().child("Business Group Chats").child((Auth.auth().currentUser?.uid)!).child((self.group?.uid)!).updateChildValues(["last message" : childRef.key!, "timestamp" : timeStamp])
self.inputContainerView.inputTextField.text = nil
}
}
Here is me taking that array of "uid's" and then pulling and printing that I can access each "uid" through a array of strings. Allowing me to access, now I can append data to each.
Database.database().reference().child("Businesses").observe(.value, with: { snapshot in
if snapshot.exists() {
self.businessUID = snapshot.value as? NSDictionary
if let dict = snapshot.value as? NSDictionary {
for item in dict {
let json = JSON(item.value)
let businessUid = json["uid"].stringValue
for uid in self.data {
if uid == businessUid {
//print(uid)
self.businessessuids = uid
print(self.businessessuids)
Database.database().reference().child("Businesses").child(self.businessessuids).observe(.value, with: { snapshot in
print(snapshot)
print("Trying to pull data from multiple strings right here this shoudld work")
})
print("printing the values to match with the string UID's")
}
}
}
}
} else {
print("does not exist")
}
})
I'm creating an app that allows notes to be shared. I'm having trouble with the Firebase database and feel that the amount of lines of code I am using to get information the user needs is more than I actually need and on top of that doesn’t work. Below is a screenshot of my database and a show of the code I’ve used. There are 3 different account types in my app. Parent, Child, and Other.
The Child can only see their own notes
The Parent can see everyone who’s written notes in for their code
The Other is supposed to see their notes and the parents notes per
code.
I am attempting to show the users whose notes can be seen in a collection view. So far it works for Parents and Children but not for the 'Other' which I am trying to fix.
This is my database. Right now, a Parent makes the account which generates a unique code. Then an Other or Child can join by typing the code in on a ViewController. For a child account it will automatically add the code to the account of the child in the user section and for the Other it is supposed to make a new section (I added a picture of what it looked like before I changed it). All users that have a certain code are added to the code section under that code.
{
"codes" : {
"ParVWb" : {
"totalUsers" : 2,
"users" : {
"VWbSR8qQyWd9deka6tgbxFC9ahs1" : {
"numberofNotes" : 0
},
"qm12qgkWfdbtSMMx58wIrxKuLKh1" : {
"numberofNotes" : 0
}
}
}
},
"users" : {
"JN47TBdI4EYX0NvoSHN21o1xFH92" : {
"email" : "other1#restart.mocs",
"fullName" : "Other 1 Name",
"type" : "Other",
"uid" : "JN47TBdI4EYX0NvoSHN21o1xFH92"
},
"VWbSR8qQyWd9deka6tgbxFC9ahs1" : {
"code" : "ParVWb",
"email" : "parentemail#restart.mocs",
"fullName" : "Parent Name",
"type" : "Parent",
"uid" : "VWbSR8qQyWd9deka6tgbxFC9ahs1"
},
"qm12qgkWfdbtSMMx58wIrxKuLKh1" : {
"code" : "ParVWb",
"email" : "childname#restart.mocs",
"fullName" : "Child Name",
"type" : "Child",
"uid" : "qm12qgkWfdbtSMMx58wIrxKuLKh1"
}
}
}
I used to have the use section look like this but now because of the large amount of reference blocks, it doesn't run the part that adds the "codes" section to the 'Other' user.
This is the function I have in my CollectionViewController that obtains all the needed users depending on the currentUser type.
func fetchConnections() {
ref.child("users").child(userID!).observe(.value, with: { (snapshot) in
let user = User(snapshot: snapshot)
if user.type == "Parent" {
let code = user.code as? String
let codeRef = databaseRef.child("codes").child(code!).child("users")
codeRef.observe(.value, with: { (codeSnapshot) in
if let users = codeSnapshot.value as? [String:AnyObject] {
DispatchQueue.main.async(execute: {
for user in users {
if let dict = user.value as? [String: Any] {
let userInformation = cellInfo(uid: user.0, numberofNotes: (dict["numberofNotes"] as? Int)!, code: self.code)
self.userCollection.append(userInformation)
self.collectionView.reloadData()
}
}
})
}
}) { (error) in
print(error.localizedDescription)
}
} else if user.type == "Child" {
let code = user.code
self.ref.child("codes").child(code!).child("users").child(self.userID!).observe(.value, with: { (snapshot) in
if let dict = snapshot.value as? [String: Any] {
print(user.key, (dict["numberofNotes"] as? Int)!)
let userInformation = cellInfo(uid: (user.key as? String)!, numberofNotes: (dict["numberofNotes"] as? Int)!, code: "code")
self.userCollection.append(userInformation)
self.collectionView.reloadData()
}
})
} else if user.type == "Other" {
self.ref.child("users").child(self.userID!).child("codes").observe(.value, with: { (snap) in
if let codes = snap.value as? [String:AnyObject] {
for code in codes {
if code.key == "numberofCodes" {
print("ignore")
} else { // If it's an actual code
self.ref.child("users").child(code.0).observeSingleEvent(of: .value, with: { (codeSnap) in
let user = User(snapshot: codeSnap)
let codetoFetch = user.code
self.ref.child("codes").child(codetoFetch!).child("users").child(self.userID!).observe(.value, with: {(codeSnapshot) in
if let users = codeSnapshot.value as? [String:AnyObject] {
DispatchQueue.main.async(execute: {
for user in users {
if let dict = user.value as? [String: Any] {
let userInformation = cellInfo(uid: code.0, numberofNotes: (dict["numberofNotes"] as? Int)!, code: self.code)
//self.userCollection.append(userInformation)
//self.collectionView.reloadData()
}
}
})
}
})
})
}
}
}
})
}
})
}
How can I obtain all of the codes that the 'Other' is a part of and all of the UID's & NumberofNotes for the 'Parents' of that code so that I can put them into the collectionView? (This code works for Parent and Child but if the way I'm doing it is long and ineffective please let me know.)
I need to make multiple observations, but I don't know how.
Here is my database structure:
"Posts" : {
"f934f8j3f8" : {
"data" : "",
"date" : "",
"userid" : ""
}
},
"Users" : {
"BusWttqaf9bWP224EQ6lOEJezLO2" : {
"Country" : "",
"DOB" : "",
"Posts" : {
"f934f8j3f8" : true
},
"Profilepic" : "",
"name" : "",
"phonenumber" : ""
}
I want to observe the posts and I write the code and it works great, but I also want to get the name of the user who posted this post but when I wrote save the name and use it it gives me null. Here is my code.
DataServices.ds.REF_POSTS.queryOrderedByKey().observe(.value,
with: { (snapshot) in
self.posts = []
if let snapshot = snapshot.children.allObjects as? [FIRDataSnapshot] {
for snap in snapshot {
if let postsDict = snap.value as? Dictionary<String, AnyObject> {
let key = snap.key
let userID = "BusWttqaf9bWP224EQ6lOEJezLO2"
DataServices.ds.REF_USERS.child(userID).observeSingleEvent(of: .value, with: { (snapshot) in
let value = snapshot.value as? NSDictionary
let postusername = value?["name"] as? String ?? ""
})
print(" ------ User name : \(postusername) ------")
})
print(" ------ User name 2 : \(postusername) ------")
let post = Posts(postKey: key, postData: postsDict)
self.posts.append(post)
The first print statement prints the username, but the second one prints nothing.
Thanks in advance.
Firebase is asynchronous so you can't operate on a variable until Firebase populates it within it's closure. Additionally code is faster than the internet so any statements following a closure will occur before the statements within the closure.
The flow would be as follows
Query for the post {
get the user id from the post inside this closure
query for the user info {
create the post inside this second closure
append the data to the array inside this second closure
reload tableview etc inside this second closure
}
}
Something like this edited code
self.posts = []
myPostsRef.queryOrderedByKey().observe(.value, with: { (snapshot) in
if let snapshot = snapshot.children.allObjects as? [FIRDataSnapshot] {
for snap in snapshot {
if let postsDict = snap.value as? Dictionary<String, AnyObject> {
let key = snap.key
let userID = "BusWttqaf9bWP224EQ6lOEJezLO2"
myUsersRef.child(userID).observeSingleEvent(of: .value, with: { (snapshot) in
let value = snapshot.value as? NSDictionary
let userName = value?["name"] as? String ?? ""
let post = Posts(postKey: key, postData: postsDict, name:userName)
self.posts.append(post)
})
}
}
}
})
You're not using the postusername inside the closure so I added that to the Posts initialization.
Also, the self.posts = [] is going to reset the posts array any time there's a change in the posts node - you may want to consider loading the array first, and then watch for adds, changes, or deletes and just update the posts array with single changes instead of reloading the entire array each time.
Edit:
A comment was made about the data not being available outside the loop. Here is a very simplified and tested version. Clicking button one populates the array from Firebase with a series of strings, clicking button 2 prints the array.
var posts = [String]()
func doButton1Action() {
let postsRef = ref.child("posts")
self.posts = []
postsRef.observe(.value, with: { (snapshot) in
if let snapshot = snapshot.children.allObjects as? [FIRDataSnapshot] {
for snap in snapshot {
let value = snap.value as! String
self.posts.append(value)
}
}
})
}
func doButton2Action() {
print(posts)
}
I have made a following feature where users can follow each other. The problem is that it is not being used the way it should. At the moment when a user is writing a post it will be saved in my Firebase database under this reference:
FIRDatabase.database().reference().child("feed-items").childByAutoId()
The feed-items is where all posts are. I am changing that however now, so when a user is posting something it will be saved here:
FIRDatabase.database().reference().child("Users").child(UserID).child("Posts").childByAutoId()
I do that because it somehow tells me that would be easier to only show the posts of the people you follow in my apps feed.
At the moment I am getting all the posts for my feed (from feed-items) like this:
func startObersvingDB() {
FIRDatabase.database().reference().child("feed-items").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()
self.tableView.reloadData()
}) { (error: NSError) in
print(error.description)
}
}
And then I call startObservingDB() in the viewDidLoad.
If you want to see my Sweet struct here it is:
import Foundation
import FirebaseDatabase
import FirebaseAuth
import UIKit
struct Sweet {
let key: String!
let content: String!
let addedByUser: String!
let profilePhoto: String!
let itemRef: FIRDatabaseReference?
init (content: String, addedByUser: String, profilePhoto: String!, key: String = "") {
self.key = key
self.content = content
self.addedByUser = addedByUser
self.profilePhoto = profilePhoto
self.itemRef = nil
}
init (snapshot: FIRDataSnapshot) {
key = snapshot.key
itemRef = snapshot.ref
path = key
if let theFeedContent = snapshot.value!["content"] as? String {
content = theFeedContent
} else {
content = ""
}
if let feedUser = snapshot.value!["addedByUser"] as? String {
addedByUser = feedUser
} else {
addedByUser = ""
}
if let feedPhoto = snapshot.value!["profilePhoto"] as? String! {
profilePhoto = feedPhoto
} else {
profilePhoto = ""
}
}
func toAnyObject() -> AnyObject {
return ["content":content, "addedByUser":addedByUser, "profilePhoto":profilePhoto!]
}
}
And in my TableViewController I am using this to display name etc. in the custom cell:
var update = updates[indexPath.row]
cell.nameLabel.text = update.addedByUser
etc. etc.
My question is:
How do I change that to only show posts from the people I am following?
Sorry for the long post
Assuming that you are saving your followers list as an dictionary in other parent node like this :-
user_followed_by :{
userID2 : {
userID1 : true,
userID5 : true,
userID6 : true,
userID12 : true,
userID99 : true,
}
}
users :{
userID2 :{
post :{
postAutoID1 : {...},
postAutoID2 : {...},
...
}
}
}
postsToShowToUser :{
userID1 : {
postAutoID1 : true, //These are the post's autoID's of all the users whom
// your current user is following
postAutoID5 : true,
postAutoID3 : true,
},
}
/* // If you choose to declare a separate section of the post Details in your Database.
posts_Of_The_User :{
userID1 : {
postAutoID1 : {...//DETAILS},
postAutoID2 : {...//DETAILS},
postAutoID3 : {...//DETAILS},
....
},
} */
The idea is that whenever a user whom your current user is following makes a post. That post's autoID gets appended in the postsToShowToUser/userID.
That is, if userID2 will make a post then a call will be made to append that post's autoID in all users postsToShowToUser/userID who are following the userID2.
PS:- I strongly suggest that you move your post details out of post section. Make it a separate parent node consisting of multiple postAutoID's as key and there post data as value. It might come in handy later on, also would avoid nesting data, which would help you navigate through your Database.