Alamofire错误领域= NSURLErrorDomain,代码= -999,“取消”

6

我已经成功获取了我的令牌的钥匙串并将其传递给下面显示的AccessTokenAdapter类。 http127.0.0.1:8000/api2/projects/?format=json被传递为projectsURL。

    class AccessTokenAdapter: RequestAdapter {
        private let accessToken: String

        init(accessToken: String) {
            self.accessToken = accessToken
        }

        func adapt(_ urlRequest: URLRequest) throws -> URLRequest {
            var urlRequest = urlRequest
         //   print("JWT \(accessToken)")
            urlRequest.setValue("JWT \(accessToken)", forHTTPHeaderField: "Authorization")

            return urlRequest
        }
    }


    let sessionManager = SessionManager()
    sessionManager.adapter = AccessTokenAdapter(accessToken: self.keychain["token"]!)

    sessionManager.request(self.projectsURL, method: .get, encoding: JSONEncoding.default).responseJSON{ response in
        switch response.result {
        case .success:
            print("yey I made it")
        case .failure(let error):
            print(error)
        }
    }

然而,从print(error)中看到我的Xcode显示的错误是: Error Domain=NSURLErrorDomain Code=-999 "cancelled" UserInfo={NSErrorFailingURLKey=http://127.0.0.1:8000/api2/projects/?format=json, NSLocalizedDescription=cancelled, NSErrorFailingURLStringKey=http127.0.0.1:8000/api2/projects/?format=json}
有什么想法吗? 使用Alamofire 4.0、Keychain、Xcode 8.1、Swift3进行IT技术开发 使用JWT进行身份验证 使用Postman请求头,键为“Authentication”,值为“JWT(在此生成的令牌)”正常工作
5个回答

13

当您将sessionManager设置为let常量时,它的生命周期不会超过包含它的函数,因此当管理器被解除分配时,会立即结束会话。

为了解决这个问题,让sessionManager的生命周期更长。例如,在我的情况下,我将其作为类属性:

class NetworkRequest: {

   var sessionManager = Alamofire.SessionManager()

   ...

   func performRequest(_ call: APICall, customLink: String = "", parameters: Dictionary<String, Any> = ["":"" as Any]) {

        let sessionConfig = URLSessionConfiguration.default
        sessionConfig.timeoutIntervalForRequest = call.suggestedTimeout()
        sessionConfig.timeoutIntervalForResource = call.suggestedTimeout()
        sessionManager = Alamofire.SessionManager(configuration: sessionConfig)
        sessionManager.adapter = AccessTokenAdapter()

        sessionManager.request(urlString,
                      method: call.method(),
                      parameters: parameters,
                      encoding: call.chooseEncoding(),
                      headers: [:])
        .responseJSON
        { response in
          ...
        }

解决方案可能因情况而异,但思路是保持sessionManager处于活动状态,直到网络请求结束。


3
self.getSessionManager()
                 .request(urlstring, 
                          method: methods, 
                          parameters: parameters, 
                          encoding: JSONEncoding.prettyPrinted, 
                          headers: Header
                  ).responseJSON(
                         queue: nil, 
                         options: JSONSerialization.ReadingOptions.allowFragments
) { (responseObject) in
 // response parsing code is here
}.session.finishTasksAndInvalidate() 

在任务完成后,只需将invalidate方法放置于其后即可,表示session.finishTasksAndInvalidate()

所有工作都很顺利。


2

通常这种错误是由于您创建的SessionManager超出了范围并被删除,导致请求被取消。保留对其的引用,我的解决方案是在APIService类中使用一个变量来存储SessionManager。

  public lazy var sharedManager: SessionManager = {
    let configuration = URLSessionConfiguration.default

    configuration.timeoutIntervalForRequest = 60
    configuration.timeoutIntervalForResource = 60

    let manager = Alamofire.SessionManager(configuration: configuration)
    return manager
}()

我同意这个。当保留对它的引用时,它运行良好。 - kkklc

1

刚解决。看起来需要事先设置HTTP方法。

    let url = URL(string: "http://127.0.0.1:8000/api2/projects/?format=json")
    var urlRequest = URLRequest(url:url!)
    urlRequest.httpMethod = HTTPMethod.get.rawValue
    urlRequest.addValue("JWT \(self.keychain["token"]!)", forHTTPHeaderField: "Authorization")
    urlRequest.addValue("application/json", forHTTPHeaderField: "Accept")
    Alamofire.request(urlRequest)
        .responseJSON { response in
            debugPrint(response)
    }

0
如果其他人像我一样遇到了这个问题,而且它不是https问题或其他SO帖子中提供的答案,那么我发现原因是一个控制器正在发出请求,但该控制器不应该显示。有点像如果您有一些控制器仅在特定条件下出现,并且它本身会在viewWillAppear或其他位置发出请求。我使用了一个基类来确定条件控制器中的调用是否应尝试请求。这为我解决了问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接