我的print语句显示该函数在大约15秒内被调用4771次,显然导致崩溃。
这是功能:
override func collectionView(_ collectionView: JSQMessagesCollectionView!, avatarImageDataForItemAt indexPath: IndexPath!) -> JSQMessageAvatarImageDataSource! {
count += 1
print("\n\nAvatar func called \(count)\n")
let databaseRef = FIRDatabase.database().reference()
let message = messages[indexPath.item]
let placeHolderImage = UIImage(named: "Logo")
let avatarImage = JSQMessagesAvatarImage(avatarImage: nil, highlightedImage: nil, placeholderImage: placeHolderImage)
if let messageID = message.senderId {
// Check cache for avatar
if imageCache.object(forKey: messageID as NSString) != nil {
DispatchQueue.main.async {
avatarImage!.avatarImage = imageCache.object(forKey: messageID as NSString)
avatarImage!.avatarHighlightedImage = imageCache.object(forKey: messageID as NSString)
self.collectionView.reloadData()
}
} else {
// If avatar isn't cached, fire off a new download
databaseRef.child("users").child(messageID).observe(.value, with: { (snapshot) in
if let profilePic = (snapshot.value as AnyObject!)!["profilePicture"] as! String! {
let profilePicURL: URL = URL(string: profilePic)!
Alamofire.request(profilePicURL)
.responseImage { response in
if let downloadedImage = response.result.value {
imageCache.setObject(downloadedImage, forKey: message.senderId as NSString)
DispatchQueue.main.async {
avatarImage!.avatarImage = imageCache.object(forKey: message.senderId as NSString)
avatarImage!.avatarHighlightedImage = imageCache.object(forKey: message.senderId as NSString)
self.collectionView.reloadData()
}
}
}
}
})
}
}
return avatarImage
}
导致循环的原因是什么?无论如何,只有一个用户(我)可以获得头像。我对编程有些新意,并试图找出如何使用缓存...我的意图是检查用户的头像是否被缓存,如果是,请使用它。如果没有,请从Firebase发布新的下载。但是我的表现非常糟糕 - 我如何写这个以便它有效地检查缓存和/或下载图像,并且不会卡在循环中?
答案 0 :(得分:1)
您正在函数中调用reloadData
,这将导致再次调用此函数,调用reloadData
等等;你创造了一个无限循环。
您只需要在最初返回占位符然后随后从网络中检索头像的情况下重新加载任何内容。在这种情况下,重新加载整个集合视图是非常浪费的;您只需重新加载受影响的项目:
override func collectionView(_ collectionView: JSQMessagesCollectionView!, avatarImageDataForItemAt indexPath: IndexPath!) -> JSQMessageAvatarImageDataSource! {
count += 1
print("\n\nAvatar func called \(count)\n")
let databaseRef = FIRDatabase.database().reference()
let message = messages[indexPath.item]
let placeHolderImage = UIImage(named: "Logo")
let avatarImage = JSQMessagesAvatarImage(avatarImage: nil, highlightedImage: nil, placeholderImage: placeHolderImage)
if let messageID = message.senderId {
// Check cache for avatar
if let cacheObject = imageCache.object(forKey: messageID as NSString) {
avatarImage!.avatarImage = cacheObject
avatarImage!.avatarHighlightedImage = cacheObject
} else {
// If avatar isn't cached, fire off a new download
databaseRef.child("users").child(messageID).observe(.value, with: { (snapshot) in
if let profilePic = (snapshot.value as AnyObject!)!["profilePicture"] as! String! {
let profilePicURL: URL = URL(string: profilePic)!
Alamofire.request(profilePicURL)
.responseImage { response in
if let downloadedImage = response.result.value {
imageCache.setObject(downloadedImage, forKey: message.senderId as NSString)
DispatchQueue.main.async {
self.collectionView.reloadItems(at:[indexPath])
}
}
}
}
})
}
}
return avatarImage
}