将返回值与完成处理程序结合使用

将返回值与完成处理程序结合使用

问题描述:

我创建了setAvatarImage函数来下载一个UIImage,然后它将在默认集合视图函数中返回。我可以在控制台看到UIImage正在下载,因此返回值应该是UIImage。但是,收集视图中不显示图像。将返回值与完成处理程序结合使用

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 
} 

我觉得异步返回函数有问题。但我认为,给setAvatarImage函数一个完成处理程序应该可以解决这个问题。 任何人都可以给我一些建议,让下载的图像返回!

编辑!

考虑到Alex的建议我改变了setAvatarImage函数。 首先我创建了一个词典:

var profileImages = [String : UIImage]() 

其目的是让所有的图像转换成profileImages与user.uid作为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在viewDidLoad中被调用。

为了从JSQMessagesViewController我这样做,默认功能返回AvatarImage:

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 
} 

很酷的事情是,它的工作,对于一些尝试。但是,在user.downloadProfileImage函数中下载图像时突然崩溃。我在每次开始崩溃之前改变的唯一一件事是,我删除了控制台中的突破点以查看它的工作速度。有没有人知道它为什么现在崩溃了。 是的,我知道最好为图像添加一些缓存,但首先这个问题必须解决!

+0

我不亲自使用JSQMessages,但是当你看着他们在Github上的项目时,它的语法看起来不同,所以你可能想看看那里:)。同样对于你的图像变量,我建议你不要大写它,因为大写的名字通常是类和结构名称,当有人读你的代码时它可能会令人困惑 – Alex

+0

是的,我看了一下,但逻辑上我看不出在我使用的方法与他们的代码相比。 downloadProfilePicture函数适用于其他应用程序快速下载图片火箭。但感谢您的回复,我会再次看看示例项目 – AlexVilla147

+0

嗯,我刚刚注意到,您是否尝试将返回avatarImage放入setAvatarImages完成块中?因为你的完成块是异步调用的,所以在你完成块被调用之前,调用“return avatarImage”这一行就会被调用。这可能是问题 – Alex

终于明白了!

我只需要添加一个完成处理程序到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 ?? "") 
      } 
     }) 
    } 
} 

,然后在viewDidLoad中

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

下一站缓存!