Skip to content

Instantly share code, notes, and snippets.

@cbess
Last active August 7, 2016 18:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cbess/86d5753dcb76ed75fe291f47d1a4ab5c to your computer and use it in GitHub Desktop.
Save cbess/86d5753dcb76ed75fe291f47d1a4ab5c to your computer and use it in GitHub Desktop.
Custom network Fetcher that accepts a key, rather than using the URL.
//
// NetworkFetcher.swift
//
// Created by C. Bess on 8/7/16.
// Pulled from original NetworkFetcher (cleaned up and updated)
import Haneke
public class NetworkFetcher<T: DataConvertible>: Fetcher<T> {
let URL: NSURL
public init(URL: NSURL, key: String) {
self.URL = URL
super.init(key: key)
}
public var session: NSURLSession {
return NSURLSession.sharedSession()
}
var task: NSURLSessionDataTask? = nil
var cancelled = false
// MARK: Fetcher
public override func fetch(failure fail: ((NSError?) -> ()), success succeed: (T.Result) -> ()) {
cancelled = false
task = session.dataTaskWithURL(URL) { [weak self] (data, response, error) -> Void in
self?.onReceiveData(data, response: response, error: error, failure: fail, success: succeed)
}
task?.resume()
}
public override func cancelFetch() {
task?.cancel()
cancelled = true
}
// MARK: Private
private func onReceiveData(data: NSData!, response: NSURLResponse!, error: NSError!, failure fail: ((NSError?) -> ()), success succeed: (T.Result) -> ()) {
if cancelled {
return
}
if let error = error {
if error.domain == NSURLErrorDomain
&& error.code == NSURLErrorCancelled {
return
}
dispatch_async(dispatch_get_main_queue()) {
fail(error)
}
return
}
if let httpResponse = response as? NSHTTPURLResponse where httpResponse.statusCode != 200 {
let description = NSHTTPURLResponse.localizedStringForStatusCode(httpResponse.statusCode)
failWithCode(.InvalidStatusCode, localizedDescription: description, failure: fail)
return
}
if !response.hnk_validateLengthOfData(data) {
let localizedFormat = NSLocalizedString("Request expected %ld bytes and received %ld bytes", comment: "Error description")
let description = String(format: localizedFormat, response.expectedContentLength, data.length)
failWithCode(.MissingData, localizedDescription: description, failure: fail)
return
}
guard let value = T.convertFromData(data) else {
let localizedFormat = NSLocalizedString("Failed to convert value from data at URL %@", comment: "Error description")
let description = String(format: localizedFormat, URL.absoluteString)
failWithCode(.InvalidData, localizedDescription: description, failure: fail)
return
}
dispatch_async(dispatch_get_main_queue()) {
succeed(value)
}
}
private func failWithCode(code: HanekeGlobals.NetworkFetcher.ErrorCode, localizedDescription: String, failure fail: ((NSError?) -> ())) {
let error = NSError.init(domain: "cache", code: code.rawValue, userInfo: [NSLocalizedDescriptionKey: localizedDescription])
dispatch_async(dispatch_get_main_queue()) {
fail(error)
}
}
}
extension Cache {
/// Fetches the data from the specified `URL`, caching it under the give `key`
func fetch(URL URL: NSURL, key: String, failure fail: Fetch<T>.Failer? = nil, success succeed: Fetch<T>.Succeeder? = nil) -> Fetch<T> {
let fetcher = NetworkFetcher<T>(URL: URL, key: key)
return self.fetch(fetcher: fetcher, formatName: HanekeGlobals.Cache.OriginalFormatName, failure: fail, success: succeed)
}
}
extension NSURLResponse {
func hnk_validateLengthOfData(data: NSData) -> Bool {
if expectedContentLength > -1 {
return Int64(data.length) >= expectedContentLength
}
return true
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment