2

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()
      })
   }
Perfect Aduh
  • 43
  • 2
  • 9
  • I will face exactly this kind of situation soon in my project, hopefully you will get an answer soon – Arafin Russell Feb 17 '17 at 19:30
  • Your code is a mess, and it's very difficulty to read - which makes it very difficulty to help. Please fix the formatting, especially the indentation for nested functions. – Pierce Feb 17 '17 at 19:54

1 Answers1

1

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.
}
matthew
  • 343
  • 2
  • 16
  • @mathew many thanks for your feedback. I seem to be making progress al ready. The issue I am currently having is that empty when printed. Can you please advise? – Perfect Aduh Feb 19 '17 at 17:49
  • What is the code you are using to print the data? Also, try printing the snapshot to see if there is any data. – matthew Feb 20 '17 at 00:57
  • @mathew It is printing out and i am able to populate my ui. But the data is being duplicated. Initially I thought it was an issue with table view cell. But upon checking I re-aliased that when I print usersposts and users the data in it are being duplicated. Could you please advise how to get rid of the duplicate data – Perfect Aduh Feb 20 '17 at 07:44