2017-10-20 53 views
0

J'ai lu de nombreux articles sur les fonctions rapides avec des fermetures, des fermetures arrière et des fonctions d'échappement. Ils semblent tous donner des exemples suffisamment différents pour que je ne comprenne pas ce que je fais de mal dans ma propre fonction.Manipulateur de fin de course rapide - Fermeture de fuite

Mon principal problème est de savoir comment exécuter une fonction de fermeture arrière.

J'ai créé cette fonction pour télécharger une image dans Firebase. Il prend deux entrées et est supposé renvoyer une chaîne (imageURL). Je crois que cette fonction est ok.

func uploadImageToFirebaseAndReturnImageURL(directory: String, image: UIImage!, handler: @escaping(_ imageURL: (ImageURL)) ->()) { 
    let imageName = NSUUID().uuidString // create unique image name 

    if let uploadData = UIImagePNGRepresentation(image) { 
     DB_STORE.child(directory).putData(uploadData, metadata: nil, completion: { (metadata, error) in 

      if error != nil { 
       print(error) 
       return 
      } 

      if let profileImageUrl = metadata?.downloadURL()?.absoluteString { 
       let d = ImageURL(imageURL: profileImageUrl) 
       handler (d)    
      } 
      return 

     }) 
    } 
} 

Mon problème est de savoir comment exécuter cette fonction correctement quand il s'agit du gestionnaire. Je veux d'abord exécuter la fonction puis, une fois terminée, je veux obtenir imageURL et utiliser cette variable dans une autre fonction imbriquée qui télécharge cette variable (String) dans une base de données firebase.

uploadImageToFirebaseAndReturnImageURL(directory: "profileImage", image: selectedImageFromPicker!, handler: { imageURL in 
    guard let uid = Auth.auth().currentUser.uid else { print("User is not logged in"); return } 
    DataService.instance.updateUserWithProfileImageURL(uid: uid, imageURL: imageURL) 
    print("") 
} 

Qu'est-ce que je fais mal?

Répondre

0

Pour passer un trailing closure vous devez mettre fin/fermer votre appel de fonction et omettent l'étiquette argument de fermeture. Par exemple:

func foo(first: Int, second: Int, handler: (Int) -> Void) { 
    ... 
} 

syntaxe d'appel:

foo(first: 10, second: 20) { result in 
    /* trailing closure body */ 
} 

Par ailleurs, vous devriez simplement votre déclaration d'argument handler de:

handler: @escaping (_ imageURL: (ImageURL)) ->() 

à ceci:

handler: @escaping (ImageURL) -> Void 

En utilisant Void ou () est matière de style car ils sont logiquement les mêmes. Je préfère le précédent;)

+0

Est-ce que Void signifie simplement n'importe quel type de données? Donc ça peut être une chaîne? –

+0

Non, ce serait 'Any'. Le type 'Void' est juste un alias au tuple vide, c'est-à-dire'() '. –