| OLD | NEW |
| 1 // | 1 // |
| 2 // FavIcon | 2 // FavIcon |
| 3 // Copyright © 2016 Leon Breedt | 3 // Copyright © 2016 Leon Breedt |
| 4 // | 4 // |
| 5 // Licensed under the Apache License, Version 2.0 (the "License"); | 5 // Licensed under the Apache License, Version 2.0 (the "License"); |
| 6 // you may not use this file except in compliance with the License. | 6 // you may not use this file except in compliance with the License. |
| 7 // You may obtain a copy of the License at | 7 // You may obtain a copy of the License at |
| 8 // | 8 // |
| 9 // http://www.apache.org/licenses/LICENSE-2.0 | 9 // http://www.apache.org/licenses/LICENSE-2.0 |
| 10 // | 10 // |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 54 /// An unexpected HTTP error response was returned. | 54 /// An unexpected HTTP error response was returned. |
| 55 /// - parameter response: The `HTTPURLResponse` that can be consulted for fu
rther information. | 55 /// - parameter response: The `HTTPURLResponse` that can be consulted for fu
rther information. |
| 56 case httpError(response: HTTPURLResponse) | 56 case httpError(response: HTTPURLResponse) |
| 57 } | 57 } |
| 58 | 58 |
| 59 /// Base class for performing URL requests in the context of an `NSOperation`. | 59 /// Base class for performing URL requests in the context of an `NSOperation`. |
| 60 class URLRequestOperation: Operation { | 60 class URLRequestOperation: Operation { |
| 61 @objc var urlRequest: URLRequest | 61 @objc var urlRequest: URLRequest |
| 62 var result: URLResult? | 62 var result: URLResult? |
| 63 | 63 |
| 64 fileprivate var task: URLSessionDataTask? | 64 private var task: URLSessionDataTask? |
| 65 fileprivate let session: URLSession | 65 private let session: URLSession |
| 66 fileprivate var semaphore: DispatchSemaphore? | 66 private var semaphore: DispatchSemaphore? |
| 67 | 67 |
| 68 @objc init(url: URL, session: URLSession) { | 68 @objc |
| 69 init(url: URL, session: URLSession) { |
| 69 self.session = session | 70 self.session = session |
| 70 self.urlRequest = URLRequest(url: url) | 71 self.urlRequest = URLRequest(url: url) |
| 71 self.semaphore = nil | 72 self.semaphore = nil |
| 72 } | 73 } |
| 73 | 74 |
| 74 override func main() { | 75 override func main() { |
| 75 semaphore = DispatchSemaphore(value: 0) | 76 semaphore = DispatchSemaphore(value: 0) |
| 76 prepareRequest() | 77 prepareRequest() |
| 77 task = session.dataTask(with: urlRequest, completionHandler: dataTaskCom
pletion) | 78 task = session.dataTask(with: urlRequest, completionHandler: dataTaskCom
pletion) |
| 78 task?.resume() | 79 task?.resume() |
| 79 semaphore?.wait() | 80 semaphore?.wait() |
| 80 } | 81 } |
| 81 | 82 |
| 82 override func cancel() { | 83 override func cancel() { |
| 83 task?.cancel() | 84 task?.cancel() |
| 84 if let semaphore = semaphore { | 85 if let semaphore = semaphore { |
| 85 semaphore.signal() | 86 semaphore.signal() |
| 86 } | 87 } |
| 87 } | 88 } |
| 88 | 89 |
| 89 @objc func prepareRequest() { | 90 @objc |
| 91 func prepareRequest() { |
| 90 } | 92 } |
| 91 | 93 |
| 92 func processResult(_ data: Data?, response: HTTPURLResponse, completion: @es
caping (URLResult) -> Void) { | 94 func processResult(_ data: Data?, response: HTTPURLResponse, completion: @es
caping (URLResult) -> Void) { |
| 93 fatalError("must override processResult()") | 95 fatalError("must override processResult()") |
| 94 } | 96 } |
| 95 | 97 |
| 96 fileprivate func dataTaskCompletion(_ data: Data?, response: URLResponse?, e
rror: Error?) { | 98 private func dataTaskCompletion(_ data: Data?, response: URLResponse?, error
: Error?) { |
| 97 guard error == nil else { | 99 guard error == nil else { |
| 98 result = .failed(error: error!) | 100 result = .failed(error: error!) |
| 99 self.notifyFinished() | 101 self.notifyFinished() |
| 100 return | 102 return |
| 101 } | 103 } |
| 102 | 104 |
| 103 guard let response = response as? HTTPURLResponse else { | 105 guard let response = response as? HTTPURLResponse else { |
| 104 result = .failed(error: URLRequestError.missingResponse) | 106 result = .failed(error: URLRequestError.missingResponse) |
| 105 self.notifyFinished() | 107 self.notifyFinished() |
| 106 return | 108 return |
| (...skipping 12 matching lines...) Expand all Loading... |
| 119 } | 121 } |
| 120 | 122 |
| 121 processResult(data, response: response) { result in | 123 processResult(data, response: response) { result in |
| 122 // This block may run on another thread long after dataTaskCompletio
n() finishes! So | 124 // This block may run on another thread long after dataTaskCompletio
n() finishes! So |
| 123 // wait until then to signal semaphore if we get past checks above. | 125 // wait until then to signal semaphore if we get past checks above. |
| 124 self.result = result | 126 self.result = result |
| 125 self.notifyFinished() | 127 self.notifyFinished() |
| 126 } | 128 } |
| 127 } | 129 } |
| 128 | 130 |
| 129 fileprivate func notifyFinished() { | 131 private func notifyFinished() { |
| 130 if let semaphore = self.semaphore { | 132 if let semaphore = self.semaphore { |
| 131 semaphore.signal() | 133 semaphore.signal() |
| 132 } | 134 } |
| 133 } | 135 } |
| 134 } | 136 } |
| 135 | 137 |
| 136 typealias URLRequestWithCallback = (request: URLRequestOperation, completion: (U
RLResult) -> Void) | 138 typealias URLRequestWithCallback = (request: URLRequestOperation, completion: (U
RLResult) -> Void) |
| 137 | 139 |
| 138 func executeURLOperations(_ operations: [URLRequestOperation], | 140 func executeURLOperations(_ operations: [URLRequestOperation], |
| 139 concurrency: Int = 2, | 141 concurrency: Int = 2, |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 185 } | 187 } |
| 186 queue.addOperation(overallCompletion) | 188 queue.addOperation(overallCompletion) |
| 187 | 189 |
| 188 queue.isSuspended = false | 190 queue.isSuspended = false |
| 189 } | 191 } |
| 190 | 192 |
| 191 func urlRequestOperation(_ operation: URLRequestOperation, | 193 func urlRequestOperation(_ operation: URLRequestOperation, |
| 192 completion: @escaping (URLResult) -> Void) -> URLReques
tWithCallback { | 194 completion: @escaping (URLResult) -> Void) -> URLReques
tWithCallback { |
| 193 return (request: operation, completion: completion) | 195 return (request: operation, completion: completion) |
| 194 } | 196 } |
| OLD | NEW |