web-dev-qa-db-ja.com

SwiftでreturnでcompletionHandler Closureを使用する方法は?

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のこのページに記載されているように、クロージャを返すための正しい構文を使用しています。

https://developer.Apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Closures.html

23
almel
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
    }
}
34
fuzz

here を見ると、dataTaskWithRequest:completionHandler:には、期待される戻り値のない完了ハンドラがあります。

completion handler's interface

つまり、NSURLSessionインスタンスは値を期待しませんfrom fromこのメソッドを呼び出した後に処理を続行します。つまり、完了クロージャ(または、必要に応じてブロック)で手順が終了します。

completion handlerを介して呼び出し元に何かを返送する理由が明確ではありません。

4
holex

提供する必要のあるクロージャーは、戻り値のタイプVoidであり、AnyObject!ではない)である必要があるため、完了ハンドラーは何も返すことができません。

func dataTaskWithRequest(_ request: NSURLRequest!,
   completionHandler completionHandler: ((NSData!,
                              NSURLResponse!,
                              NSError!) -> Void)!) -> NSURLSessionDataTask!
2
Skyte

CloudKitから取得したコンテンツに基づいて中央DBの情報を更新しようとしたときに、同様の問題に遭遇しました。 CKデータをプルするパターンにはすべて、戻り値を許可しないこれらの非同期完了ハンドラーがあります。

異なるコンテキストで同様のコードを再利用できるようにしたかったため、CKコールアウトを独自のクラスに分離し、コアクラスを準拠させるデリゲートプロトコルを定義しました。完了ハンドラー内で、CK呼び出しから取得したデータをデリゲートメソッド経由で保存したい場所に送り返しました。

簡単です。

0
Ben Carroll