私はライブラリを書いているので、UIKitを使用していない、私のiOSアプリでも同じコードが機能しますが、コマンドラインで実行すると機能しません。 PlayGroundでも動作しているようです。
何らかの理由でコールバックがトリガーされないため、printステートメントは実行されません。
internal class func post(request: URLRequest, responseCallback: @escaping (Bool, AnyObject?) -> ()) {
execTask(request: request, taskCallback: { (status, resp) -> Void in
responseCallback(status, resp)
})
}
internal class func clientURLRequest(url: URL, path: String, method: RequestMethod.RawValue, params: Dictionary<String, Any>? = nil) -> URLRequest {
var request = URLRequest(url: url)
request.httpMethod = method
do {
let jsonData = try JSONSerialization.data(withJSONObject: (params! as [String : Any]), options: .prettyPrinted)
request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
request.httpBody = jsonData
} catch let error as NSError {
print(error)
}
return request
}
private class func execTask(request: URLRequest, taskCallback: @escaping (Bool,
AnyObject?) -> ()) {
let session = URLSession(configuration: URLSessionConfiguration.default)
print("THIS LINE IS PRINTED")
let task = session.dataTask(with: request, completionHandler: {(data, response, error) -> Void in
if let data = data {
print("THIS ONE IS NOT PRINTED")
let json = try? JSONSerialization.jsonObject(with: data, options: [])
if let response = response as? HTTPURLResponse , 200...299 ~= response.statusCode {
taskCallback(true, json as AnyObject?)
} else {
taskCallback(false, json as AnyObject?)
}
}
})
task.resume()
}
編集-:私はライブラリを書いているので、UIKitを使用していません、私のiOSアプリでも同じコードは動作しますが、コマンドラインで実行すると動作しません。 PlayGroundでも動作しているようです。
シンプルなアプリをゼロから作成しました。 (Xcode 8ベータ6/Swift 3)コントローラーにコードを貼り付けました。
この1つIS PRINTED
この1つIS PRINTED、TOO
戻りました
だから、うまくいっているようだ。
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let URLString = "https://Apple.com"
let url = URL(string: URLString)
let request = URLRequest(url: url!)
ViewController.execTask(request: request) { (ok, obj) in
print("I AM BACK")
}
}
private class func execTask(request: URLRequest, taskCallback: @escaping (Bool,
AnyObject?) -> ()) {
let session = URLSession(configuration: URLSessionConfiguration.default)
print("THIS LINE IS PRINTED")
let task = session.dataTask(with: request, completionHandler: {(data, response, error) -> Void in
if let data = data {
print("THIS ONE IS PRINTED, TOO")
let json = try? JSONSerialization.jsonObject(with: data, options: [])
if let response = response as? HTTPURLResponse , 200...299 ~= response.statusCode {
taskCallback(true, json as AnyObject?)
} else {
taskCallback(false, json as AnyObject?)
}
}
})
task.resume()
}
}
私は答えが遅いことを知っていますが、あなたが問題を理解していないか、他の場所で問題を取得していない場合は、これを試してみましょう。
メソッドのスコープ外にセッション変数を保存する必要があります(インスタンス変数にします)。関数スコープでローカルに定義したため。完了ハンドラーを呼び出す前にその割り当てを解除します。完了ハンドラーはセッションオブジェクトを保持できず、実行ループの実行後にガベージコレクターがセッションオブジェクトの割り当てを解除します。デリゲートまたは完了ハンドラーからコールバックする場合は、常にそのようなオブジェクトを保持する必要があります。
self.session = URLSession(configuration: URLSessionConfiguration.default)
ここで提案された変更は、今すぐ動作します。
Swiftコマンドラインプログラム)からNSURLSessionを使用
var sema = DispatchSemaphore( value: 0 )
private func execTask(request: URLRequest, taskCallback: @escaping (Bool,
AnyObject?) -> ()) {
let session = URLSession(configuration: URLSessionConfiguration.default, delegate: self, delegateQueue: nil )
session.dataTask(with: request) {(data, response, error) -> Void in
if let data = data {
let json = try? JSONSerialization.jsonObject(with: data, options: [])
if let response = response as? HTTPURLResponse , 200...299 ~= response.statusCode {
taskCallback(true, json as AnyObject?)
} else {
taskCallback(false, json as AnyObject?)
}
}
}.resume()
sema.wait()
}
let dataTask = session.dataTask(with: request, completionHandler: {data, response,error -> Void in
print("Request : \(response)")
let res = response as! HTTPURLResponse
print("Status Code : \(res.statusCode)")
let strResponse = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
print("Response String :\(strResponse)")
})
dataTask.resume()