【发布时间】:2016-07-15 23:32:15
【问题描述】:
我遇到了一个奇怪的问题,新创建的URLSessionUploadTask 立即被取消。我不确定这是否是当前 Xcode 8 测试版的错误。
我怀疑这可能是一个错误,因为我要发布的代码恰好运行了一次。之后没有对其进行任何更改,然后它就停止了工作。是的,它确实运行了一次,然后就停止了工作。我将在接近尾声时发布错误。
我将在下面发布代码,但首先我将总结这里的逻辑是如何工作的。
我的测试或用户公开的 API(IE 用于 Playgrounds 或直接在应用程序上使用)调用 authorize 方法。这个authorize 方法将依次调用buildPOSTTask,它将构造一个有效的URL 并返回一个URLSessionUploadTask 以供authorize 方法使用。
话虽如此,代码如下:
会议:
internal let urlSession = URLSession(configuration: .default)
创建上传任务的函数:
internal func buildPOSTTask(onURLSession urlSession: URLSession, appendingPath path: String, withPostParameters postParams: [String : String]?, getParameters getParams: [String : String]?, httpHeaders: [String : String]?, completionHandler completion: URLSessionUploadTaskCompletionHandler) -> URLSessionUploadTask {
let fullURL: URL
if let gets = getParams {
fullURL = buildURL(appendingPath: path, withGetParameters: gets)
} else {
fullURL = URL(string: path, relativeTo: baseURL)!
}
var request = URLRequest(url: fullURL)
request.httpMethod = "POST"
var postParameters: Data? = nil
if let posts = postParams {
do {
postParameters = try JSONSerialization.data(withJSONObject: posts, options: [])
} catch let error as NSError {
fatalError("[\(#function) \(#line)]: Could not build POST task: \(error.localizedDescription)")
}
}
let postTask = urlSession.uploadTask(with: request, from: postParameters, completionHandler: completion)
return postTask
}
身份验证函数,它使用由上述函数创建的任务:
public func authorize(withCode code: String?, completion: AccessTokenExchangeCompletionHandler) {
// I have removed a lot of irrelevant code here, such as the dictionary building code, to make this snippet shorter.
let obtainTokenTask = buildPOSTTask(onURLSession: self.urlSession, appendingPath: "auth/access_token", withPostParameters: nil, getParameters: body, httpHeaders: nil) { (data, response, error) in
if let err = error {
completion(error: err)
} else {
print("Response is \(response)")
completion(error: nil)
}
}
obtainTokenTask.resume()
}
我在测试中发现了这个错误:
let testUser = Anilist(grantType: grant, name: "Test Session")
let exp = expectation(withDescription: "Waiting for authorization")
testUser.authorize(withCode: "a valid code") { (error) in
if let er = error {
XCTFail("Authentication error: \(er.localizedDescription)")
}
exp.fulfill()
}
self.waitForExpectations(withTimeout: 5) { (err) in
if let error = err {
XCTFail(error.localizedDescription)
}
}
它总是因为这个错误而立即失败:
错误域=NSURLErrorDomain 代码=-999 “取消” UserInfo={NSErrorFailingURLKey=https://anilist.co/api/auth/access_token?client_secret=REMOVED&grant_type=authorization_code&redirect_uri=genericwebsitethatshouldntexist.bo&client_id=ibanez-hod6w&code=REMOVED, NSLocalizedDescription=取消, NSErrorFailingURLStringKey=https://anilist.co/api/auth/access_token?client_secret=REMOVED&grant_type=authorization_code&redirect_uri=genericwebsitethatshouldntexist.bo&client_id=ibanez-hod6w&code=REMOVED}
请注意以下几点:
- 会话使用的 URL 有效。
- 所有凭据均有效。
- 它立即失败并出现“已取消”错误,这在以前根本没有发生过。我没有在任何地方取消任务,所以它被系统取消了。
- 在启用了无限期执行的 Playgrounds 上也会失败。这不仅限于我的测试。
这是我尝试过的事情的清单:
- 因为我怀疑这是一个错误,我首先尝试清理我的项目,删除派生数据,并重置所有模拟器。他们都没有工作。
- 甚至重启我的 Mac...
- 由于上传任务没有任何强指针而被释放,并反过来调用
cancel,我也重写了authorize以返回由buildPOSTTask创建的任务并将其分配给我的测试中的一个变量。任务仍在取消。
我还没有尝试过的事情(但我会接受任何其他想法,因为我正在研究这些):
- 在物理设备上运行它。目前在 iPad 上下载 iOS 10,因为这是一个 iOS 10 项目。编辑:我刚试过,这是不可能的。
我不知道该尝试什么。生成的日志似乎没有任何有用的信息。
编辑:
我决定在这里发布整个项目。无论如何,这东西完成后都会开源,我得到的 API 凭据是用于测试应用程序的。
【问题讨论】:
-
对,对不起,这很重要,哈哈。是的,测试确实有一个 waitForExpectationsWithTimeout 调用。我将编辑我的问题以添加它。我还没有在实际的应用程序中尝试过(这是我正在构建的框架,但稍后将构建一个使用的应用程序),但它在启用无限期执行的 Swift 游乐场中确实失败了。
-
你可以试试:pastebin.com/B7nZFY1n 它会打印响应吗?报错?
-
感谢布兰登的意见。我在操场上运行它,它运行良好。按预期打印响应。
-
为你给我的代码写一个测试也很好。我的方法调用之间一定发生了什么事。
-
pastebin.com/ijshDH6Q 似乎与您使用的代码相同。我能够根据您的错误代码推断出它。
标签: ios nsurlsession swift3 xcode8 nsurlsessionuploadtask