2016-12-24 2 views
-2
public func fetchAllRooms(completion: ([RemoteRoom]?) -> Void) { 
    let url = NSURL(string: "http://localhost:5984/rooms/_all_docs?include_docs=true")! 

    let urlRequest = NSMutableURLRequest(
    URL: url, 
    cachePolicy: .ReloadIgnoringLocalAndRemoteCacheData, 
    timeoutInterval: 10.0 * 1000) 
    urlRequest.HTTPMethod = "GET" 
    urlRequest.addValue("application/json", forHTTPHeaderField: "Accept") 

    let task = urlSession.dataTaskWithRequest(urlRequest) 
    { (data, response, error) -> Void in 
    guard error == nil else { 
     print("Error while fetching remote rooms: \(error)") 
     completion(nil) 
     return 
    } 

    guard let json = try? NSJSONSerialization.JSONObjectWithData(data!, 
     options: []) as? [String: AnyObject] else { 
     print("Nil data received from fetchAllRooms service") 
     completion(nil) 
     return 
    } 

    guard let rows = json["rows"] as? [[String: AnyObject]] { 
     print("Malformed data received from fetchAllRooms service") 
     completion(nil) 
     return 
    } 

    var rooms = [RemoteRoom]() 
    for roomDict in rows { 
     rooms.append(RemoteRoom(jsonData: roomDict)) 
    } 

    completion(rooms) 
    } 

    task.resume() 
} 

Je suis assez nouveau dans Swift.S'il vous plaît, aidez-moi à comprendre cet extrait de code

fetchAllRooms fonction prend une autre fonction avec l'achèvement du nom, qui prend un tableau de paramètres RemoteRoom et renvoie void. Maintenant, à la fin, le bloc d'achèvement (la syntaxe ressemble à un rappel de bloc dans Objective c) est appelé avec un paramètre RemoteRoom. RemoteRoom est initialisé & Le bloc d'achèvement est appelé completion(rooms). Mais où est le corps du bloc d'achèvement? Quelles sont les lignes à exécuter lorsque la ligne completion(rooms) est exécutée?

Répondre

3

Le corps du bloc d'achèvement est le corps d'une fonction ou d'une fermeture. Les exemples qui suivent tous la même chose:

func fetch(completion: (Int) -> Int) { 
    print("executing fetch") 

    let result = completion(5) 
    print("completion(5) returns \(result)") 
} 

// calling it passing a function with the right signature 
func addOne(i: Int) -> Int { 
    return i + 1 
} 

fetch(completion: addOne) 

// passing a closure 
fetch(completion: { i in return i + 1 }) 

// same with trailing closure syntax 
fetch() { i in 
    return i + 1 
} 

//() isn't needed if completion is the only parameter 
fetch { i in 
    return i + 1 
} 

// simplified closure removing parameter name and return 
fetch { $0 + 1 } 
+0

Merci pour Awesomely réponse complète @vacawwama. Couple de questions que j'ai. Si je compare "// passer une fermeture" et "// même avec la syntaxe de clôture" quand utiliser la fermeture et quand utiliser la fermeture arrière? un cas particulier? Pourquoi utilise-t-on ce mot-clé? Paramètre d'entrée? Pourquoi ce $ 0 utilisé pour? Si utilisé pour représenter le paramètre d'entrée, qu'en est-il de la ligne de la question "{(data, response, error) -> Void in". – user804417

+1

@ user804417, vous utilisez généralement la syntaxe de fermeture arrière si le dernier paramètre prend une fermeture. Le mot clé 'in' sépare les arguments du corps de fermeture. '$ 0' représente le premier paramètre. Si vous avez 3 paramètres, alors vous utiliserez '$ 0',' $ 1', et '$ 2'. – vacawama

+0

Merci beaucoup Monsieur! C'est limpide maintenant! – user804417

1

Une partie du bloc completion est appelée (exécutée) lorsque vous appelez cette fonction. L'appel de completion(rooms) exécutera le bloc d'achèvement où vous avez appelé cette fonction fetchAllRooms.

self.fetchAllRooms() { rooms in 
    //When you call completion(rooms) this block will be executed and you get [RemoteRoom] 
    in rooms instance 

    //do something with rooms instance here 
} 
+0

Merci Nirav pour votre réponse. Quand le bloc est appelé, je peux comprendre, mais où est le corps du bloc? (Bien que je ne sois pas très sûr que la fermeture fonctionne de la même manière que les blocs) – user804417

+1

@ user804417 Dans votre corps de terminaison de 'completion (rooms)' est {{rooms in} 'lorsque vous appelez la fonction' fetchAllRooms'. –

+0

Got it Nirav, Merci beaucoup. Une autre question que j'ai, – user804417

1

blocs Objective-C et les fermetures Swift sont la même chose, avec des noms différents et syntaxe légèrement différente, mais ils sont interchangeables.

En Objective-C, le système a une méthode de classe d'animation UIView animateWithDuration:animations:. Imaginez sa mise en œuvre:

@interface UIView 

+(void) animateWithDuration: (int) duration, animations: (void (^)(void)) animations { 
    //set up animation 
    animations(); 
    //finish animations 
} 

Où se trouve le corps du bloc d'animations?

Il est fourni par l'appelant. La ligne animations() appelle le bloc transmis à la méthode. La même chose est vraie avec la fonction fetch(). Il faut un bloc/fermeture, nommé completion. La fonction d'extraction utilise un dataTask asynchrone URLSession (NSURLSession dans Objective-C) pour télécharger des données et fournit un gestionnaire d'achèvement à la tâche de données.

Une fois la tâche de données terminée, le code du gestionnaire de complétion de la tâche de données s'exécute. Dans ce gestionnaire d'achèvement, la fonction fetch() appelle la fonction de gestionnaire d'achèvement qui lui est transmise. (Il y a 2 niveaux de gestionnaires de complétion en jeu ici.) C'est un modèle très courant pour utiliser les bibliothèques aysnc, à la fois dans Objective-C et Swift.

Swift a une syntaxe de "fermeture arrière" tout comme Objective-C. Dans les deux langues, si le dernier paramètre d'une fonction est un bloc/une fermeture, vous pouvez retirer le bloc-fermeture à l'extérieur des parenthèses, ignorer l'étiquette du paramètre et simplement fournir le bloc/la fermeture avec des accolades. En Objective-C vous devez préfixer le bloc avec cette hideuse ^ pour rendre le compilateur heureux, mais sinon les deux sont assez similaires.