1

[Edit2: This question still does not get the correct network response. The supposed duplicate also does not get the correct response when I put my URL in the duplicate.] I am following a textbook about Swift3 and iOS/tvOS which contains a class with code to get a network image, but the code does not produce the image. I have copied that code into a playground to try and create a small working unit as below. In the book, all the playground code before 'let theUrlString ..' is within a class. When getImageFromURL is called with the URL shown, the print statements produce:

Download: http://www.impawards.com/2014/posters/american_sniper_xlg.jpg Image from cache Image cached from 539 bytes Downloaded image size: Optional((1.0, 1.0))

I can use the URL to get the image in any browser, and it is 206 KB, so the cache size in the code is not the problem. But only 539 bytes seem to be downloaded, implying that the code does not function, as is also indicated by the printed size. Since it is in a textbook, I presume that it worked originally, and in fact I am using the code download as supplied by the publisher, so its not a typing error.

The new Swift4 version of the book has changed by providing all the sample data in a resource file, so that is no help.

//: Playground - noun: a place where people can play

import UIKit
import PlaygroundSupport

let URLCache = Foundation.URLCache(memoryCapacity: 20 * 1024 * 1024, diskCapacity: 100 * 1024 * 1024, diskPath: "ImageDownloadCache")

let config = URLSessionConfiguration.default
config.requestCachePolicy = NSURLRequest.CachePolicy.returnCacheDataElseLoad
config.urlCache = URLCache
let session = URLSession(configuration: config)

func getImageFromURL(_ imageURL: String, completion: @escaping (UIImage?) -> Void) {
  if let url = URL(string: imageURL) {
    print("Download: \(imageURL)")
    let urlRequest = URLRequest(url: url, cachePolicy: NSURLRequest.CachePolicy.returnCacheDataElseLoad, timeoutInterval: 30.0)

    if let response = URLCache.cachedResponse(for: urlRequest) {
        let image = UIImage(data: response.data)
        print("Image from cache")
        DispatchQueue.main.async {
            completion(image)
            return
        }
    }

    session.dataTask(with: urlRequest) { (data: Data?, response: URLResponse?, error: Error?) -> Void in
        guard let response = response, let data = data else {
            completion(nil)
            print("Failed to load image.")
            return
        }

        URLCache.storeCachedResponse(CachedURLResponse(response:response, data:data, userInfo:nil, storagePolicy:.allowed), for: urlRequest) // commit response into cache
        print("Image cached from \(data)")
        let downloadedImage = UIImage(data: data)
        DispatchQueue.main.async {
            completion(downloadedImage)
            print("Downloaded image size: \(downloadedImage?.size)")
        }
     }.resume()
  }
}

PlaygroundPage.current.needsIndefiniteExecution = true
let theUrlString: String = "http://www.impawards.com/2014/posters/american_sniper_xlg.jpg" // 206 KB image

var theImage: UIImage = UIImage()
getImageFromURL(theUrlString) { image in
    theImage = image!
  }

[Edit: Thanks to this link How do I run Asynchronous callbacks in Playground the code now completes in extended time and replicates the error of the original code.]

AndrewCSP
  • 41
  • 4

0 Answers0