I have been on this issue for over three days, i have research and came across other similar questions on SO which relates to my issue but those fix could not solve mine hence the reason am asking this question.
I have a users, posts and users-posts node in firebase as shown below. I want to run a query on the node such that if two users are friends they can see each others post. But if they are not friends they cannot see each others posts
Users
123840ajldkjfas0d9
username: Joe
friend
78983049802930laks: true
78983049802930laks: true
4563049802930laks
username: Ken
friend
123840ajldkjfas0d9: true
78983049802930laks
username: Pean
friend
123840ajldkjfas0d9: true
posts
876f92fh02hfj02930239
post: This is cool
whoposted: 123840ajldkjfas0d9
39fh938hqw9320923308
post: I love pizza
whoposted: 78983049802930laks
users-posts
123840ajldkjfas0d9
876f92fh02hfj02930239: true
78983049802930laks
39fh938hqw9320923308: true
This is my query currently, it is showing all post for all users whether they are friends or not. Please i need help with this.
DataService.ds.REF_USERS.observe(.value, with: { (userSnapshot) in
if let snapshot = userSnapshot.children.allObjects as?
[FIRDataSnapshot]{
for userSnap in snapshot{
print("snapshot.key: \(userSnap.key)")
let userKey = userSnap.key
if var userDict = userSnap.value as? Dictionary<String,
AnyObject>{
let postUserPicUrl = userDict["profileImgUrl"] as? String
if let firstName = userDict["firstName"] as? String{
("firstName: \(firstName)")
DataService.ds.REF_POST.observeSingleEvent(of: .value, with: {
(postSnapshot) in
if let postSnapshot = postSnapshot.children.allObjects as?
[FIRDataSnapshot]{
for postSnap in postSnapshot{
if var postDict = postSnap.value as? Dictionary<String, AnyObject>{
if let refPostUserKey = postDict["user"] as? String{
if userKey == refPostUserKey{
DataService.ds.REF_BLOCK_USER.observeSingleEvent(of: .value, with: {
(blockUserSnapshot) in
if let blockUserSnapshot = blockUserSnapshot.children.allObjects as?
[FIRDataSnapshot] {
for blockUserSnap in blockUserSnapshot{
if var blockUserDict = blockUserSnap.value as? Dictionary<String,
AnyObject> {
if let user = blockUserDict["user"] as? String{
if firstName != user {
postDict["postUserPicUrl"] = postUserPicUrl as AnyObject?;
let postKey = postSnap.key
let post = Post(postKey: postKey, postData: postDict)
self.posts.append(post)
}
}
}
}
}
self.tableView.reloadData()
})
}
}
}
}
}
self.tableView.reloadData()
})
}
}
}
}
self.tableView.reloadData()
})
}
I mean this with no disrespect, but you are not utilizing these queries well with each nested within another. Also, make sure you update all of your queries. The Post query uses the old formatting while your user query is up to date.
You should create 3 dictionaries to hold the data for each node Users, posts, users-posts as well as a var to hold the current user string and a dictionary to contain the post data:
var users = [String:Any]()
var posts = [String:Any]()
var usersposts = [String:Any]()
var currentUserKey:String!
var visibleposts = [String:Any]()
Then have three separate queries to get the data. Currently it does not appear that you are querying for any specific users so I will do the same:
func getUserData(){
DataService.ds.REF_USERS.observe(.childAdded, with: {snapshot in
let key = snapshot.key
let data = snapshot.value as? [String:Any] ?? [:]
self.users[key] = data
})
}
func getPostsData(){
DataService.ds.REF_POST.observe(.childAdded, with: {snapshot in
let key = snapshot.key
let data = snapshot.value as? [String:Any] ?? [:]
self.posts[key] = data
self.refreshPosts()
})
}
func getUsersPostsData(){
DataService.ds.REF_BLOCK_USERS.observe(.childAdded, with:{snapshot in // I am guessing you have the users posts here?? there doesn't seem to be sample data for blocked users in your OP
let key = snapshot.key
let data = snapshot.value as? [String:Any] ?? [:]
self.usersposts[key] = data
self.refreshPosts()
})
}
Now get the current user before firing off these queries in the view did load and then call each query.
override func viewDidLoad(){
self.currentUserKey = (FIRAuth.auth()?.currentUser?.uid)!
/* you may want to do some error handling here to ensure the user
is actually signed in, for now this will get the key if
they are signed in */
self.getUserData()
self.getPostsData()
self.getUsersPostsData()
// data will be refreshed anytime a child is added
}
func refreshPosts(){
self.validposts = [:]
let validUsers = [String]() // this will hold the valid keys to get posts
validUsers.append(self.currentUserKey)
let currentUserData = users[self.currentUserKey] // filter the current user data to get the friends
// get friends keys
let friendsData = currentUserData["friends"] as? [String:Any] ?? [:]
for key in friendsData.keys {
// add friends posts to the validposts data
validUsers.append(key)
}
// get current users posts:
for (key,value) in self.posts {
let postData = value as? [String:Any] ?? [:]
let whoposted = postData["whoposted"] as? String ?? ""
if validUsers.contains(whoposted){
self.validposts[key] = postData
}
}
// access the self.validposts data in your UI however you have it setup
// The child added queries above will continue to fire off and refresh
// your data when new posts are added.
// I am still not clear what the usersposts data is for so it is omitted here.
}