skip to Main Content

So I have an app that connects to a simple firebase database that connects users to their profile when logging into the app. Every user has a username, profile picture, and other data related to the app stored within their own user ID. My main issue is that my UI becomes unresponsive when the app tries to retrieve the info from the database, for example, if I wanted to press down on an object in my home page (whether it be a button, table view, etc) to take me to another view controller, it would take about 5 seconds and sometimes even worse if the user has bad wifi connection.

I’ve tried doing a few things, like running the code that retrieves the data onto a dispatchQueue with a .background DispatchQoS, thinking it would have it run on a background thread allowing the user to freely use the UI without having to wait for the data to load, but that did not seem to work for me.

Any help would be appreciated.

override func viewDidLoad() {
    super.viewDidLoad()
    
    let dispatchQueue = DispatchQueue(label: "QueueIdentification", qos: .background)
   
    _ = Auth.auth().addStateDidChangeListener { (auth, user) in
            if user != nil {
                //There is a user
                self.usernameLabel.text = user?.displayName ?? "Edit Name"
                
                // Get the user profile picture from storage
                let storage = Storage.storage()
                let storageRef = storage.reference()
                let profilePicRef = storageRef.child("ProfileImages/(Auth.auth().currentUser!.uid).jpg")
                
                dispatchQueue.async {
                    
                    profilePicRef.downloadURL { (url, error) in
                        guard let downloadURL = url else {
                            // Error occured
                            return
                        }
                        // Now we set the image using the downloadURL
                        let imageData = try! Data(contentsOf: downloadURL)
                        let image = UIImage(data: imageData)
                        self.profilePictureImageView.image = image
                    }
                    
                }
                    
            } else {
                //There is no user, go to sign in page
                self.performSegue(withIdentifier: "toSignIn", sender: self)
            }
         
        
        
    }
    
    setUpUI()

}

2

Answers


  1. Chosen as BEST ANSWER
                   profilePicRef.downloadURL { (url, error) in
                        guard let downloadURL = url else {
                            // Error occured
                            return
                        }
                        // Now we set the image using the downloadURL
                        
                        DispatchQueue.global(qos: .userInitiated).async {
                            self.imageData = try! Data(contentsOf: downloadURL)
                            self.image = UIImage(data: self.imageData!)
                            
                            DispatchQueue.main.async {
                                self.profilePictureImageView.image = self.image
                            }
                        }
       
                    }
    

  2. If you are retrieving data from a background thread, you need to do the UI changes in the main thread. Otherwise the app will freez.

    DispatchQueue.global(qos: .background).async {
        print("This is run on the background queue")
    
        DispatchQueue.main.async {
            print("This is run on the main queue, Do the UI changes here")
        }
    } 
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search