Search code examples
swiftuiimagensurlconnection

Swift: Downloading and displaying an image takes 5 times longer than it should


I am using the Google image API to download an image that is then displayed to the user, the code runs like this:

        downloadImage { [weak self] image in
        if let strongSelf = self {
            if let image = image {
                strongSelf.mainImage.image = image
            }
        }
    }
}

func downloadImage(completion: UIImage? -> Void) {

    let url = NSURL(string: "https://ajax.googleapis.com/ajax/services/search/images?v=1.0&q=anything")
    let request = NSURLRequest(URL: url!)


    NSURLConnection.sendAsynchronousRequest(request, queue: self.operationQueue) { [weak self] response, data, error in
        if let strongSelf = self {
            if error != nil || data == nil {
                println(error)
                completion(nil)
                return
            }

            var serializationError: NSError?
            if let go = NSJSONSerialization.JSONObjectWithData(data!, options: .AllowFragments, error: &serializationError) as? [String: AnyObject] {
                let responseData = go["responseData"] as [String:AnyObject]
                let results = responseData["results"] as [[String:String]]
                let firstObject = results[0]
                var firstURL = firstObject["unescapedUrl"]!
                let theurl = NSURL(string: firstURL)
                let imageRequest = NSURLRequest(URL: theurl!)

                NSURLConnection.sendAsynchronousRequest(imageRequest, queue: strongSelf.operationQueue) { response, data, error in
                    if error != nil || data == nil {
                        println(error)
                        completion(nil)
                        return
                    }

                    if let image = UIImage(data: data!) {
                        completion(image)

                    } else {
                        completion(nil)
                    }
                }
            } else {
                println(serializationError)
                completion(nil)
            }
        }
    }

This basically just finds a URL of an image, and then downloads the image and sets the mainImage to that image. However, in most cases it takes the mainImage about 20 or 30 seconds to display the downloaded image, even though I know the image must be downloaded much faster than that (if I println the url found and open it in my browser, it will do it in 3 or 4 seconds, then I will patiently wait for the mainImage to display it in the simulator). It's also funny that if I save the url, switch view controllers and have the new view controller have an image variable that loads the URL image, it will do it straight away pretty much (like opening it in my browser) while the main view controller will still not have loaded it.


Solution

  • I think the problem is that you are not updating the UI in the Main Queue. Try calling it like this:

            downloadImage { [weak self] image in
            if let strongSelf = self {
                if let image = image {
                    dispatch_async(dispatch_get_main_queue(), { () -> Void in
                        strongSelf.mainImage.image = image
                    })
                }
            }
        }