skip to Main Content

Hello everyone junior dev here, I fetch data from server in background thread and update ui in main thread, it works but i also have separate ui image loader from url here:

extension UIImageView {
    func load(url: String) {
        guard let urlString = URL(string: url) else {return}
        DispatchQueue.global(qos: .background).async { [weak self] in
            if let data = try? Data(contentsOf: urlString) {
                if let image = UIImage(data: data) {
                    DispatchQueue.main.async {
                        self?.image = image
                    }
                }
            }
        }
    }
}

But when open screen first image loader above works and app freezes for seconds and then main ui (uiviews) update, both ui updates in main thread. How can I make it image load in main thread do not block uiview update? I want it to be like this: Ui updates and works, then when image is uploaded it should not freeze main ui updates.
Additional info: using combine to fetch data and uikit for design.
Thanks in advance!

2

Answers


  1. Use URLSession

    extension UIImageView {
        func load(urlString: String) {
            guard let url = URL(string: urlString) else {return}
            
            let task = URLSession.shared.dataTask(with: url) { data, response, error in
                guard let data = data, error == nil else { return }
                
                DispatchQueue.main.async {
                    self.image = UIImage(data: data)
                }
            }
            
            task.resume()
        }
    }
    
    Login or Signup to reply.
  2. I think you should create a static thread instead of calling DispatchQueue.global(qos: .background), for example:

    extension UIImageView {
    static let loadingImageThread = DispatchQueue(label: "loadingImageThread", qos: .background ,attributes: .concurrent, autoreleaseFrequency: .workItem)
    func load(url: String) {
        guard let urlString = URL(string: url) else {return}
        loadingImageThread.async { [weak self] in
            if let data = try? Data(contentsOf: urlString) {
                if let image = UIImage(data: data) {
                    DispatchQueue.main.async {
                        self?.image = image
                    }
                }
            }
        }
    }
    

    }

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search