URLSessionUploadTask 立即自动取消

     2023-02-24     255

关键词:

【中文标题】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.***.comhttps://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... 查看详情