1

SOAP投稿のためにNSURLConnectionからNSURLSessionに移行しようとしていますが、NSURLSessionDataDelegateに問題があるようです。

正常に動作する NSURLConnection の古いコードは次のとおりです。

let soapMessage = "<?xml version='1.0' encoding='UTF-8'?><SOAP-ENV:Envelope xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/' xmlns:ns1='http://tempuri.org/'><SOAP-ENV:Body><ns1:get_Countries/></SOAP-ENV:Body></SOAP-ENV:Envelope>"
    print("Soap Packet is \(soapMessage)")

    let urlString = "https://example.com/Service.svc"
    let url = NSURL(string: urlString)
    let theRequest = NSMutableURLRequest(URL: url!)
    let msgLength = String(soapMessage.characters.count)

    theRequest.addValue("text/xml; charset=utf-8", forHTTPHeaderField: "Content-Type")
    theRequest.addValue(msgLength, forHTTPHeaderField: "Content-Length")
    theRequest.addValue("http://tempuri.org/IService/get_Countries", forHTTPHeaderField: "SoapAction")
    theRequest.HTTPMethod = "POST"
    theRequest.HTTPBody = soapMessage.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
    print("Request is \(theRequest.allHTTPHeaderFields!)")

    let connection = NSURLConnection(request: theRequest, delegate: self, startImmediately: false)
    connection?.start()

次に、このコードは NSURLConnectionDelegate を使用し、次のように正常に動作します。

func connection(connection: NSURLConnection!, didReceiveResponse response: NSURLResponse!) {
    MutableData.length = 0;
    let httpresponse = response as? NSHTTPURLResponse
    print("status \(httpresponse?.statusCode)")
    //print("headers \(httpresponse?.allHeaderFields)")
}

func connection(connection: NSURLConnection!, didReceiveData data: NSData!) {
    MutableData.appendData(data)
}


func connection(connection: NSURLConnection, didFailWithError error: NSError) {
    NSLog("Error with Soap call: %@", error)

}

func connectionDidFinishLoading(connection: NSURLConnection!) {
    let xmlParser = NSXMLParser(data: MutableData)
    xmlParser.delegate = self
    xmlParser.parse()
    xmlParser.shouldResolveExternalEntities = true
}

func connection(connection: NSURLConnection, willSendRequestForAuthenticationChallenge challenge: NSURLAuthenticationChallenge) {
    if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust && challenge.protectionSpace.host == "example.com" {
        NSLog("yep")
        let credential = NSURLCredential(trust: challenge.protectionSpace.serverTrust!)
        challenge.sender!.useCredential(credential, forAuthenticationChallenge: challenge)
    } else {
        NSLog("nope")
        challenge.sender!.performDefaultHandlingForAuthenticationChallenge!(challenge)
    }
}

そのコードはすべて正常に動作し、参照用に過ぎないので、私が過去に行ったことと、API が実際に機能するという事実を確認できます! ただし、代わりに NSURLSession と NSURLSessionDataDelegate を使用すると、正しく動作しなくなります。

新しいコードは次のとおりです。

let soapMessage = "<?xml version='1.0' encoding='UTF-8'?><SOAP-ENV:Envelope xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/' xmlns:ns1='http://tempuri.org/'><SOAP-ENV:Body><ns1:get_Countries/></SOAP-ENV:Body></SOAP-ENV:Envelope>"
    print("Soap Packet is \(soapMessage)")

    let urlString = "https://example.com/Service.svc"
    let url = NSURL(string: urlString)
    let theRequest = NSMutableURLRequest(URL: url!)
    let msgLength = String(soapMessage.characters.count)

    theRequest.addValue("text/xml; charset=utf-8", forHTTPHeaderField: "Content-Type")
    theRequest.addValue(msgLength, forHTTPHeaderField: "Content-Length")
    theRequest.addValue("http://tempuri.org/IService/get_Countries", forHTTPHeaderField: "SoapAction")
    theRequest.HTTPMethod = "POST"
    theRequest.HTTPBody = soapMessage.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
    print("Request is \(theRequest.allHTTPHeaderFields!)")

let config = NSURLSessionConfiguration.defaultSessionConfiguration()
let session = NSURLSession(configuration:config, delegate: self, delegateQueue: NSOperationQueue.mainQueue())
let task = session.dataTaskWithRequest(theRequest)
task.resume()

私が使用しているデリゲートは、NSURLSessionDelegate、NSURLSessionDataDelegate です。

func URLSession(session: NSURLSession, didReceiveChallenge challenge: NSURLAuthenticationChallenge, completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential?) -> Void) {

    print("Am in NSURLSessionDelegate didReceiveChallenge")

    if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust && challenge.protectionSpace.host == "example.com" {
        NSLog("yep authorised")
        let credential = NSURLCredential(trust: challenge.protectionSpace.serverTrust!)
        challenge.sender!.useCredential(credential, forAuthenticationChallenge: challenge)
    } else {
        NSLog("nope")
        challenge.sender!.performDefaultHandlingForAuthenticationChallenge!(challenge)
    }

}
func URLSessionDidFinishEventsForBackgroundURLSession(session: NSURLSession) {
    print("Am in URLSessionDidFinishEventsForBackgroundURLSession")
    let xmlParser = NSXMLParser(data: MutableData)
    xmlParser.delegate = self
    xmlParser.parse()
    xmlParser.shouldResolveExternalEntities = true
}
func URLSession(session: NSURLSession, didBecomeInvalidWithError error: NSError?) {
    print("error of \(error)")
}

func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveResponse response: NSURLResponse, completionHandler: (NSURLSessionResponseDisposition) -> Void) {
    print("Am in didReceiveResponse")
    MutableData.length = 0
}


func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData data: NSData) {
    print("Am in didReceiveData")
    MutableData.appendData(data)
}

func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?) {
    print("error of \(error)")
}

したがって、コードを実行すると、次の出力が得られます。

「NSURLSessionDelegate didReceiveChallenge にいます」「はい、承認されました」

したがって、didReceiveChallenge はうまくいき、HTTPS の安全な証明書をうまく承認しているように見えますが、それ以上何も起こらず、他に何もしません。全て。

だから私は立ち往生しています。もちろん、すべて正常に動作するので、引き続き NSURLConnection を使用できますが、NSURLSession、特にどこが間違っているのかを理解したいと思います。誰かがそれを助けることができれば、それは素晴らしいことです。

ありがとう

4

2 に答える 2

1

他の誰かが同じ問題を抱えている場合に備えて、これを整理しました。問題は、didReceiveChallenge および didReceiveResponse デリゲートで completionHandler を使用していなかったことです。

于 2015-10-05T15:46:56.150 に答える
0
func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveResponse response: NSURLResponse, completionHandler: (NSURLSessionResponseDisposition) -> Void) {

completionHandler(NSURLSessionResponseDisposition.Allow) //.Cancel,ダウンロードを中止したい場合 }

于 2016-05-11T15:45:03.590 に答える