Skip to content

Instantly share code, notes, and snippets.

@cipolleschi
Created June 13, 2020 13:07
Show Gist options
  • Select an option

  • Save cipolleschi/f3997d09061bd71061622284bf98ca61 to your computer and use it in GitHub Desktop.

Select an option

Save cipolleschi/f3997d09061bd71061622284bf98ca61 to your computer and use it in GitHub Desktop.
// Data structure for a Movie
struct Movie: Codable {
let id: String
let title: String
let description: String
let director: String
let producer: String
let releaseDate: String
let rtScore: String
let url: URL
}
// Function that starts the download and updates the UI afterward
func downloadMovies() {
self.promisifyDownload(url: URL(string: "https://ghibliapi.herokuapp.com/films")!)
.then(in: .main) { [weak self] movies in
// download finished. Update the state.
self?.localState.movies = movies.count
}
.catch(in: .main) { [weak self] error in
// download errored, present the alert with the error.
let vc = UIAlertController(title: "Error", message: "Error obtained: \(error.localizedDescription)", preferredStyle: .alert)
vc.addAction(UIAlertAction(title: "Ok", style: .default, handler: nil))
self.present(vc, animated: true, completion: nil)
}
}
// Function that transform the download in a promise.
func promisifyDownload(url: URL) -> Promise<[Movie]> {
return Promise<[Movie]>(in: .background) { [weak self] resolve, reject, _ in
// data delegate that will resolve or reject the promise.
let dataDelegate = DataDelegate(resolve: resolve, reject: reject)
let session = URLSession(configuration: .default, delegate: dataDelegate, delegateQueue: nil)
let task = session.dataTask(with: url)
// start the download.
task.resume()
}
}
// Delegate for the download of the movies.
class DataDelegate: NSObject, URLSessionDataDelegate {
let resolve: ([Movie]) -> ()
let reject: (Error) -> ()
init(resolve: @escaping ([Movie]) -> (), reject: @escaping (Error) -> ()) {
self.resolve = resolve
self.reject = reject
}
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
do {
// decode the received data
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let movies = try decoder.decode([Movie].self, from: data)
// resolve the promise so that the ui can be updated.
self.resolve(movies)
} catch {
self.reject(error)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment