11

URLSessionUploadTask新しく作成されたものがすぐにキャンセルされるという奇妙な問題が発生しています。Xcode 8 の現在のベータ版のバグかどうかはわかりません。

投稿しようとしているコードは一度だけ正常に実行されたため、バグである可能性があると思われます。その後、変更は加えられず、単に機能しなくなりました。はい、文字通り一度実行した後、動作を停止しました。最後にエラーを投稿します。

以下にコードを掲載しますが、最初にここでのロジックがどのように機能するかを要約します。

私のテスト、またはユーザー公開 API (Playgrounds またはアプリで直接使用するための IE) は、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)
    }
}

次のエラーで常に即座に失敗します。

エラー Domain=NSURLErrorDomain Code=-999 「キャンセルされまし」 NSErrorFailingURLStringKey = https://anilist.co/api/auth/access_token?client_secret=削除&grant_type=authorization_code&redirect_uri=genericwebsitethatshouldntexist.bo&client_id=ibanez-hod6w&code=削除}

次の点に注意してください。

  • セッションで使用される URL は有効です。
  • すべての資格情報が有効です。
  • 以前は発生しなかった「キャンセルされた」エラーで即座に失敗します。どこでもタスクをキャンセルしていないため、システムによってキャンセルされています。
  • 無期限実行が有効になっているプレイグラウンドでも失敗します。これは私のテストに限定されません。

これが私が試したことのリストです:

  • これはバグだと思うので、まずプロジェクトをクリーンアップし、派生データを削除し、すべてのシミュレーターをリセットしようとしました。それらのどれも機能しませんでした。
  • Macを再起動するところまで行きました...
  • 強力なポインターがないためにアップロード タスクの割り当てが解除され、次に を呼び出しているという小さな疑いの下で、によって作成されたタスクを返すようにcancel書き直して、テストの変数に割り当てました。タスクはまだキャンセルされていました。authorizebuildPOSTTask

私がまだ試していないこと (ただし、これらに取り組んでいる間、他のアイデアを受け入れます):

  • 物理デバイスで実行します。これは iOS 10 プロジェクトであるため、現在 iPad に iOS 10 をダウンロードしています。編集:試してみましたが、これを行うことはできません。

私は何を試してみるべきかについてのアイデアがありません。生成されたログには有用な情報がないようです。

編集:

プロジェクト全体をここに投稿することにしました。とにかく完成したらオープンソースになり、私が取得したAPI認証情報はテストアプリ用です。

ALCキット

4

4 に答える 4

0

ひょっとして Ensighten などのサードパーティ製ライブラリを使用していませんか? XCode 8 ベータ版 (XCode 7 では正常に動作) でまったく同じ問題が発生し、パラメーターが nil のすべてのブロックがクラッシュを引き起こしていました。問題の原因となっているのは、何らかのエンコーディングを行っているライブラリであることが判明しました。

于 2016-07-28T16:07:58.540 に答える
0

あなたのサーバーは壊れています..

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) {

    }
}
于 2016-07-16T03:03:18.497 に答える