JSONデータを返すRESTful APIを使用しようとしています。 HTTPリクエストを作成し、独自のメソッドにヘッダーを設定するコードをカプセル化し、url Stringを入力して呼び出すことができ、メソッドがJSONオブジェクトを返すようにします。
次のコードスニペットでは、リクエストオブジェクトを既に作成し、ヘッダーを設定しています。その変数を「req」と呼びます。 data、response、またはerrorという名前のオブジェクトは宣言していません。 JSONオブジェクトを正しく出力する次のコードがあります
let sesh = NSURLSession.sharedSession()
let dataTask = sesh.dataTaskWithRequest(req, completionHandler: {(data, response, error) in
var jsonError : NSError?
let jsonBlob = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableLeaves, error: &jsonError)
println(jsonBlob)
});
dataTask.resume()
だからここに私の質問です。このcompletionHandlerブロックが「AnyObject!」タイプのjsonBlobを返すことができるようにするにはどうすればよいですか?コードを次のようにわずかに変更した場合:
let sesh = NSURLSession.sharedSession()
let dataTask = sesh.dataTaskWithRequest(req, completionHandler: {(data, response, error) -> AnyObject! in
var jsonError : NSError?
let jsonBlob : AnyObject! = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableLeaves, error: &jsonError)
return jsonBlob
});
dataTask.resume()
dataTaskWithRequest:completionHandlerの呼び出しがコンパイラ警告を発するため、プログラムはコンパイルされません。
Could not find an overload for 'dataTaskWithRequest' that accepts the supplied arguments
これはわかりません。 Swift Docsのこのページに記載されているように、クロージャを返すための正しい構文を使用しています。
func getSomething(callback: (Array<AnyObject>) -> ()) {
var dataTask = NSURLSessionDataTask()
dataTask = session.dataTaskWithRequest(request) { (data, response, error) in
if (error == nil) {
var callbackArray = Array<MyObject>()
let responseDict = NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers, error: nil) as NSDictionary
let response = responseDict.objectForKey("response_key") as NSDictionary
let array = response.objectForKey("array_key") as NSArray
for item: AnyObject in array {
var arrayItem = MyObject(dict: item as NSDictionary)
callbackArray.append(arrayItem)
}
callback(callbackArray)
} else {
// handle an error
}
}
dataTask.resume()
}
その後、次のようなことができます:
getSomething() { (response) in
if let responseArray = response as? Array<MyObject> {
self.somethings = responseArray
}
}
here を見ると、dataTaskWithRequest:completionHandler:
には、期待される戻り値のない完了ハンドラがあります。
つまり、NSURLSession
インスタンスは値を期待しませんfrom fromこのメソッドを呼び出した後に処理を続行します。つまり、完了クロージャ(または、必要に応じてブロック)で手順が終了します。
completion handlerを介して呼び出し元に何かを返送する理由が明確ではありません。
提供する必要のあるクロージャーは、戻り値のタイプVoidであり、AnyObject!ではない)である必要があるため、完了ハンドラーは何も返すことができません。
func dataTaskWithRequest(_ request: NSURLRequest!,
completionHandler completionHandler: ((NSData!,
NSURLResponse!,
NSError!) -> Void)!) -> NSURLSessionDataTask!
CloudKitから取得したコンテンツに基づいて中央DBの情報を更新しようとしたときに、同様の問題に遭遇しました。 CKデータをプルするパターンにはすべて、戻り値を許可しないこれらの非同期完了ハンドラーがあります。
異なるコンテキストで同様のコードを再利用できるようにしたかったため、CKコールアウトを独自のクラスに分離し、コアクラスを準拠させるデリゲートプロトコルを定義しました。完了ハンドラー内で、CK呼び出しから取得したデータをデリゲートメソッド経由で保存したい場所に送り返しました。
簡単です。