DiskFetcher.swift 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. //
  2. // DiskFetcher.swift
  3. // Haneke
  4. //
  5. // Created by Joan Romano on 9/16/14.
  6. // Copyright (c) 2014 Haneke. All rights reserved.
  7. //
  8. import Foundation
  9. extension HanekeGlobals {
  10. // It'd be better to define this in the DiskFetcher class but Swift doesn't allow to declare an enum in a generic type
  11. public struct DiskFetcher {
  12. public enum ErrorCode : Int {
  13. case invalidData = -500
  14. }
  15. }
  16. }
  17. open class DiskFetcher<T : DataConvertible> : Fetcher<T> {
  18. let path: String
  19. var cancelled = false
  20. public init(path: String) {
  21. self.path = path
  22. let key = path
  23. super.init(key: key)
  24. }
  25. // MARK: Fetcher
  26. open override func fetch(failure fail: @escaping ((Error?) -> ()), success succeed: @escaping (T.Result) -> ()) {
  27. self.cancelled = false
  28. DispatchQueue.global(qos: DispatchQoS.QoSClass.default).async(execute: { [weak self] in
  29. if let strongSelf = self {
  30. strongSelf.privateFetch(failure: fail, success: succeed)
  31. }
  32. })
  33. }
  34. open override func cancelFetch() {
  35. self.cancelled = true
  36. }
  37. // MARK: Private
  38. fileprivate func privateFetch(failure fail: @escaping ((Error?) -> ()), success succeed: @escaping (T.Result) -> ()) {
  39. if self.cancelled {
  40. return
  41. }
  42. let data : Data
  43. do {
  44. data = try Data(contentsOf: URL(fileURLWithPath: self.path), options: Data.ReadingOptions())
  45. } catch {
  46. DispatchQueue.main.async {
  47. if self.cancelled {
  48. return
  49. }
  50. fail(error)
  51. }
  52. return
  53. }
  54. if self.cancelled {
  55. return
  56. }
  57. guard let value : T.Result = T.convertFromData(data) else {
  58. let localizedFormat = NSLocalizedString("Failed to convert value from data at path %@", comment: "Error description")
  59. let description = String(format:localizedFormat, self.path)
  60. let error = errorWithCode(HanekeGlobals.DiskFetcher.ErrorCode.invalidData.rawValue, description: description)
  61. DispatchQueue.main.async {
  62. fail(error)
  63. }
  64. return
  65. }
  66. DispatchQueue.main.async(execute: {
  67. if self.cancelled {
  68. return
  69. }
  70. succeed(value)
  71. })
  72. }
  73. }