Swift - JSQMessagesViewController Swift
Swift - JSQMessagesViewController with Swift
我正在开发一个聊天应用程序,我在向 JSQMessagesViewController
显示头像时遇到问题
override func collectionView(collectionView: JSQMessagesCollectionView!, avatarImageDataForItemAtIndexPath indexPath: NSIndexPath!) -> JSQMessageAvatarImageDataSource! {
var avatar = UIImage()
let people = FIRDatabase.database().reference().child("people").child(senderId)
people.observeEventType(.Value, withBlock: {
snapshot -> Void in
let dict = snapshot.value as! Dictionary<String, AnyObject>
let imageUrl = dict["profileImage"] as! String
if imageUrl.hasPrefix("gs://") {
FIRStorage.storage().referenceForURL(imageUrl).dataWithMaxSize(INT64_MAX, completion: { (data, error) in
if let error = error {
print("Error downloading: \(error)")
return
}
avatar = UIImage.init(data: data!)!
})
}
})
let AvatarJobs = JSQMessagesAvatarImageFactory.avatarImageWithPlaceholder(avatar, diameter: UInt(kJSQMessagesCollectionViewAvatarSizeDefault))
return AvatarJobs
}
这里的问题是,当我试图从 firebase 中提取发件人的图像时,我得到的是一张空白图像,但是当我尝试使用这个 let AvatarJobs = JSQMessagesAvatarImageFactory.avatarImageWithPlaceholder(UIImage(named: "icon.png"), diameter: UInt(kJSQMessagesCollectionViewAvatarSizeDefault))
它工作正常,什么你认为问题出在这里吗?谢谢!
我可以推荐一个替代方案吗?为什么你没有字典:
var avatars = [String: JSQMessagesAvatarImage]()
let storage = FIRStorage.storage()
并使用以下函数:
override func collectionView(collectionView: JSQMessagesCollectionView!, avatarImageDataForItemAtIndexPath indexPath: NSIndexPath!) -> JSQMessageAvatarImageDataSource!
{
let message = messages[indexPath.row]
return avatars[message.senderId]
}
并在 viewDidLoad 中(或任何地方)创建头像
createAvatar(senderId, senderDisplayName: senderDisplayName, user: currentUser, color: UIColor.lightGrayColor())
有函数
func createAvatar(senderId: String, senderDisplayName: String, user: FBUser, color: UIColor)
{
if self.avatars[senderId] == nil
{
//as you can see, I use cache
let img = MyImageCache.sharedCache.objectForKey(senderId) as? UIImage
if img != nil
{
self.avatars[senderId] = JSQMessagesAvatarImageFactory.avatarImageWithImage(img, diameter: 30)
// print("from cache")
}
else if let photoUrl = user.pictureURL where user.pictureURL != ""
{
// the images are very small, so the following methods work just fine, no need for Alamofire here
if photoUrl.containsString("https://firebasestorage.googleapis.com")
{
self.storage.referenceForURL(photoUrl).dataWithMaxSize(1 * 1024 * 1024) { (data, error) -> Void in
if (error != nil)
{
//deal with error
}
else
{
let newImage = UIImage(data: data!)
self.avatars[senderId] = JSQMessagesAvatarImageFactory.avatarImageWithImage(newImage, diameter: 30)
MyImageCache.sharedCache.setObject(newImage!, forKey: senderId, cost: data!.length)
}
}
}
else if let data = NSData(contentsOfURL: NSURL(string:photoUrl)!)
{
let newImage = UIImage(data: data)!
self.avatars[senderId] = JSQMessagesAvatarImageFactory.avatarImageWithImage(newImage, diameter: 30)
MyImageCache.sharedCache.setObject(newImage, forKey: senderId, cost: data.length)
}
else
{
//etc. blank image or image with initials
}
}
}
else
{
//etc. blank image or image with initials
}
}
对于缓存我有一个自定义 class
import Foundation
class MyImageCache
{
static let sharedCache: NSCache =
{
let cache = NSCache()
cache.name = "MyImageCache"
cache.countLimit = 200 // Max 200 images in memory.
cache.totalCostLimit = 20*1024*1024 // Max 20MB used.
return cache
}()
}
如果有帮助请告诉我
我建议尝试隔离您的问题。我不知道问题是否出在 JSQMessagesAvatarImageFactory
我认为问题可能是您在需要显示单元格时没有下载图像。在您尝试将它设置为您的头像之前,我会确保您从 fireBase
得到一些东西。闭包通常是我这样做的方式
func getImageForUser(id: String, completiion() -> Void) {
//Add your logic for retrieving from firebase
let imageFromFirebase = firebaserReference.chiledWithID(id)
completion(image)
}
然后在你的
override func collectionView(collectionView: JSQMessagesCollectionView!, avatarImageDataForItemAtIndexPath indexPath: NSIndexPath!) -> JSQMessageAvatarImageDataSource! {
var avatarImage = JSQAavatarImage()
getImageForUser {
self.avatarImage = JSQMessagesAvatarImageFactory.avatarImageWithPlaceholder(imageFromFirebase, diameter: UInt(kJSQMessagesCollectionViewAvatarSizeDefault))
self.collectionView.reloadItemAtIndexPath(indexPath)
}
这样它会等到响应返回,然后在响应返回时重新加载单元格。
如果您有任何其他问题,请告诉我。
我正在开发一个聊天应用程序,我在向 JSQMessagesViewController
override func collectionView(collectionView: JSQMessagesCollectionView!, avatarImageDataForItemAtIndexPath indexPath: NSIndexPath!) -> JSQMessageAvatarImageDataSource! {
var avatar = UIImage()
let people = FIRDatabase.database().reference().child("people").child(senderId)
people.observeEventType(.Value, withBlock: {
snapshot -> Void in
let dict = snapshot.value as! Dictionary<String, AnyObject>
let imageUrl = dict["profileImage"] as! String
if imageUrl.hasPrefix("gs://") {
FIRStorage.storage().referenceForURL(imageUrl).dataWithMaxSize(INT64_MAX, completion: { (data, error) in
if let error = error {
print("Error downloading: \(error)")
return
}
avatar = UIImage.init(data: data!)!
})
}
})
let AvatarJobs = JSQMessagesAvatarImageFactory.avatarImageWithPlaceholder(avatar, diameter: UInt(kJSQMessagesCollectionViewAvatarSizeDefault))
return AvatarJobs
}
这里的问题是,当我试图从 firebase 中提取发件人的图像时,我得到的是一张空白图像,但是当我尝试使用这个 let AvatarJobs = JSQMessagesAvatarImageFactory.avatarImageWithPlaceholder(UIImage(named: "icon.png"), diameter: UInt(kJSQMessagesCollectionViewAvatarSizeDefault))
它工作正常,什么你认为问题出在这里吗?谢谢!
我可以推荐一个替代方案吗?为什么你没有字典:
var avatars = [String: JSQMessagesAvatarImage]()
let storage = FIRStorage.storage()
并使用以下函数:
override func collectionView(collectionView: JSQMessagesCollectionView!, avatarImageDataForItemAtIndexPath indexPath: NSIndexPath!) -> JSQMessageAvatarImageDataSource!
{
let message = messages[indexPath.row]
return avatars[message.senderId]
}
并在 viewDidLoad 中(或任何地方)创建头像
createAvatar(senderId, senderDisplayName: senderDisplayName, user: currentUser, color: UIColor.lightGrayColor())
有函数
func createAvatar(senderId: String, senderDisplayName: String, user: FBUser, color: UIColor)
{
if self.avatars[senderId] == nil
{
//as you can see, I use cache
let img = MyImageCache.sharedCache.objectForKey(senderId) as? UIImage
if img != nil
{
self.avatars[senderId] = JSQMessagesAvatarImageFactory.avatarImageWithImage(img, diameter: 30)
// print("from cache")
}
else if let photoUrl = user.pictureURL where user.pictureURL != ""
{
// the images are very small, so the following methods work just fine, no need for Alamofire here
if photoUrl.containsString("https://firebasestorage.googleapis.com")
{
self.storage.referenceForURL(photoUrl).dataWithMaxSize(1 * 1024 * 1024) { (data, error) -> Void in
if (error != nil)
{
//deal with error
}
else
{
let newImage = UIImage(data: data!)
self.avatars[senderId] = JSQMessagesAvatarImageFactory.avatarImageWithImage(newImage, diameter: 30)
MyImageCache.sharedCache.setObject(newImage!, forKey: senderId, cost: data!.length)
}
}
}
else if let data = NSData(contentsOfURL: NSURL(string:photoUrl)!)
{
let newImage = UIImage(data: data)!
self.avatars[senderId] = JSQMessagesAvatarImageFactory.avatarImageWithImage(newImage, diameter: 30)
MyImageCache.sharedCache.setObject(newImage, forKey: senderId, cost: data.length)
}
else
{
//etc. blank image or image with initials
}
}
}
else
{
//etc. blank image or image with initials
}
}
对于缓存我有一个自定义 class
import Foundation
class MyImageCache
{
static let sharedCache: NSCache =
{
let cache = NSCache()
cache.name = "MyImageCache"
cache.countLimit = 200 // Max 200 images in memory.
cache.totalCostLimit = 20*1024*1024 // Max 20MB used.
return cache
}()
}
如果有帮助请告诉我
我建议尝试隔离您的问题。我不知道问题是否出在 JSQMessagesAvatarImageFactory
我认为问题可能是您在需要显示单元格时没有下载图像。在您尝试将它设置为您的头像之前,我会确保您从 fireBase
得到一些东西。闭包通常是我这样做的方式
func getImageForUser(id: String, completiion() -> Void) {
//Add your logic for retrieving from firebase
let imageFromFirebase = firebaserReference.chiledWithID(id)
completion(image)
}
然后在你的
override func collectionView(collectionView: JSQMessagesCollectionView!, avatarImageDataForItemAtIndexPath indexPath: NSIndexPath!) -> JSQMessageAvatarImageDataSource! {
var avatarImage = JSQAavatarImage()
getImageForUser {
self.avatarImage = JSQMessagesAvatarImageFactory.avatarImageWithPlaceholder(imageFromFirebase, diameter: UInt(kJSQMessagesCollectionViewAvatarSizeDefault))
self.collectionView.reloadItemAtIndexPath(indexPath)
}
这样它会等到响应返回,然后在响应返回时重新加载单元格。
如果您有任何其他问题,请告诉我。