2

I want to handle a friend request in my app written in Swift using Firebase. In my database, this means that the user sending the request needs to add the other user to their "sentRequests" dictionary, and the user receiving the request needs to add the user sending the requests to their "receivedRequests" dictionary. The problem is, if the user sending the request has a faulty connection and only does the first part, then it might cause issues. Either both writes should happen or none. What can I do to fix this? I included my code below for reference, but honestly if someone just sends me a good tutorial or answer here that would be just has helpful as correctly rewriting my code.

static func sendRequestFromCurrentUser(toUser userThatRequestWasSentTo : User, succeeded : @escaping (Bool)->Void ){

    let ref = Database.database().reference().child("users").child(User.current.uid).child("sentRequests").child(userThatRequestWasSentTo.uid)
    ref.setValue(userThatRequestWasSentTo.toDictionary(), withCompletionBlock: {(error, ref) in
        if error == nil{
            let currentUserRef = Database.database().reference().child("users").child(userThatRequestWasSentTo.uid).child("receivedRequests").child(User.current.uid)
            currentUserRef.setValue(User.current.toDictionary(), withCompletionBlock: {(error, ref) in
                if error == nil{
                    succeeded(true)
                }
                else{
                    succeeded(false)
                }

            })
        }
        else{
            succeeded(false)
        }
    })
}
Kyle Somers
  • 614
  • 1
  • 8
  • 21
  • You'd typically use a multi-location update for that. See for some more details: https://stackoverflow.com/questions/30693785/how-to-write-denormalized-data-in-firebase – Frank van Puffelen Aug 09 '17 at 20:41
  • That's helpful, though I'm not too good in javascript. I'll keep digging through it and see how well it carries over to Swift. I may include a Swift answer below when I get it working if no one else has already. Thanks! – Kyle Somers Aug 09 '17 at 22:54
  • Is the `User` class referring to `Firebase.User`, or have you made your own? – Callam Aug 09 '17 at 22:56
  • I made my own. It makes the current user a static variable of type User (my own custom version of User) of my custom User class. – Kyle Somers Aug 09 '17 at 23:01

1 Answers1

0

So I stole this from the Firebase blog and got it to match my code. The answer is fairly intuitive, I just hadn't considered it. Basically you just create a reference to the top level of your database and specify the paths you want to write to in the dictionary (so not by creating specific references with child()), and then just call updateChildValues().

static func sendRequestFromCurrentUser(toUser userThatRequestWasSentTo : User, succeeded : @escaping (Bool)->Void ){



    let ref = Database.database().reference()

    // Create the data we want to update
    var updatedUserData : [String : Any] = [:]
    updatedUserData["users/\(User.current.uid)/sentRequests/\(userThatRequestWasSentTo.uid)"] = userThatRequestWasSentTo.toDictionary()
    updatedUserData["users/\(userThatRequestWasSentTo.uid)/receivedRequests/\(User.current.uid)"] = User.current.toDictionary()

    // Do a deep-path update
    ref.updateChildValues(updatedUserData, withCompletionBlock: { (error, ref)  in
        if let error = error {
            print("Error updating data: \(error.localizedDescription)")
            succeeded(false)
        }
        else{
            succeeded(true)
        }
    })
}
Kyle Somers
  • 614
  • 1
  • 8
  • 21