web-dev-qa-db-fra.com

Comment utiliser ComplementHandler Closure avec retour dans Swift?

J'essaie de nous une API RESTful qui renvoie des données json. Je veux encapsuler le code qui crée la demande HTTP et définit les en-têtes dans sa propre méthode afin que je puisse l'appeler en entrant une chaîne d'URL, puis que la méthode renvoie un objet JSON.

Dans l'extrait de code suivant, j'ai déjà créé l'objet de demande et défini les en-têtes, et j'appelle cette variable "req". Je n'ai déclaré aucun objet nommé données, réponse ou erreur. J'ai le code suivant qui imprime correctement un objet 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()

Voici donc ma question. Comment puis-je faire en sorte que ce bloc d'achèvementHandler soit capable de renvoyer le jsonBlob, qui est de type "AnyObject!"? Si je modifie légèrement le code pour qu'il soit le suivant:

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()

le programme ne compilera pas alors que l'appel à dataTaskWithRequest: complétHandler donne un avertissement du compilateur disant:

 Could not find an overload for 'dataTaskWithRequest' that accepts the supplied arguments

Je ne comprends pas ça. J'utilise la syntaxe correcte pour renvoyer les fermetures, comme indiqué dans cette page des documents Swift:

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()
}

Ensuite, vous pourriez faire quelque chose comme:

getSomething() { (response) in
    if let responseArray = response as? Array<MyObject> {
        self.somethings = responseArray
    }
}
34
fuzz

comme vous le voyez ici , le dataTaskWithRequest:completionHandler: a un gestionnaire d'achèvement sans valeur de retour attendue.

completion handler's interface

cela signifie que l'instance NSURLSession n'attend aucune valeur de votre part pour continuer après avoir appelé cette méthode ; en d'autres termes: vous clôturez la clôture (ou bloquez, si vous voulez) termine ici la procédure.

il n'est pas clair pourquoi vous souhaitez renvoyer quoi que ce soit à l'appelant via le gestionnaire d'achèvement.

4
holex

Le gestionnaire de complétion ne peut rien retourner car la fermeture que vous devez fournir doit être de type retour Void et non AnyObject !.

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

Je suis tombé sur un problème similaire en essayant de mettre à jour les informations dans une base de données centrale en fonction du contenu extrait de CloudKit. Les modèles d'extraction de données CK ont tous ces gestionnaires d'achèvement asynchrones qui n'autorisent aucune valeur de retour.

Comme je voulais pouvoir réutiliser un code similaire dans différents contextes, j'ai séparé les appels CK dans leur propre classe et défini un protocole délégué auquel j'ai rendu la classe principale conforme. Dans les gestionnaires d'achèvement, j'ai renvoyé les données récupérées des appels CK à l'endroit où je veux les stocker via des méthodes déléguées.

Peasy facile.

0
Ben Carroll