web-dev-qa-db-ja.com

Swift 3:URLSession / URLRequestが機能しない

私はまだアプリケーションをSwift 2からSwift 3に変換しようとしています。これは、すべてのAppleデバイスは現在iOS10を実行しています。

コード変換を実行し、うまくいっていると思いましたが、JSONの問題をデバッグしようとしているときに(別の質問に投稿されています)、送信されていないリクエストを処理しています。

let params: [String:AnyObject] = [
    "email":"\(self.preferences.string(forKey: "preference_email")!)" as AnyObject
]
let requestParams: [String:AnyObject] = [
    "action":"601" as AnyObject,
    "params":params as AnyObject
]

do {
    let requestObject = try JSONSerialization.data(withJSONObject: requestParams, options:[])
    var request = URLRequest(url: URL(string: "http://domain.tld/path/")!)

    request.httpBody = requestObject
    request.httpMethod = "POST"

    let config = URLSessionConfiguration.default
    let session = URLSession(configuration: config)

    NSLog("Got here?")

    session.dataTask(with: request) {data, response, error in
        guard let data = data, error == nil else {
            print("error=\(error)")
            return
        }

        NSLog("Got here 3?")

        let object:JSON = JSON(data:data)

        NSLog("Object: \(object)")
    }.resume()

    NSLog("Got here 4?")
} catch {
    NSLog("Got here catch?")
}

NSLog("End of getUser")

上記のコードは、次の出力を生成します。

2016-10-04 13:00:12.011969 OneTouch[1589:623015] [DYMTLInitPlatform] platform initialization successful
2016-10-04 13:00:12.264319 OneTouch[1589:622954] [MC] System group container for systemgroup.com.Apple.configurationprofiles path is /private/var/containers/Shared/SystemGroup/systemgroup.com.Apple.configurationprofiles
2016-10-04 13:00:12.265321 OneTouch[1589:622954] [MC] Reading from public effective user settings.
2016-10-04 13:00:12.295055 OneTouch[1589:622954] Got here?
2016-10-04 13:00:12.295445 OneTouch[1589:622954] Got here 4?
2016-10-04 13:00:12.295515 OneTouch[1589:622954] End of getUser
(lldb) 

つまり、リクエストは行われていません。 PLISTに再度追加する必要のあるキーはありますか?これは煩わしくなり始めています。

以下は私の古いコードであり、それはもう機能していません:

let params: [String:AnyObject] = [
    "email":"\(self.preferences.string(forKey: "preference_email")!)" as AnyObject
]
let requestParams: [String:AnyObject] = [
    "action":"601" as AnyObject,
    "params":params as AnyObject
]

do {
    let requestObject = try JSONSerialization.data(withJSONObject: requestParams, options:[])
    let request = NSMutableURLRequest(url: URL(string: "http://domain.tld/path/" as String)!, cachePolicy:NSURLRequest.CachePolicy.reloadIgnoringLocalCacheData, timeoutInterval: 20)

    request.httpBody = requestObject
    request.httpMethod = "POST"

    NSLog("Got here?")

    let task = URLSession.shared.dataTask(with: request as URLRequest, completionHandler: {data, response, error in
        if error != nil {
            NSLog("Got here 2?")
        }

        NSLog("Got here 3?")

        let object:JSON = JSON(data:data!)

        NSLog("Object: \(object)")
    })

    NSLog("Got here 4?")

    task.resume()
} catch {
    NSLog("Got here catch?")
}

NSLog("End of getUser")

上記のコードは、他のコードと同じ出力を生成します!

8
recoilnetworks

getUserを呼び出した直後にブレークポイントを設定すると、非同期で実行されるURLSessionタスクの完了ハンドラー(つまり、要求がすぐに失敗するか、キャッシュされた応答によって満たされない限り、通常は後で終了します)が実行されない場合があります。呼ばれる機会がありました。

dataTask完了ハンドラー内にブレークポイントを設定すると、その時点でデータが表示されます。


個人的には、getUserに完了ハンドラーを指定して、完了したことを確認します。

func getUser(completionHandler: @escaping (JSON?, Error?) -> Void) {
    let params = [
        "email":"\(preferences.string(forKey: "preference_email")!)"
    ]

    let requestParams: [String: Any] = [
        "action": "601",
        "params": params
    ]

    do {
        let requestObject = try JSONSerialization.data(withJSONObject: requestParams)

        var request = URLRequest(url: URL(string: "http://domain.tld/path/")!, cachePolicy: .reloadIgnoringLocalCacheData, timeoutInterval: 20)

        request.httpBody = requestObject
        request.httpMethod = "POST"
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        request.setValue("application/json", forHTTPHeaderField: "Accept")

        let task = URLSession.shared.dataTask(with: request) {data, response, error in
            guard let data = data, error == nil else {
                completionHandler(nil, error)
                return
            }

            completionHandler(JSON(data: data), nil)
        }

        task.resume()
    } catch {
        completionHandler(nil, error)
    }
}

次に、それを呼び出すと、次のようなことができます。

getUser { json, error in
    guard let json = json else {
        print(error)
        return
    }

    // do something with json
    print(json)
}

そして、ブレークポイントをgetUserの完了ハンドラーに置くだけです。また、完了ハンドラーがメインキューで実行されるかどうかは保証されていないため、UIまたはモデルの更新をメインキューにディスパッチして戻す必要があります。

0
Rob