2017-09-16 8 views
0

J'ai créé la fonction setAvatarImage pour télécharger un UIImage qui est ensuite retourné dans une fonction de vue de collection par défaut. Je peux voir dans la console que le UIImage est téléchargé, ainsi la valeur de retour devrait être le UIImage. Cependant, aucune image n'est affichée dans la vue de collection.Avoir un problème avec une valeur de retour en combinaison avec un gestionnaire d'achèvement

func setAvatarImages(_ senderUid: String!, completionhandler: @escaping (UIImage!) -> Void) { 

    let ref = DatabaseReference.users(uid: senderUid).reference() 
    ref.observe(.value, with: { (snapshot) in 
     let user = User(dictionary: snapshot.value as! [String : Any]) 
     user.downloadProfilePicture(completion: { (image, error) in 
      if image != nil { 
       let profileImage = image 
       print(profileImage!) 
       completionhandler(profileImage!) 
      } else if error != nil { 
       print(error?.localizedDescription ?? "") 
      } 
     }) 
    }) 
} 

override func collectionView(_ collectionView: JSQMessagesCollectionView!, avatarImageDataForItemAt indexPath: IndexPath!) -> JSQMessageAvatarImageDataSource! { 

    let message = messages[indexPath.item] 
    var avatarImage: JSQMessagesAvatarImage! 
    setAvatarImages(message.senderUID) { (profileImage) in 
     avatarImage = JSQMessagesAvatarImageFactory.avatarImage(with: profileImage, diameter: UInt(kJSQMessagesCollectionViewAvatarSizeDefault)) 
     print(avatarImage) 
    } 
    return avatarImage 
} 

Je pense qu'il y a un problème avec la fonction de retour asynchrone. Mais je pensais que donner à la fonction setAvatarImage un completionhandler devrait résoudre ce problème. Quelqu'un peut-il me donner quelques conseils, de sorte que l'image téléchargée est retournée !!

ÉDITER !!!

Prise en compte des suggestions d'Alex J'ai changé la fonction setAvatarImage. D'abord, je publié un dictionnaire:

var profileImages = [String : UIImage]() 

L'intention était d'obtenir toutes les images en profileImages avec le user.uid comme la clé dans le viewDidLoad.

func setAvatarImages() { 

    for user in chat.users { 
     print(user.fullName) 
     user.downloadProfilePicture(completion: { (image, error) in 
      print(image!) 
      if let profileImage = image { 
       self.profileImages[user.uid] = profileImage 
      } else if error != nil { 
       print(error?.localizedDescription ?? "") 
      } 
     }) 
    } 
} 

SetAvatarImages est appelé dans viewDidLoad.

Pour retourner la AvatarImage dans la fonction par défaut de la JSQMessagesViewController je l'ai fait:

override func collectionView(_ collectionView: JSQMessagesCollectionView!, avatarImageDataForItemAt indexPath: IndexPath!) -> JSQMessageAvatarImageDataSource! { 

    let message = messages[indexPath.item] 
    let avatarImage = JSQMessagesAvatarImageFactory.avatarImage(with: profileImages[message.senderUID], diameter: UInt(kJSQMessagesCollectionViewAvatarSizeDefault)) 
    return avatarImage 
} 

La chose cool est que cela a fonctionné, pour quelques essais. Mais soudainement, il se bloque lors du téléchargement de l'image dans la fonction user.downloadProfileImage. La seule chose que j'ai changé avant qu'il ne se bloque à chaque fois est que j'ai supprimé les points de rupture dans la console pour voir à quelle vitesse cela fonctionne ... Quelqu'un a-t-il une idée de la raison pour laquelle il se bloque maintenant? Et oui, je sais qu'il est préférable d'ajouter un peu de Caching pour les images, mais d'abord ce problème doit être résolu!

+0

Je n'utilise pas personnellement JSQMessages mais quand vous regardez leur projet sur Github, il semble que la syntaxe soit différente, alors vous pouvez jeter un oeil ici :). Aussi pour votre variable d'image je vous suggère de ne pas la mettre en majuscule car les noms en majuscules sont généralement pour les noms de classe et de structure et cela peut être déroutant quand quelqu'un lit votre code – Alex

+0

Ouais j'ai jeté un oeil, mais logique je ne peux pas voir un inconvénient dans le méthode que j'ai utilisée par rapport à leur code. La fonction downloadProfilePicture fonctionne assez bien pour le reste de l'application pour télécharger des photos rapidement. Mais merci pour votre réponse, je vais jeter un oeil à nouveau dans le projet d'exemple – AlexVilla147

+0

Hmm, je viens de remarquer, avez-vous essayé de mettre le retour avatarImage dans votre bloc d'achèvement setAvatarImages? Parce que votre bloc d'achèvement est appelé de manière asynchrone, il y a de fortes chances que la ligne "return avatarImage" soit appelée avant que votre bloc d'achèvement ne soit appelé. Et c'est peut-être le problème ici – Alex

Répondre

0

Enfin obtenu!

J'ai juste dû ajouter un gestionnaire de completion à la fonction setAvatarImages!

func setAvatarImages(completion: @escaping ([String : UIImage]) -> Void) { 

    for user in chat.users { 
     print(user.fullName) 
     user.downloadProfilePicture(completion: { (image, error) in 
      print(image!) 
      if let profileImage = image { 
       self.profileImages[user.uid] = profileImage 
       completion(self.profileImages) 
      } else if error != nil { 
       print(error?.localizedDescription ?? "") 
      } 
     }) 
    } 
} 

puis dans viewDidLoad

setAvatarImages(completion: { (profileUserImages) in 
     print(profileUserImages) 
    }) 

Suivant la mise en cache d'arrêt!