将返回值与完成处理程序结合使用
问题描述:
我创建了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函数中下载图像时突然崩溃。我在每次开始崩溃之前改变的唯一一件事是,我删除了控制台中的突破点以查看它的工作速度。有没有人知道它为什么现在崩溃了。 是的,我知道最好为图像添加一些缓存,但首先这个问题必须解决!
答
终于明白了!
我只需要添加一个完成处理程序到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)
})
下一站缓存!
我不亲自使用JSQMessages,但是当你看着他们在Github上的项目时,它的语法看起来不同,所以你可能想看看那里:)。同样对于你的图像变量,我建议你不要大写它,因为大写的名字通常是类和结构名称,当有人读你的代码时它可能会令人困惑 – Alex
是的,我看了一下,但逻辑上我看不出在我使用的方法与他们的代码相比。 downloadProfilePicture函数适用于其他应用程序快速下载图片火箭。但感谢您的回复,我会再次看看示例项目 – AlexVilla147
嗯,我刚刚注意到,您是否尝试将返回avatarImage放入setAvatarImages完成块中?因为你的完成块是异步调用的,所以在你完成块被调用之前,调用“return avatarImage”这一行就会被调用。这可能是问题 – Alex