Problem regarding swift code execution

I’m facing some difficulty in the code as shown below:

let group = DispatchGroup()
                    
group.enter()
DispatchQueue.global(qos: .default).async {
   Utlities().setCurrUser(currUser: result!.user)
   group.leave()
}
    
                    
group.enter()
DispatchQueue.main.async {
     strongSelf.spinner.dismiss()
      group.leave()

}
group.wait()
                    
var f = " ", l = " "
(f,l) = strongSelf.getName()
print(f,"---",l)
User.Instance().setfName(name: f)
User.Instance().setlName(name: l)

I want the code to execute in order but what is happening that the last 5 lines are being executed before the first DispatchQueue code i.e this code

Utlities().setCurrUser(currUser: result!.user)

This setCurrUser function is simply getting names of user from firebase on the basis of user id and and storing it in user defaults ,and my getName is just returning names after getting it from user defaults .The code mentioned above is being called in my login functionality part , so what happens is that when I first login, the attributes of user object ‘firstname’ and ‘lastname’ get empty but when I run my app again , the login session is stored so no need to login again , so this time i just get the firstname and lastname from user defaults , this time the attributes of user object ‘firstname’ and ‘lastname’ get filled . So I am concluding that this is the issue that the last 5 lines of code gets executed first before this code completion:

Utlities().setCurrUser(currUser: result!.user)

so thats why first time we get empty names and second we get successful data.

Useful codes:

public func setCurrUser(currUser: FirebaseAuth.User){
    
        let uid = currUser.uid
        
        let email = currUser.email
        let filename = uid + ".png"
        
        // get firstname and lastname from database
        DatabaseManager().getUserName(uid: uid) { [weak self] result in
            
            switch result {
                
            case .success(let data):

                guard let userData = data as? [String:Any],
                      let firstname = userData["firstname"] as? String,
                      let lastname = userData["lastname"] as? String
                        
                else {return}
        
                
                UserDefaults.standard.set(firstname, forKey: "fName")
                UserDefaults.standard.set(lastname, forKey: "lName")
  
             
            case .failure(let err):
                print("Utilities: func: setCurrUser: Line 55: ",err)
            }
        }



        let usr = User.Instance(firstName:" " ,lastName:" ", email: email!, uid: uid)

        usr.setUrl(path:"images/\(filename)")

}

Below is the same function (with same name) , it gets called when the user is already logged in:

 public func setCurrUser(currUser: FirebaseAuth.User){
    
        let uid = currUser.uid
        
        let email = currUser.email
        let filename = uid + ".png"
        
        var f = " ", l = " "
        (f,l) = self.getName()


        let usr = User.Instance(firstName:f ,lastName:l, email: email!, uid: uid)

        usr.setUrl(path:"images/\(filename)")

    }

Hi @Huzaifa

I’m not 100% sure about this but It looks like the issue is that the code at the bottom of your function is executing before the Utilities().setCurrUser(currUser: result!.user) function has completed. You can to move the code at the bottom of the function inside the switch result block, after the UserDefaults.standard.set(firstname, forKey: "fName") and UserDefaults.standard.set(lastname, forKey: "lName") lines. This will ensure that the code is executed only after the setCurrUser function has completed and the first and last names have been saved to the user defaults.

Additionally, you can also use the notify(queue:) function of DispatchGroup to specify the queue on which you want to execute the next set of code, so that you can be sure that your code runs in the desired order.

Here’s an example of how you can use notify(queue:) :

let group = DispatchGroup()

group.enter()
DispatchQueue.global(qos: .default).async {
   Utilities().setCurrUser(currUser: result!.user)
   group.leave()
}

group.notify(queue: .main) {
  var f = " ", l = " "
  (f,l) = strongSelf.getName()
  print(f,"---",l)
  User.Instance().setfName(name: f)
  User.Instance().setlName(name: l)
}

This way, you can be sure that the code inside the notify block will only run after the setCurrUser function has completed and the group’s leave() method has been called.

Let me know if this work. :blush:

1 Like

Yeah bro this worked , I simply placed the bottom code, inside the case .success part and , add a completion handler in the parameters , so I’ll go to the next page after login only after this code completion i.e the code when this code gets executed completely and I get my desired values, so my this issue is resolved.
Thanks

1 Like