Post

Replies

Boosts

Views

Activity

Reply to How do I wait for a task to finish before proceeding with the program flow?
Here is a simple snippet on how you should use completionHandlers func loadImageAsync(completion: @escaping (UIImage?, Error?) -> Void) { guard let url = URL(string: "https://rickandmortyapi.com/api/character/avatar/2.jpeg") else { return } URLSession.shared.dataTask(with: url) { data, response, error in guard let data = data, error == nil else { DispatchQueue.main.async { completion(nil, error) } return } let image = UIImage(data: data) DispatchQueue.main.async { completion(image, nil) } }.resume() } See whats happening here? After the download occurs, we tell the main thread to dispatch our result. That's when we call the completion handler. That's like "Hey, i'm done, do whatever you want with these results." Also important: UI updates should ALWAYS happen on the main thread. Of course the syntax is a little different from what you're using but the principle is the same. And the usage should be something like: loadImageAsync { [weak self] img, err in if let image = img { self?.imageContainer.image = image } else { print("error \(String(describing: err))") } } You should always use weak self or unowned self when possible, it prevent weird crashes and and memory leaks. Also, try to nest the if let when possible, it reduces the cognitives complexity and makes your code more readable. So, instead of this:         if let image = UIImage(data: data!){     if let cgimage = image.cgImage { //... } } Try something like: if let data = data, let image = UImage(data: data), let cgImage = image.cgImage { //... } And you should never, ever force unwrap a property unless you are 100% sure it has something in it. Try unwraping it using guard let or if let for your own security.
Jun ’22