我有一个 NetworkRequest 类,我所有的 Alamofire 请求都是在其中发出的:
class NetworkRequest {
static let request = NetworkRequest()
var currentRequest: Alamofire.Request?
let dataManager = DataManager()
let networkManager = NetworkReachabilityManager()
let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT
func downloadData<T: Film>(slug: String, provider: String, section: String, dynamic: String, anyClass: T, completion: ([T]?) -> Void ) {
var token: String = ""
if LOGGED_IN == true {
token = "\(NSUserDefaults.standardUserDefaults().valueForKey(TOKEN)!)"
}
let headers = [
"Access": "application/json",
"Authorization": "Bearer \(token)"
]
let dataUrl = "\(BASE_URL)\(slug)\(provider)\(section)\(dynamic)"
print(headers)
print(dataUrl)
if networkManager!.isReachable {
currentRequest?.cancel()
dispatch_async(dispatch_get_global_queue(priority, 0)) {
if let url = NSURL(string: dataUrl) {
let request = Alamofire.request(.GET, url, headers: headers)
request.validate().responseJSON { response in
switch response.result {
case .Success:
if let data = response.result.value as! [String: AnyObject]! {
let receivedData = self.dataManager.parseDataToFilms(data, someClass: anyClass)
completion(receivedData)
}
case .Failure(let error):
print("Alamofire error: \(error)")
if error.code == 1001 {
self.goToNoConnectionVC()
}
print("canceled")
}
}
}
}
} else {
goToNoConnectionVC()
}
}
}
而且我需要取消以前的 downloadData 请求,当新的 downloadData 请求开始时,尝试使用 currentRequest?.cancel() 取消,但没有帮助。
已尝试使用 NSOperationsBlock 取消操作,但它不会取消当前操作。
我现在阻止 UI,以便用户无法发送另一个请求。但这是不正确的,会导致稍后出现一些错误。
现在在
Alamofire
4 上 Alamofire.Manager.sharedInstance.session
不可用,您应该使用 this 解决方案:
let sessionManager = Alamofire.SessionManager.default
sessionManager.session.getTasksWithCompletionHandler { dataTasks, uploadTasks, downloadTasks in
dataTasks.forEach { $0.cancel() }
uploadTasks.forEach { $0.cancel() }
downloadTasks.forEach { $0.cancel() }
}
如果您想取消(暂停、恢复)特定请求,您可以检查
.forEach
块中的请求网址,如下所示:
dataTasks.forEach {
if ($0.originalRequest?.url?.absoluteString == url) {
$0.cancel()
}
}
找到需要的解决方案:
func stopAllSessions() {
Alamofire.Manager.sharedInstance.session.getAllTasksWithCompletionHandler { tasks in
tasks.forEach { $0.cancel() }
}
}
Alamofire 5 更新
func stopAllSessions() {
AF.session.getTasksWithCompletionHandler { (sessionDataTask, uploadData, downloadData) in
sessionDataTask.forEach { $0.cancel() }
uploadData.forEach { $0.cancel() }
downloadData.forEach { $0.cancel() }
}
}
斯威夫特5
要取消所有请求,请使用
Alamofire.Session.default.session.getTasksWithCompletionHandler({ dataTasks, uploadTasks, downloadTasks in
dataTasks.forEach { $0.cancel() }
uploadTasks.forEach { $0.cancel() }
downloadTasks.forEach { $0.cancel() }
})
要取消具有特定 url 的请求,请使用
Alamofire.Session.default.session.getTasksWithCompletionHandler({ dataTasks, uploadTasks, downloadTasks in
dataTasks.forEach {
if ($0.originalRequest?.url?.absoluteString == "www.google.com") {
$0.cancel()
}
}
uploadTasks.forEach {
if ($0.originalRequest?.url?.absoluteString == "www.google.com") {
$0.cancel()
}
}
downloadTasks.forEach {
if ($0.originalRequest?.url?.absoluteString == "www.google.com") {
$0.cancel()
}
}
})
如果您想取消请求,您需要追踪发出的请求并尝试取消。您可以将其存储在数组中并取消之前存储的每个请求。 在您的代码中创建一个请求:
let request = Alamofire.request(.GET, url, headers: headers)
但你试图取消那些永远不被重视的currentRequest?.cancel()
。
对于使用 AF.request
AF.Session.getTasksWithCompletionHandler
或 getAllTasks(completionHandler: <#T##([URLSessionTask]) -> Void#>)
的人来说,总是返回空,所以我找到了一个解决方案来取消上一个任务,方法是存储上一个任务实例,然后检查它是否重试相同的请求,如果它包含相同的 url,则取消存储的 DataRequest
致电 DataRequestInstance.cancel()
例如:
private var isRetrying = false
private var latestDataRequest: DataRequest?
typealias ServiceCompletionHandler = (Swift.Result<ExampleResponse, Error>) -> ()
func requestTokenDataWith(completionHandler: @escaping ServiceCompletionHandler) {
let url = // Your service url
let parameters = // Required parameters
// Cancel first request if isn't response until now
if isRetrying, let latestDataRequest {
// Find request task that contains exact same url with new request
// Or you can directly cancel old DataRequest without looking for url
let sameOldRequests = latestDataRequest.tasks.compactMap({ $0.originalRequest?.url }).filter({ $0 == url })
if sameOldRequests.isEmpty == false {
// Cancel first task and release it's instance
latestDataRequest.cancel()
self.latestDataRequest = nil
// Log error
let error = NetworkError(
domain: Constants.bundleId(),
code: -1,
type: .stillWaitingForResponse
)
Logger.shared.info(from: "TokenService", message: error.localizedDescription)
}
}
// No requests already in, mark as true to block coming requests
isRetrying = true
latestDataRequest = AF.request(
url,
method: .post,
parameters: params,
encoding: URLEncoding.httpBody,
interceptor: self
)
.validate(contentType: ["application/json"])
.validate(statusCode: 200..<300)
.responseJSON(completionHandler: { response in
// Stop blocking incoming requests
self?.isRetrying = false
completionHandler(response)
}
}