Search code examples
iosswiftuitableviewfirebasefirebaseui

firebaseui-ios FirebaseTableViewDataSource synchronisation with UITableView


I'm using FirebaseUI-IOS and the FirebaseTableViewDataSource to bind to my UITableView. For my implementation the UITableView should show Invitations in a 'pending' state to connect users, similar to LinkedIn. The Invitation data stored in Firebase has a Status key that can be either 'pending', 'accepted' or 'rejected'. I am struggling to get the UITableView to update and display only the 'pending' rows after the user has accepted/rejected an invitation. What currently happens is that the UITableView cell gets updated (the name label changes to it's default text), but the cell is still displayed. It seems that the UITableView is bound to all rows under the user's 'received' node, rather than responding to when the status != 'pending'.

My data in Firebase is structured as follows:

Firebase 'Invitation' data structure

I am using the following code in ViewDidLoad() to initialise the FirebaseTableViewDataSource and populate the cell:

    //Initialise a Firebase reference to the authorised user's 'received' invitations data
    self.ref = Firebase(url: "\(kFBInvitationsUsersRef)/\(authData.uid)/received")

    //Query the location for invitations where the status is pending only
    self.ref.queryOrderedByChild("status").queryStartingAtValue(InvitationStatus.pending.rawValue).queryEndingAtValue(InvitationStatus.pending.rawValue).observeEventType(.ChildChanged , withBlock: {(snapshot) in
    } )

    //Assign the tableview datasource to a new FirebaseTableViewDataSource instance using the Firebase ref created above
    self.dataSource = FirebaseTableViewDataSource(query: self.ref, modelClass:nil, prototypeReuseIdentifier: "invitationCell", view: self.tableView)

    //Call the populateCellWithBlock method and configure the cell
    self.dataSource.populateCellWithBlock { (cell: UITableViewCell, obj: NSObject) -> Void in
        let cell = cell as! InvitationTableViewCell
        let snap = obj as! FDataSnapshot

        if let status = snap.value["status"] as? String where status == InvitationStatus.pending.rawValue {
            let userRef = Firebase(url: "\(kFBUsersPublicRef)/\(snap.key)")
            userRef.observeSingleEventOfType(.Value, withBlock: {snapshot in

                let user = User(key: snapshot.key, displayName: snapshot.value["displayName"] as! String, givenName: snapshot.value["givenName"]  as! String, familyName: snapshot.value["familyName"]  as! String)
                cell.user = user
                cell.delegate = self
            })
        }
    }
    self.tableView.dataSource = self.dataSource
    self.tableView.delegate = self
}

Can anyone help diagnose what I'm doing wrong here? Is my approach correct?

Thank you for any help you can provide!


Solution

  • I've changed my approach to this to find a solution. I've modified my data structure in Firebase so that the statuses become keys. I then bind the FirebaseTableViewDataSource to the reference for the 'pending' key. When the user accepts/rejects the invitation it gets deleted from the 'pending' node and created on the 'accepted'/'rejected' node. The tableView now updates as expected when new 'pending' invitations are added or existing 'pending' invitations are accepted/rejected.