关键词:
【中文标题】URLSessionUploadTask 立即自动取消【英文标题】:URLSessionUploadTask getting automatically cancelled instantly 【发布时间】: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 凭据是用于测试应用程序的。
ALCKit
【问题讨论】:
对,对不起,这很重要,哈哈。是的,测试确实有一个 waitForExpectationsWithTimeout 调用。我将编辑我的问题以添加它。我还没有在实际的应用程序中尝试过(这是我正在构建的框架,但稍后将构建一个使用的应用程序),但它在启用无限期执行的 Swift 游乐场中确实失败了。 你可以试试:pastebin.com/B7nZFY1n 它会打印响应吗?报错? 感谢布兰登的意见。我在操场上运行它,它运行良好。按预期打印响应。 为你给我的代码写一个测试也很好。我的方法调用之间一定发生了什么事。 pastebin.com/ijshDH6Q 似乎与您使用的代码相同。我能够根据您的错误代码推断出它。 【参考方案1】:在为此苦苦挣扎了 6 天,并在谷歌上不停地寻找解决方案之后,我真的很高兴说我终于弄明白了。
事实证明,无论出于什么神秘原因,uploadTask(with:from:completionHandler)
中的 from:
参数都不能为 nil。尽管该参数被标记为可选Data
,但它在丢失时会立即取消。这可能是 Apple 方面的一个错误,当我无法让它工作时我打开了一个错误,所以我将使用这些新信息更新我的错误报告。
话虽如此,我所要做的就是更新我的buildPOSTTask
方法,以说明传递的字典可能为零。有了它,它现在可以正常工作了:
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
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)")
else
postParameters = Data()
let postTask = urlSession.uploadTask(with: request, from: postParameters, completionHandler: completion)
return postTask
【讨论】:
刚刚为此苦苦挣扎了两个多小时。苹果有没有回复过你的错误报告?由于没有发布参数而被取消的错误是荒谬的(而且令人愤怒) 他们没有回复。它也没有被标记为重复。它自 2016 年 7 月 19 日起开放。 现在是 2019 年。仍然需要传递非零数据。 @Fitsyu 是的。该错误报告也被忽略了 3 年多。【参考方案2】:你的服务器坏了..
tcp_connection_cancel 1
nw_socket_handle_socket_event Event mask: 0x4
nw_socket_handle_socket_event Socket received WRITE_CLOSE event
nw_endpoint_handler_cancel [1 anilist.co:443 ready resolver (satisfied)]
nw_endpoint_handler_cancel [1.1 104.28.1.44:443 ready socket-flow (satisfied)]
__nw_socket_service_writes_block_invoke sendmsg(fd 9, 31 bytes): socket has been closed
nw_endpoint_flow_protocol_error [1.1
104.28.1.44:443 cancelled socket-flow (null)] Socket protocol sent error: [32] Broken pipe
nw_endpoint_flow_protocol_disconnected [1.1 104.28.1.44:443 cancelled socket-flow (null)] Output protocol disconnected
nw_endpoint_handler_cancel [1.2 104.28.0.44:443 initial path (null)]
nw_resolver_cancel_on_queue 0x60800010da40
[NWConcrete_tcp_connection dealloc] 1
[User Defaults] CFPrefsPlistSource<0x6180000f8700> (Domain: XIO.PrivateAPITest, User: kCFPreferencesCurrentUser, ByHost: No, Container: (null)) is waiting for writes to complete so it can determine if new data is available
它无限等待“写入”完成..
它发送请求.. 进行 SSL 握手并且没有得到响应。它超时并认为它是一个损坏的请求..
class WTF : NSObject, URLSessionDelegate
var urlSession: URLSession!
override init()
super.init()
urlSession = URLSession(configuration: .default, delegate: self, delegateQueue: nil)
var request = URLRequest(url: URL(string: "https://anilist.co/api/auth/access_token?client_secret=REMOVED&grant_type=authorization_code&redirect_uri=genericwebsitethatshouldntexist.bo&client_id=ibanez-hod6w&code=REMOVED")!)
request.httpMethod = "POST"
let data = try! JSONSerialization.data(withJSONObject: ["Test":"Test"], options: [])
urlSession.uploadTask(with: request, from: data).resume()
func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: (URLSession.AuthChallengeDisposition, URLCredential?) -> Void)
completionHandler(.performDefaultHandling, nil)
func urlSession(_ session: URLSession, task: URLSessionTask, didSendBodyData bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64)
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: NSError?)
func urlSession(_ session: URLSession, task: URLSessionTask, willPerformHTTPRedirection response: HTTPURLResponse, newRequest request: URLRequest, completionHandler: (URLRequest?) -> Void)
completionHandler(request)
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse, completionHandler: (URLSession.ResponseDisposition) -> Void)
completionHandler(.allow)
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data)
【讨论】:
好吧,就像我在问题的 cmets 中所说的那样,当我用任何通用 URL 替换 URL 时,我遇到了同样的错误。我用http://www.***.com
和https://www.google.com
替换了buildPOSTTask
中的fullURL
,同样的事情正在发生。您在此答案中提供的代码也在 Playground 中成功完成,我能够看到响应(对于 Anilist URL)。看起来服务器没有损坏(顺便说一句,我不管理它),并且没有关于人们在授权应用程序时遇到问题的报告。这很令人困惑,我将在实际应用中尝试一下,看看效果如何。
好的,刚刚在单视图应用程序中测试了我的整个代码。无论 URL 是 AniList 还是 StatckOverflow 或 Google,我都会收到相同的错误。这绝对是我的代码错误。
更多信息,整个is waiting for writes to complete so it can determine if new data is available
似乎与请求本身没有任何关系。它似乎是当前 beta 版本中某些激进日志记录的一部分。我只能找到this,但你可以看到他们甚至没有使用 URLSession 或等效的 API。
尝试在全新的机器上运行代码。同样的错误。哈哈。好吧,至少我知道我的主计算机表现得不好。
从 Xcode 8 Beta 3 开始,我们可以正式放弃 is waiting for writes to complete so it can determine if new data is available
日志记录,因为它毫无意义。谢谢你的意见。会尝试找出问题所在。【参考方案3】:
您是否有机会使用 Ensighten 等第三方库?我在 XCode 8 beta 中遇到了完全相同的问题(在 XCode 7 中运行良好),并且我所有带有 nil 参数的块都导致了崩溃。原来是图书馆做了一些编码导致了这个问题。
【讨论】:
你是如何确定的? 我通过反复试验。我禁用了图书馆,一切都运行良好。在我的特殊情况下,他们已经更新了库并且一切运行良好。【参考方案4】:对我来说,这是一个导致问题的弱引用,所以我改变了
completion: [weak self] (response: Result<ResponseType, Error>)
到
completion: [self] (response: Result<ResponseType, Error>)
【讨论】:
自动创建立即购买按钮贝宝?
】自动创建立即购买按钮贝宝?【英文标题】:automaticallycreatebuynowbuttonpaypal?【发布时间】:2011-07-1722:51:29【问题描述】:我想自动创建一个paypal立即购买按钮。最简单的方法是什么?【问题讨论】:【参考方案1】:我还发现您... 查看详情
在插入中立即使用自动增量值
】在插入中立即使用自动增量值【英文标题】:Instantlyusingauto-incrementvalueininsert【发布时间】:2014-03-1220:02:25【问题描述】:这是一个困扰我很久的问题。假设我有一个包含两列的表(id和file)。有没有办法在插入查询中立即使... 查看详情
javascript自动执行函数(立即调用函数)
开头:各种原因总结一下javascript中的自动执行函数(立即调用函数)的一些方法,正文如下 在Javascript中,任何function在执行的时候都会创建一个执行上下文,因为function声明变量和function有可能只在该function内部,这个... 查看详情
Paypal 交易完成后立即自动返回(无需 10 秒)到我们的网站
】Paypal交易完成后立即自动返回(无需10秒)到我们的网站【英文标题】:autoreturnimmediately(without10sec)toourwebsiteafterPaypaltransactioncompleted【发布时间】:2017-08-1111:42:56【问题描述】:我很想知道如何进行PayPal交易,并让用户立即自... 查看详情
立即抓取mySql中自动生成的字段以供使用
】立即抓取mySql中自动生成的字段以供使用【英文标题】:Immediatelygrabauto-generatedfieldinmySqlforuse【发布时间】:2021-01-1005:47:37【问题描述】:在此获取期间,它会创建一条新记录,并在mySql表中自动增加一个名为“employee_id”的字... 查看详情
jQuery select2打开后立即自动关闭
】jQueryselect2打开后立即自动关闭【英文标题】:jQueryselect2automaticcloseimmediateafteropened【发布时间】:2019-09-0808:40:12【问题描述】:select2在bootstrap4modal中,它只发生在modal中。看上面的截图,当我点击元素时,它会显示,然后关闭... 查看详情
PayPal 立即购买按钮 - 强制自动退货(无需通过账户设置)
】PayPal立即购买按钮-强制自动退货(无需通过账户设置)【英文标题】:PayPalbuynowbutton-forceautoreturn(withoutsettingviaaccount)【发布时间】:2014-06-1114:11:17【问题描述】:我正在尝试建立一个市场,让用户尽可能快速简单地买卖商品... 查看详情
为啥有时会立即释放内存,而有时仅在自动释放池耗尽时才释放内存?
】为啥有时会立即释放内存,而有时仅在自动释放池耗尽时才释放内存?【英文标题】:Whyismemorysometimesdeallocatedimmediatelyandothertimesonlywhenautoreleasepoolisdrained?为什么有时会立即释放内存,而有时仅在自动释放池耗尽时才释放内存... 查看详情
自动布局不会在 iOS 8-Xcode 6 中立即更新帧
】自动布局不会在iOS8-Xcode6中立即更新帧【英文标题】:AutolayoutisnotupdatingframesinstantlyiniOS8-Xcode6【发布时间】:2014-10-0909:38:03【问题描述】:我在XCode6中使用autolayout。我已将以下约束应用于scrollview。我尝试在iPhone4Inchs设备的-view... 查看详情
如何在插入新行后立即将自动生成的主键值保存到第二列
】如何在插入新行后立即将自动生成的主键值保存到第二列【英文标题】:Howtosaveauto-generatedprimarykeyvalueintosecondcolumnrightafterinsertingnewrow【发布时间】:2020-12-0114:50:37【问题描述】:在表中插入新行时,我想在插入新行后立即将... 查看详情
postgresql数据库使用delete命令删除数据后,空间是不是立即自动释放?
如果没有自动释放,怎样手动释放??请各位高人指点,小弟新手上路!!感激不尽参考技术A不能自动释放,需要使用VACUUM命令请参考http://www.91linux.com/html/article/guanli/20070621/2902.html参考资料:PostgreSQL数据库的日常维护工作本回... 查看详情
立即收取订阅更改费用
】立即收取订阅更改费用【英文标题】:Immediatelychargeforsubscriptionchanges【发布时间】:2017-11-0901:35:48【问题描述】:我们正在为客户的订阅使用Stripe付款处理。当用户更改计划时,我们希望他们立即为按比例分配的差额付费。当... 查看详情
为啥 Protractor 会立即运行每一行代码?
】为啥Protractor会立即运行每一行代码?【英文标题】:WhyisProtractorrunningeverylineofcodeimmediately?为什么Protractor会立即运行每一行代码?【发布时间】:2015-01-0315:37:01【问题描述】:为什么Protractor会立即运行每一行代码?所以我有... 查看详情
UILabel 没有立即获取内容
】UILabel没有立即获取内容【英文标题】:UILabelnotgettingcontentsimmediately【发布时间】:2015-11-1902:09:45【问题描述】:我正在使用UITableViewAutomaticDimension让我的TableViewCells自动调整到内容的大小。如果我在第一个单元格中有多行文本... 查看详情
核心蓝牙立即断开连接后外设
】核心蓝牙立即断开连接后外设【英文标题】:CoreBluetoothimmediatedisconnectPeripheralafterconnected【发布时间】:2014-04-1608:03:02【问题描述】:在核心蓝牙中,连接到设备后,会在5到10秒后自动断开连接。它给出了这样的错误:ErrorDomai... 查看详情
Paypal 经常性:立即收取试用金额?
】Paypal经常性:立即收取试用金额?【英文标题】:Paypalrecurring:trialamountchargedimmediatelyornot?【发布时间】:2015-02-1711:44:07【问题描述】:我在Sanbox模式下使用PaypalRESTAPI(Java)来测试我的定期付款设置。业务规则:1-新订阅后,我想... 查看详情
文本框输入内容立即触发事件(代码片段)
1、当输入内容时,立即触发某事件,宜用onkeyup,onchange会有延时。2、jsp页面中常用的触发方法有: onchange、onkeyup、onblur3、js中一般去掉on,例如 //自动检索$("#resetSearch").keyup(function()varname=$("#resetSearch").val();$("#projectListPan... 查看详情
Couchbase - 创建视图并立即访问其数据
】Couchbase-创建视图并立即访问其数据【英文标题】:Couchbase-CreatingaViewandaccessingitsdataimmediatelly【发布时间】:2014-06-1709:29:12【问题描述】:假设我需要一个(自动)升级脚本,如果它是,它会重置所有用户的余额我想运行一个ja... 查看详情