服务商获取权限失败的话retry,更换了首页的背景图
This commit is contained in:
334
Pods/Alamofire/Source/Request.swift
generated
334
Pods/Alamofire/Source/Request.swift
generated
@@ -125,11 +125,10 @@ public class Request {
|
||||
}
|
||||
|
||||
/// Protected `MutableState` value that provides thread-safe access to state values.
|
||||
@Protected
|
||||
fileprivate var mutableState = MutableState()
|
||||
fileprivate let mutableState = Protected(MutableState())
|
||||
|
||||
/// `State` of the `Request`.
|
||||
public var state: State { $mutableState.state }
|
||||
public var state: State { mutableState.state }
|
||||
/// Returns whether `state` is `.initialized`.
|
||||
public var isInitialized: Bool { state == .initialized }
|
||||
/// Returns whether `state is `.resumed`.
|
||||
@@ -152,50 +151,49 @@ public class Request {
|
||||
public let downloadProgress = Progress(totalUnitCount: 0)
|
||||
/// `ProgressHandler` called when `uploadProgress` is updated, on the provided `DispatchQueue`.
|
||||
private var uploadProgressHandler: (handler: ProgressHandler, queue: DispatchQueue)? {
|
||||
get { $mutableState.uploadProgressHandler }
|
||||
set { $mutableState.uploadProgressHandler = newValue }
|
||||
get { mutableState.uploadProgressHandler }
|
||||
set { mutableState.uploadProgressHandler = newValue }
|
||||
}
|
||||
|
||||
/// `ProgressHandler` called when `downloadProgress` is updated, on the provided `DispatchQueue`.
|
||||
fileprivate var downloadProgressHandler: (handler: ProgressHandler, queue: DispatchQueue)? {
|
||||
get { $mutableState.downloadProgressHandler }
|
||||
set { $mutableState.downloadProgressHandler = newValue }
|
||||
get { mutableState.downloadProgressHandler }
|
||||
set { mutableState.downloadProgressHandler = newValue }
|
||||
}
|
||||
|
||||
// MARK: Redirect Handling
|
||||
|
||||
/// `RedirectHandler` set on the instance.
|
||||
public private(set) var redirectHandler: RedirectHandler? {
|
||||
get { $mutableState.redirectHandler }
|
||||
set { $mutableState.redirectHandler = newValue }
|
||||
get { mutableState.redirectHandler }
|
||||
set { mutableState.redirectHandler = newValue }
|
||||
}
|
||||
|
||||
// MARK: Cached Response Handling
|
||||
|
||||
/// `CachedResponseHandler` set on the instance.
|
||||
public private(set) var cachedResponseHandler: CachedResponseHandler? {
|
||||
get { $mutableState.cachedResponseHandler }
|
||||
set { $mutableState.cachedResponseHandler = newValue }
|
||||
get { mutableState.cachedResponseHandler }
|
||||
set { mutableState.cachedResponseHandler = newValue }
|
||||
}
|
||||
|
||||
// MARK: URLCredential
|
||||
|
||||
/// `URLCredential` used for authentication challenges. Created by calling one of the `authenticate` methods.
|
||||
public private(set) var credential: URLCredential? {
|
||||
get { $mutableState.credential }
|
||||
set { $mutableState.credential = newValue }
|
||||
get { mutableState.credential }
|
||||
set { mutableState.credential = newValue }
|
||||
}
|
||||
|
||||
// MARK: Validators
|
||||
|
||||
/// `Validator` callback closures that store the validation calls enqueued.
|
||||
@Protected
|
||||
fileprivate var validators: [() -> Void] = []
|
||||
fileprivate let validators = Protected<[() -> Void]>([])
|
||||
|
||||
// MARK: URLRequests
|
||||
|
||||
/// All `URLRequests` created on behalf of the `Request`, including original and adapted requests.
|
||||
public var requests: [URLRequest] { $mutableState.requests }
|
||||
public var requests: [URLRequest] { mutableState.requests }
|
||||
/// First `URLRequest` created on behalf of the `Request`. May not be the first one actually executed.
|
||||
public var firstRequest: URLRequest? { requests.first }
|
||||
/// Last `URLRequest` created on behalf of the `Request`.
|
||||
@@ -205,7 +203,7 @@ public class Request {
|
||||
|
||||
/// `URLRequest`s from all of the `URLSessionTask`s executed on behalf of the `Request`. May be different from
|
||||
/// `requests` due to `URLSession` manipulation.
|
||||
public var performedRequests: [URLRequest] { $mutableState.read { $0.tasks.compactMap(\.currentRequest) } }
|
||||
public var performedRequests: [URLRequest] { mutableState.read { $0.tasks.compactMap(\.currentRequest) } }
|
||||
|
||||
// MARK: HTTPURLResponse
|
||||
|
||||
@@ -216,7 +214,7 @@ public class Request {
|
||||
// MARK: Tasks
|
||||
|
||||
/// All `URLSessionTask`s created on behalf of the `Request`.
|
||||
public var tasks: [URLSessionTask] { $mutableState.tasks }
|
||||
public var tasks: [URLSessionTask] { mutableState.tasks }
|
||||
/// First `URLSessionTask` created on behalf of the `Request`.
|
||||
public var firstTask: URLSessionTask? { tasks.first }
|
||||
/// Last `URLSessionTask` created on behalf of the `Request`.
|
||||
@@ -227,7 +225,7 @@ public class Request {
|
||||
// MARK: Metrics
|
||||
|
||||
/// All `URLSessionTaskMetrics` gathered on behalf of the `Request`. Should correspond to the `tasks` created.
|
||||
public var allMetrics: [URLSessionTaskMetrics] { $mutableState.metrics }
|
||||
public var allMetrics: [URLSessionTaskMetrics] { mutableState.metrics }
|
||||
/// First `URLSessionTaskMetrics` gathered on behalf of the `Request`.
|
||||
public var firstMetrics: URLSessionTaskMetrics? { allMetrics.first }
|
||||
/// Last `URLSessionTaskMetrics` gathered on behalf of the `Request`.
|
||||
@@ -238,14 +236,14 @@ public class Request {
|
||||
// MARK: Retry Count
|
||||
|
||||
/// Number of times the `Request` has been retried.
|
||||
public var retryCount: Int { $mutableState.retryCount }
|
||||
public var retryCount: Int { mutableState.retryCount }
|
||||
|
||||
// MARK: Error
|
||||
|
||||
/// `Error` returned from Alamofire internally, from the network request directly, or any validators executed.
|
||||
public fileprivate(set) var error: AFError? {
|
||||
get { $mutableState.error }
|
||||
set { $mutableState.error = newValue }
|
||||
get { mutableState.error }
|
||||
set { mutableState.error = newValue }
|
||||
}
|
||||
|
||||
/// Default initializer for the `Request` superclass.
|
||||
@@ -283,7 +281,7 @@ public class Request {
|
||||
func didCreateInitialURLRequest(_ request: URLRequest) {
|
||||
dispatchPrecondition(condition: .onQueue(underlyingQueue))
|
||||
|
||||
$mutableState.write { $0.requests.append(request) }
|
||||
mutableState.write { $0.requests.append(request) }
|
||||
|
||||
eventMonitor?.request(self, didCreateInitialURLRequest: request)
|
||||
}
|
||||
@@ -313,7 +311,7 @@ public class Request {
|
||||
func didAdaptInitialRequest(_ initialRequest: URLRequest, to adaptedRequest: URLRequest) {
|
||||
dispatchPrecondition(condition: .onQueue(underlyingQueue))
|
||||
|
||||
$mutableState.write { $0.requests.append(adaptedRequest) }
|
||||
mutableState.write { $0.requests.append(adaptedRequest) }
|
||||
|
||||
eventMonitor?.request(self, didAdaptInitialRequest: initialRequest, to: adaptedRequest)
|
||||
}
|
||||
@@ -343,7 +341,7 @@ public class Request {
|
||||
func didCreateURLRequest(_ request: URLRequest) {
|
||||
dispatchPrecondition(condition: .onQueue(underlyingQueue))
|
||||
|
||||
$mutableState.read { state in
|
||||
mutableState.read { state in
|
||||
state.urlRequestHandler?.queue.async { state.urlRequestHandler?.handler(request) }
|
||||
}
|
||||
|
||||
@@ -354,7 +352,7 @@ public class Request {
|
||||
|
||||
/// Asynchronously calls any stored `cURLHandler` and then removes it from `mutableState`.
|
||||
private func callCURLHandlerIfNecessary() {
|
||||
$mutableState.write { mutableState in
|
||||
mutableState.write { mutableState in
|
||||
guard let cURLHandler = mutableState.cURLHandler else { return }
|
||||
|
||||
cURLHandler.queue.async { cURLHandler.handler(self.cURLDescription()) }
|
||||
@@ -369,7 +367,7 @@ public class Request {
|
||||
func didCreateTask(_ task: URLSessionTask) {
|
||||
dispatchPrecondition(condition: .onQueue(underlyingQueue))
|
||||
|
||||
$mutableState.write { state in
|
||||
mutableState.write { state in
|
||||
state.tasks.append(task)
|
||||
|
||||
guard let urlSessionTaskHandler = state.urlSessionTaskHandler else { return }
|
||||
@@ -416,7 +414,9 @@ public class Request {
|
||||
func didCancel() {
|
||||
dispatchPrecondition(condition: .onQueue(underlyingQueue))
|
||||
|
||||
error = error ?? AFError.explicitlyCancelled
|
||||
mutableState.write { mutableState in
|
||||
mutableState.error = mutableState.error ?? AFError.explicitlyCancelled
|
||||
}
|
||||
|
||||
eventMonitor?.requestDidCancel(self)
|
||||
}
|
||||
@@ -436,7 +436,7 @@ public class Request {
|
||||
func didGatherMetrics(_ metrics: URLSessionTaskMetrics) {
|
||||
dispatchPrecondition(condition: .onQueue(underlyingQueue))
|
||||
|
||||
$mutableState.write { $0.metrics.append(metrics) }
|
||||
mutableState.write { $0.metrics.append(metrics) }
|
||||
|
||||
eventMonitor?.request(self, didGatherMetrics: metrics)
|
||||
}
|
||||
@@ -468,6 +468,7 @@ public class Request {
|
||||
|
||||
self.error = self.error ?? error
|
||||
|
||||
let validators = validators.read { $0 }
|
||||
validators.forEach { $0() }
|
||||
|
||||
eventMonitor?.request(self, didCompleteTask: task, with: error)
|
||||
@@ -479,7 +480,7 @@ public class Request {
|
||||
func prepareForRetry() {
|
||||
dispatchPrecondition(condition: .onQueue(underlyingQueue))
|
||||
|
||||
$mutableState.write { $0.retryCount += 1 }
|
||||
mutableState.write { $0.retryCount += 1 }
|
||||
|
||||
reset()
|
||||
|
||||
@@ -513,9 +514,9 @@ public class Request {
|
||||
func finish(error: AFError? = nil) {
|
||||
dispatchPrecondition(condition: .onQueue(underlyingQueue))
|
||||
|
||||
guard !$mutableState.isFinishing else { return }
|
||||
guard !mutableState.isFinishing else { return }
|
||||
|
||||
$mutableState.isFinishing = true
|
||||
mutableState.isFinishing = true
|
||||
|
||||
if let error = error { self.error = error }
|
||||
|
||||
@@ -531,7 +532,7 @@ public class Request {
|
||||
///
|
||||
/// - Parameter closure: The closure containing the response serialization call.
|
||||
func appendResponseSerializer(_ closure: @escaping () -> Void) {
|
||||
$mutableState.write { mutableState in
|
||||
mutableState.write { mutableState in
|
||||
mutableState.responseSerializers.append(closure)
|
||||
|
||||
if mutableState.state == .finished {
|
||||
@@ -554,7 +555,7 @@ public class Request {
|
||||
func nextResponseSerializer() -> (() -> Void)? {
|
||||
var responseSerializer: (() -> Void)?
|
||||
|
||||
$mutableState.write { mutableState in
|
||||
mutableState.write { mutableState in
|
||||
let responseSerializerIndex = mutableState.responseSerializerCompletions.count
|
||||
|
||||
if responseSerializerIndex < mutableState.responseSerializers.count {
|
||||
@@ -571,7 +572,7 @@ public class Request {
|
||||
// Execute all response serializer completions and clear them
|
||||
var completions: [() -> Void] = []
|
||||
|
||||
$mutableState.write { mutableState in
|
||||
mutableState.write { mutableState in
|
||||
completions = mutableState.responseSerializerCompletions
|
||||
|
||||
// Clear out all response serializers and response serializer completions in mutable state since the
|
||||
@@ -605,7 +606,7 @@ public class Request {
|
||||
/// - Parameter completion: The completion handler provided with the response serializer, called when all serializers
|
||||
/// are complete.
|
||||
func responseSerializerDidComplete(completion: @escaping () -> Void) {
|
||||
$mutableState.write { $0.responseSerializerCompletions.append(completion) }
|
||||
mutableState.write { $0.responseSerializerCompletions.append(completion) }
|
||||
processNextResponseSerializer()
|
||||
}
|
||||
|
||||
@@ -618,7 +619,7 @@ public class Request {
|
||||
downloadProgress.totalUnitCount = 0
|
||||
downloadProgress.completedUnitCount = 0
|
||||
|
||||
$mutableState.write { state in
|
||||
mutableState.write { state in
|
||||
state.isFinishing = false
|
||||
state.responseSerializerCompletions = []
|
||||
}
|
||||
@@ -640,7 +641,7 @@ public class Request {
|
||||
///
|
||||
/// - Parameter perform: The closure to perform.
|
||||
func withState(perform: (State) -> Void) {
|
||||
$mutableState.withState(perform: perform)
|
||||
mutableState.withState(perform: perform)
|
||||
}
|
||||
|
||||
// MARK: Task Creation
|
||||
@@ -667,7 +668,7 @@ public class Request {
|
||||
/// - Returns: The instance.
|
||||
@discardableResult
|
||||
public func cancel() -> Self {
|
||||
$mutableState.write { mutableState in
|
||||
mutableState.write { mutableState in
|
||||
guard mutableState.state.canTransitionTo(.cancelled) else { return }
|
||||
|
||||
mutableState.state = .cancelled
|
||||
@@ -693,7 +694,7 @@ public class Request {
|
||||
/// - Returns: The instance.
|
||||
@discardableResult
|
||||
public func suspend() -> Self {
|
||||
$mutableState.write { mutableState in
|
||||
mutableState.write { mutableState in
|
||||
guard mutableState.state.canTransitionTo(.suspended) else { return }
|
||||
|
||||
mutableState.state = .suspended
|
||||
@@ -714,7 +715,7 @@ public class Request {
|
||||
/// - Returns: The instance.
|
||||
@discardableResult
|
||||
public func resume() -> Self {
|
||||
$mutableState.write { mutableState in
|
||||
mutableState.write { mutableState in
|
||||
guard mutableState.state.canTransitionTo(.resumed) else { return }
|
||||
|
||||
mutableState.state = .resumed
|
||||
@@ -754,7 +755,7 @@ public class Request {
|
||||
/// - Returns: The instance.
|
||||
@discardableResult
|
||||
public func authenticate(with credential: URLCredential) -> Self {
|
||||
$mutableState.credential = credential
|
||||
mutableState.credential = credential
|
||||
|
||||
return self
|
||||
}
|
||||
@@ -770,7 +771,7 @@ public class Request {
|
||||
/// - Returns: The instance.
|
||||
@discardableResult
|
||||
public func downloadProgress(queue: DispatchQueue = .main, closure: @escaping ProgressHandler) -> Self {
|
||||
$mutableState.downloadProgressHandler = (handler: closure, queue: queue)
|
||||
mutableState.downloadProgressHandler = (handler: closure, queue: queue)
|
||||
|
||||
return self
|
||||
}
|
||||
@@ -786,7 +787,7 @@ public class Request {
|
||||
/// - Returns: The instance.
|
||||
@discardableResult
|
||||
public func uploadProgress(queue: DispatchQueue = .main, closure: @escaping ProgressHandler) -> Self {
|
||||
$mutableState.uploadProgressHandler = (handler: closure, queue: queue)
|
||||
mutableState.uploadProgressHandler = (handler: closure, queue: queue)
|
||||
|
||||
return self
|
||||
}
|
||||
@@ -802,7 +803,7 @@ public class Request {
|
||||
/// - Returns: The instance.
|
||||
@discardableResult
|
||||
public func redirect(using handler: RedirectHandler) -> Self {
|
||||
$mutableState.write { mutableState in
|
||||
mutableState.write { mutableState in
|
||||
precondition(mutableState.redirectHandler == nil, "Redirect handler has already been set.")
|
||||
mutableState.redirectHandler = handler
|
||||
}
|
||||
@@ -821,7 +822,7 @@ public class Request {
|
||||
/// - Returns: The instance.
|
||||
@discardableResult
|
||||
public func cacheResponse(using handler: CachedResponseHandler) -> Self {
|
||||
$mutableState.write { mutableState in
|
||||
mutableState.write { mutableState in
|
||||
precondition(mutableState.cachedResponseHandler == nil, "Cached response handler has already been set.")
|
||||
mutableState.cachedResponseHandler = handler
|
||||
}
|
||||
@@ -842,7 +843,7 @@ public class Request {
|
||||
/// - Returns: The instance.
|
||||
@discardableResult
|
||||
public func cURLDescription(on queue: DispatchQueue, calling handler: @escaping (String) -> Void) -> Self {
|
||||
$mutableState.write { mutableState in
|
||||
mutableState.write { mutableState in
|
||||
if mutableState.requests.last != nil {
|
||||
queue.async { handler(self.cURLDescription()) }
|
||||
} else {
|
||||
@@ -863,13 +864,7 @@ public class Request {
|
||||
/// - Returns: The instance.
|
||||
@discardableResult
|
||||
public func cURLDescription(calling handler: @escaping (String) -> Void) -> Self {
|
||||
$mutableState.write { mutableState in
|
||||
if mutableState.requests.last != nil {
|
||||
underlyingQueue.async { handler(self.cURLDescription()) }
|
||||
} else {
|
||||
mutableState.cURLHandler = (underlyingQueue, handler)
|
||||
}
|
||||
}
|
||||
cURLDescription(on: underlyingQueue, calling: handler)
|
||||
|
||||
return self
|
||||
}
|
||||
@@ -885,7 +880,7 @@ public class Request {
|
||||
/// - Returns: The instance.
|
||||
@discardableResult
|
||||
public func onURLRequestCreation(on queue: DispatchQueue = .main, perform handler: @escaping (URLRequest) -> Void) -> Self {
|
||||
$mutableState.write { state in
|
||||
mutableState.write { state in
|
||||
if let request = state.requests.last {
|
||||
queue.async { handler(request) }
|
||||
}
|
||||
@@ -909,7 +904,7 @@ public class Request {
|
||||
/// - Returns: The instance.
|
||||
@discardableResult
|
||||
public func onURLSessionTaskCreation(on queue: DispatchQueue = .main, perform handler: @escaping (URLSessionTask) -> Void) -> Self {
|
||||
$mutableState.write { state in
|
||||
mutableState.write { state in
|
||||
if let task = state.tasks.last {
|
||||
queue.async { handler(task) }
|
||||
}
|
||||
@@ -928,19 +923,37 @@ public class Request {
|
||||
func onFinish(perform finishHandler: @escaping () -> Void) {
|
||||
guard !isFinished else { finishHandler(); return }
|
||||
|
||||
$mutableState.write { state in
|
||||
mutableState.write { state in
|
||||
state.finishHandlers.append(finishHandler)
|
||||
}
|
||||
}
|
||||
|
||||
/// Final cleanup step executed when the instance finishes response serialization.
|
||||
func cleanup() {
|
||||
delegate?.cleanup(after: self)
|
||||
let handlers = $mutableState.finishHandlers
|
||||
let handlers = mutableState.finishHandlers
|
||||
handlers.forEach { $0() }
|
||||
$mutableState.write { state in
|
||||
mutableState.write { state in
|
||||
state.finishHandlers.removeAll()
|
||||
}
|
||||
|
||||
delegate?.cleanup(after: self)
|
||||
}
|
||||
}
|
||||
|
||||
extension Request {
|
||||
/// Type indicating how a `DataRequest` or `DataStreamRequest` should proceed after receiving an `HTTPURLResponse`.
|
||||
public enum ResponseDisposition {
|
||||
/// Allow the request to continue normally.
|
||||
case allow
|
||||
/// Cancel the request, similar to calling `cancel()`.
|
||||
case cancel
|
||||
|
||||
var sessionDisposition: URLSession.ResponseDisposition {
|
||||
switch self {
|
||||
case .allow: return .allow
|
||||
case .cancel: return .cancel
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1085,11 +1098,16 @@ public class DataRequest: Request {
|
||||
/// `URLRequestConvertible` value used to create `URLRequest`s for this instance.
|
||||
public let convertible: URLRequestConvertible
|
||||
/// `Data` read from the server so far.
|
||||
public var data: Data? { mutableData }
|
||||
public var data: Data? { dataMutableState.data }
|
||||
|
||||
/// Protected storage for the `Data` read by the instance.
|
||||
@Protected
|
||||
private var mutableData: Data? = nil
|
||||
private struct DataMutableState {
|
||||
var data: Data?
|
||||
var httpResponseHandler: (queue: DispatchQueue,
|
||||
handler: (_ response: HTTPURLResponse,
|
||||
_ completionHandler: @escaping (ResponseDisposition) -> Void) -> Void)?
|
||||
}
|
||||
|
||||
private let dataMutableState = Protected(DataMutableState())
|
||||
|
||||
/// Creates a `DataRequest` using the provided parameters.
|
||||
///
|
||||
@@ -1122,7 +1140,9 @@ public class DataRequest: Request {
|
||||
override func reset() {
|
||||
super.reset()
|
||||
|
||||
mutableData = nil
|
||||
dataMutableState.write { mutableState in
|
||||
mutableState.data = nil
|
||||
}
|
||||
}
|
||||
|
||||
/// Called when `Data` is received by this instance.
|
||||
@@ -1131,15 +1151,41 @@ public class DataRequest: Request {
|
||||
///
|
||||
/// - Parameter data: The `Data` received.
|
||||
func didReceive(data: Data) {
|
||||
if self.data == nil {
|
||||
mutableData = data
|
||||
} else {
|
||||
$mutableData.write { $0?.append(data) }
|
||||
dataMutableState.write { mutableState in
|
||||
if mutableState.data == nil {
|
||||
mutableState.data = data
|
||||
} else {
|
||||
mutableState.data?.append(data)
|
||||
}
|
||||
}
|
||||
|
||||
updateDownloadProgress()
|
||||
}
|
||||
|
||||
func didReceiveResponse(_ response: HTTPURLResponse, completionHandler: @escaping (URLSession.ResponseDisposition) -> Void) {
|
||||
dataMutableState.read { dataMutableState in
|
||||
guard let httpResponseHandler = dataMutableState.httpResponseHandler else {
|
||||
underlyingQueue.async { completionHandler(.allow) }
|
||||
return
|
||||
}
|
||||
|
||||
httpResponseHandler.queue.async {
|
||||
httpResponseHandler.handler(response) { disposition in
|
||||
if disposition == .cancel {
|
||||
self.mutableState.write { mutableState in
|
||||
mutableState.state = .cancelled
|
||||
mutableState.error = mutableState.error ?? AFError.explicitlyCancelled
|
||||
}
|
||||
}
|
||||
|
||||
self.underlyingQueue.async {
|
||||
completionHandler(disposition.sessionDisposition)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override func task(for request: URLRequest, using session: URLSession) -> URLSessionTask {
|
||||
let copiedRequest = request
|
||||
return session.dataTask(with: copiedRequest)
|
||||
@@ -1179,7 +1225,48 @@ public class DataRequest: Request {
|
||||
withResult: result)
|
||||
}
|
||||
|
||||
$validators.write { $0.append(validator) }
|
||||
validators.write { $0.append(validator) }
|
||||
|
||||
return self
|
||||
}
|
||||
|
||||
/// Sets a closure called whenever the `DataRequest` produces an `HTTPURLResponse` and providing a completion
|
||||
/// handler to return a `ResponseDisposition` value.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - queue: `DispatchQueue` on which the closure will be called. `.main` by default.
|
||||
/// - handler: Closure called when the instance produces an `HTTPURLResponse`. The `completionHandler` provided
|
||||
/// MUST be called, otherwise the request will never complete.
|
||||
///
|
||||
/// - Returns: The instance.
|
||||
@_disfavoredOverload
|
||||
@discardableResult
|
||||
public func onHTTPResponse(
|
||||
on queue: DispatchQueue = .main,
|
||||
perform handler: @escaping (_ response: HTTPURLResponse,
|
||||
_ completionHandler: @escaping (ResponseDisposition) -> Void) -> Void
|
||||
) -> Self {
|
||||
dataMutableState.write { mutableState in
|
||||
mutableState.httpResponseHandler = (queue, handler)
|
||||
}
|
||||
|
||||
return self
|
||||
}
|
||||
|
||||
/// Sets a closure called whenever the `DataRequest` produces an `HTTPURLResponse`.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - queue: `DispatchQueue` on which the closure will be called. `.main` by default.
|
||||
/// - handler: Closure called when the instance produces an `HTTPURLResponse`.
|
||||
///
|
||||
/// - Returns: The instance.
|
||||
@discardableResult
|
||||
public func onHTTPResponse(on queue: DispatchQueue = .main,
|
||||
perform handler: @escaping (HTTPURLResponse) -> Void) -> Self {
|
||||
onHTTPResponse(on: queue) { response, completionHandler in
|
||||
handler(response)
|
||||
completionHandler(.allow)
|
||||
}
|
||||
|
||||
return self
|
||||
}
|
||||
@@ -1259,10 +1346,13 @@ public final class DataStreamRequest: Request {
|
||||
var numberOfExecutingStreams = 0
|
||||
/// Completion calls enqueued while streams are still executing.
|
||||
var enqueuedCompletionEvents: [() -> Void] = []
|
||||
/// Handler for any `HTTPURLResponse`s received.
|
||||
var httpResponseHandler: (queue: DispatchQueue,
|
||||
handler: (_ response: HTTPURLResponse,
|
||||
_ completionHandler: @escaping (ResponseDisposition) -> Void) -> Void)?
|
||||
}
|
||||
|
||||
@Protected
|
||||
var streamMutableState = StreamMutableState()
|
||||
let streamMutableState = Protected(StreamMutableState())
|
||||
|
||||
/// Creates a `DataStreamRequest` using the provided parameters.
|
||||
///
|
||||
@@ -1306,7 +1396,7 @@ public final class DataStreamRequest: Request {
|
||||
}
|
||||
|
||||
override func finish(error: AFError? = nil) {
|
||||
$streamMutableState.write { state in
|
||||
streamMutableState.write { state in
|
||||
state.outputStream?.close()
|
||||
}
|
||||
|
||||
@@ -1314,8 +1404,8 @@ public final class DataStreamRequest: Request {
|
||||
}
|
||||
|
||||
func didReceive(data: Data) {
|
||||
$streamMutableState.write { state in
|
||||
#if !(os(Linux) || os(Windows))
|
||||
streamMutableState.write { state in
|
||||
#if !canImport(FoundationNetworking) // If we not using swift-corelibs-foundation.
|
||||
if let stream = state.outputStream {
|
||||
underlyingQueue.async {
|
||||
var bytes = Array(data)
|
||||
@@ -1329,6 +1419,30 @@ public final class DataStreamRequest: Request {
|
||||
}
|
||||
}
|
||||
|
||||
func didReceiveResponse(_ response: HTTPURLResponse, completionHandler: @escaping (URLSession.ResponseDisposition) -> Void) {
|
||||
streamMutableState.read { dataMutableState in
|
||||
guard let httpResponseHandler = dataMutableState.httpResponseHandler else {
|
||||
underlyingQueue.async { completionHandler(.allow) }
|
||||
return
|
||||
}
|
||||
|
||||
httpResponseHandler.queue.async {
|
||||
httpResponseHandler.handler(response) { disposition in
|
||||
if disposition == .cancel {
|
||||
self.mutableState.write { mutableState in
|
||||
mutableState.state = .cancelled
|
||||
mutableState.error = mutableState.error ?? AFError.explicitlyCancelled
|
||||
}
|
||||
}
|
||||
|
||||
self.underlyingQueue.async {
|
||||
completionHandler(disposition.sessionDisposition)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Validates the `URLRequest` and `HTTPURLResponse` received for the instance using the provided `Validation` closure.
|
||||
///
|
||||
/// - Parameter validation: `Validation` closure used to validate the request and response.
|
||||
@@ -1351,12 +1465,12 @@ public final class DataStreamRequest: Request {
|
||||
withResult: result)
|
||||
}
|
||||
|
||||
$validators.write { $0.append(validator) }
|
||||
validators.write { $0.append(validator) }
|
||||
|
||||
return self
|
||||
}
|
||||
|
||||
#if !(os(Linux) || os(Windows))
|
||||
#if !canImport(FoundationNetworking) // If we not using swift-corelibs-foundation.
|
||||
/// Produces an `InputStream` that receives the `Data` received by the instance.
|
||||
///
|
||||
/// - Note: The `InputStream` produced by this method must have `open()` called before being able to read `Data`.
|
||||
@@ -1370,7 +1484,7 @@ public final class DataStreamRequest: Request {
|
||||
defer { resume() }
|
||||
|
||||
var inputStream: InputStream?
|
||||
$streamMutableState.write { state in
|
||||
streamMutableState.write { state in
|
||||
Foundation.Stream.getBoundStreams(withBufferSize: bufferSize,
|
||||
inputStream: &inputStream,
|
||||
outputStream: &state.outputStream)
|
||||
@@ -1381,6 +1495,47 @@ public final class DataStreamRequest: Request {
|
||||
}
|
||||
#endif
|
||||
|
||||
/// Sets a closure called whenever the `DataRequest` produces an `HTTPURLResponse` and providing a completion
|
||||
/// handler to return a `ResponseDisposition` value.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - queue: `DispatchQueue` on which the closure will be called. `.main` by default.
|
||||
/// - handler: Closure called when the instance produces an `HTTPURLResponse`. The `completionHandler` provided
|
||||
/// MUST be called, otherwise the request will never complete.
|
||||
///
|
||||
/// - Returns: The instance.
|
||||
@_disfavoredOverload
|
||||
@discardableResult
|
||||
public func onHTTPResponse(
|
||||
on queue: DispatchQueue = .main,
|
||||
perform handler: @escaping (_ response: HTTPURLResponse,
|
||||
_ completionHandler: @escaping (ResponseDisposition) -> Void) -> Void
|
||||
) -> Self {
|
||||
streamMutableState.write { mutableState in
|
||||
mutableState.httpResponseHandler = (queue, handler)
|
||||
}
|
||||
|
||||
return self
|
||||
}
|
||||
|
||||
/// Sets a closure called whenever the `DataRequest` produces an `HTTPURLResponse`.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - queue: `DispatchQueue` on which the closure will be called. `.main` by default.
|
||||
/// - handler: Closure called when the instance produces an `HTTPURLResponse`.
|
||||
///
|
||||
/// - Returns: The instance.
|
||||
@discardableResult
|
||||
public func onHTTPResponse(on queue: DispatchQueue = .main,
|
||||
perform handler: @escaping (HTTPURLResponse) -> Void) -> Self {
|
||||
onHTTPResponse(on: queue) { response, completionHandler in
|
||||
handler(response)
|
||||
completionHandler(.allow)
|
||||
}
|
||||
|
||||
return self
|
||||
}
|
||||
|
||||
func capturingError(from closure: () throws -> Void) {
|
||||
do {
|
||||
try closure()
|
||||
@@ -1395,7 +1550,7 @@ public final class DataStreamRequest: Request {
|
||||
appendResponseSerializer {
|
||||
self.underlyingQueue.async {
|
||||
self.responseSerializerDidComplete {
|
||||
self.$streamMutableState.write { state in
|
||||
self.streamMutableState.write { state in
|
||||
guard state.numberOfExecutingStreams == 0 else {
|
||||
state.enqueuedCompletionEvents.append {
|
||||
self.enqueueCompletion(on: queue, stream: stream)
|
||||
@@ -1546,23 +1701,22 @@ public class DownloadRequest: Request {
|
||||
}
|
||||
|
||||
/// Protected mutable state specific to `DownloadRequest`.
|
||||
@Protected
|
||||
private var mutableDownloadState = DownloadRequestMutableState()
|
||||
private let mutableDownloadState = Protected(DownloadRequestMutableState())
|
||||
|
||||
/// If the download is resumable and is eventually cancelled or fails, this value may be used to resume the download
|
||||
/// using the `download(resumingWith data:)` API.
|
||||
///
|
||||
/// - Note: For more information about `resumeData`, see [Apple's documentation](https://developer.apple.com/documentation/foundation/urlsessiondownloadtask/1411634-cancel).
|
||||
public var resumeData: Data? {
|
||||
#if !(os(Linux) || os(Windows))
|
||||
return $mutableDownloadState.resumeData ?? error?.downloadResumeData
|
||||
#if !canImport(FoundationNetworking) // If we not using swift-corelibs-foundation.
|
||||
return mutableDownloadState.resumeData ?? error?.downloadResumeData
|
||||
#else
|
||||
return $mutableDownloadState.resumeData
|
||||
return mutableDownloadState.resumeData
|
||||
#endif
|
||||
}
|
||||
|
||||
/// If the download is successful, the `URL` where the file was downloaded.
|
||||
public var fileURL: URL? { $mutableDownloadState.fileURL }
|
||||
public var fileURL: URL? { mutableDownloadState.fileURL }
|
||||
|
||||
// MARK: Initial State
|
||||
|
||||
@@ -1605,7 +1759,7 @@ public class DownloadRequest: Request {
|
||||
override func reset() {
|
||||
super.reset()
|
||||
|
||||
$mutableDownloadState.write {
|
||||
mutableDownloadState.write {
|
||||
$0.resumeData = nil
|
||||
$0.fileURL = nil
|
||||
}
|
||||
@@ -1620,7 +1774,7 @@ public class DownloadRequest: Request {
|
||||
eventMonitor?.request(self, didFinishDownloadingUsing: task, with: result)
|
||||
|
||||
switch result {
|
||||
case let .success(url): $mutableDownloadState.fileURL = url
|
||||
case let .success(url): mutableDownloadState.fileURL = url
|
||||
case let .failure(error): self.error = error
|
||||
}
|
||||
}
|
||||
@@ -1698,7 +1852,7 @@ public class DownloadRequest: Request {
|
||||
///
|
||||
/// - Returns: The instance.
|
||||
private func cancel(optionallyProducingResumeData completionHandler: ((_ resumeData: Data?) -> Void)?) -> Self {
|
||||
$mutableState.write { mutableState in
|
||||
mutableState.write { mutableState in
|
||||
guard mutableState.state.canTransitionTo(.cancelled) else { return }
|
||||
|
||||
mutableState.state = .cancelled
|
||||
@@ -1714,7 +1868,7 @@ public class DownloadRequest: Request {
|
||||
// Resume to ensure metrics are gathered.
|
||||
task.resume()
|
||||
task.cancel { resumeData in
|
||||
self.$mutableDownloadState.resumeData = resumeData
|
||||
self.mutableDownloadState.resumeData = resumeData
|
||||
self.underlyingQueue.async { self.didCancelTask(task) }
|
||||
completionHandler(resumeData)
|
||||
}
|
||||
@@ -1754,7 +1908,7 @@ public class DownloadRequest: Request {
|
||||
withResult: result)
|
||||
}
|
||||
|
||||
$validators.write { $0.append(validator) }
|
||||
validators.write { $0.append(validator) }
|
||||
|
||||
return self
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user