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:
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
}
}
comme vous le voyez ici , le dataTaskWithRequest:completionHandler:
a un gestionnaire d'achèvement sans valeur de retour attendue.
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.
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!
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.