Is it possible to load an image from firebase using a url and then changing it's color to black and white?
If I used an image from assets it works but I'm loading my images from firebase via a url and when I try to apply the code below backgroundProfileImage.image equals nil or an Image is not detected. Im also using SDWebImage load my images if that helps. How can I make this work? I Appreciate the help in advance. Thanks
func ChangeImageColor(){
//Auto Adjustment to Input Image
var inputImage = CIImage(image: self.backgroundProfileImage.image!) //backgroundProfileImage is not
let options:[String : AnyObject] = [CIDetectorImageOrientation:1 as AnyObject]
let filters = inputImage!.autoAdjustmentFilters(options: options)
for filter: CIFilter in filters {
filter.setValue(inputImage, forKey: kCIInputImageKey)
inputImage = filter.outputImage
}
let cgImage = self.context.createCGImage(inputImage!, from: inputImage!.extent)
self.backgroundProfileImage.image = UIImage(cgImage: cgImage!)
//Apply noir Filter
let currentFilter = CIFilter(name: "CIPhotoEffectTonal")
currentFilter!.setValue(CIImage(image: UIImage(cgImage: cgImage!)), forKey: kCIInputImageKey)
let output = currentFilter!.outputImage
// let cgimg = self.context.createCGImage(output!, from: output!.extent)
let processedImage = UIImage(cgImage: cgimg)
self.backgroundProfileImage.image = processedImage
}
})
}
This is how I'm retrieving the image
self.backgroundProfileImage.sd_setImage(with: URL(string: backgroundProfileImageURL), placeholderImage: UIImage(named: "empty-profile-3.png"))
Ok this method works for me
func ChangeImageColor(){
let currentFilter = CIFilter(name: "CIPhotoEffectNoir")
currentFilter!.setValue(CIImage(image: self.backgroundProfileImage.image!), forKey: kCIInputImageKey)
let output = currentFilter!.outputImage
let cgimg = context.createCGImage(output!,from: output!.extent)
let processedImage = UIImage(cgImage: cgimg!)
self.backgroundProfileImage.image = processedImage
}
imgView.sd_setImage(with: URL(string:url), completed: { (image, error, type, url) in
//Do any thing with image here.
self.ChangeImageColor(image)
})
func ChangeImageColor(_ image: UIImage){
//Auto Adjustment to Input Image
var inputImage = CIImage(image: image)
let options:[String : AnyObject] = [CIDetectorImageOrientation:1 as AnyObject]
let filters = inputImage!.autoAdjustmentFilters(options: options)
for filter: CIFilter in filters {
filter.setValue(inputImage, forKey: kCIInputImageKey)
inputImage = filter.outputImage
}
let cgImage = self.context.createCGImage(inputImage!, from: inputImage!.extent)
self.backgroundProfileImage.image = UIImage(cgImage: cgImage!)
//Apply noir Filter
let currentFilter = CIFilter(name: "CIPhotoEffectTonal")
currentFilter!.setValue(CIImage(image: UIImage(cgImage: cgImage!)), forKey: kCIInputImageKey)
let output = currentFilter!.outputImage
// let cgimg = self.context.createCGImage(output!, from: output!.extent)
let processedImage = UIImage(cgImage: cgimg)
self.backgroundProfileImage.image = processedImage
}
})
}
Call the method when you retrieve the image with your library and pass it as parameter.
Related
I am having a problem with sorting data from firebase. The result of my code is completely unordered. I want to order it by the "date".
I have already tried with .queryOrderedBy(child: "date"), but I got the same issue.
Can someone helps me?
func getPosts(){
let ref = Database.database().reference()
ref.child("posts").queryOrderedByKey().observeSingleEvent(of: .value, with: { (snap) in
let postsSnap = snap.value as! [String : AnyObject]
for (_,post) in postsSnap {
let posst = Post()
if let author = post["author"] as? String, late date = post["date"], let postID = post["postID"] as? String, let userID = post["userID"] as? String {
posst.date = date
posst.author = author
posst.postID = postID
posst.userID = userID
self.posts.append(posst)
}
self.collectionview.reloadData()
}
})
}
My Firebase-Database structure looks like this:
{
"posts" : {
"Optional(\"-M2tKGSlfsUng8XfmnbV\")" : {
"author" : "Lilli",
"postID" : "-M2tKGSlfsUng8XfmnbV",
"date" : 1584731069721,
"userID" : "cayQLr27tsaJR76nH4H6yVUAOP03"
},
}
},
Just use following code
self.posts.sort(by: {$0.date > $1.date})
[code]
I need to take a snapshot of a collectionview cell for the provided indexpath, i have created the below function and it always returns image as nil
Please suggest me what am doing wrong here,
func screenshotForCellAtIndexPath(indexPath: IndexPath!, rect: CGRect!) -> UIImage?
{
let cellRect = rect
UIGraphicsBeginImageContextWithOptions(cellRect!.size, false, 0.0)
guard let context = UIGraphicsGetCurrentContext() else { return nil }
let cell = collectionView.cellForItem(at: indexPath)
cell?.layer.render(in: context)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image
}
[code]
Taking a snapshot of Collection view cell for selected indexpath.
Try this for taking snapshot of
var yourImage: UIImage?
UIGraphicsBeginImageContextWithOptions(yourView.bounds.size, false, UIScreen.main.scale)
yourView.drawHierarchy(in: myView.bounds, afterScreenUpdates: true)
yourImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return yourImage!
I have a collection view that displays a video in each cell. It also contains a play button and an image which is displayed before the video is played. When I scroll up and down it theres no problem, but when I play a video it shows in the right cell but sometimes it also displays in another cell when I scroll down. I've tried using DispatchQueue(not sure if its the right thing to do) and that doesn't work so I'm stuck for ideas. I have another similar collection view that shows just images and it works perfectly but I'm having issues with this collection view because it displays videos instead. I've searched other questions but I can't find the answer I need to solve this issue. Help would much appreciated. Thanks in advance!
Collection view controller
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: homePostCellId, for: indexPath) as! videoListCollectionViewCell
cell.photoImageView.sd_setImage(with: URL(string: posts[indexPath.item].imageUrl!), placeholderImage: UIImage(named: “placeholder-image.png"))
let tapGesture : UITapGestureRecognizer = UITapGestureRecognizer.init(target: self, action: #selector(playVideo))
return cell
}
}
collection view Cell
class videoListCollectionViewCell: UICollectionViewCell {
var post: videoPost?
lazy var playButton: UIButton = {
let button = UIButton(type: .system)
button.translatesAutoresizingMaskIntoConstraints = false
let image = UIImage(named: "playButton7")
button.tintColor = UIColor.white
button.setImage(image, for: UIControlState())
button.addTarget(self, action: #selector(handlePlay), for: .touchUpInside)
return button
}()
lazy var asset: AVURLAsset = {
let videoUrlString = self.post?.videoUrl
let url = URL(string: videoUrlString!)
var asset: AVURLAsset = AVURLAsset(url: url!)
asset.resourceLoader.setDelegate(self, queue: DispatchQueue.main)
return asset
}()
var playerLayer: AVPlayerLayer?
var player: AVPlayer?
var observer:Any!
func handlePlay() {
// The video has been download already to the document directory
let filename = self.post?.postID
let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
let url = NSURL(fileURLWithPath: path)
let filePath = url.appendingPathComponent(filename!)?.path
let fileManager = FileManager.default
let RealURL = NSURL(fileURLWithPath: filePath!)
if fileManager.fileExists(atPath: filePath!) {
player = AVPlayer(url: RealURL as URL)
playerLayer = AVPlayerLayer(player: player)
playerLayer?.frame = photoImageView.bounds
photoImageView.layer.addSublayer(playerLayer!)
player?.play()
playButton.isHidden = true
print("Playing from saved disk")
NotificationCenter.default.addObserver(self, selector:#selector(self.playerDidFinishPlaying(note:)),name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: player?.currentItem)
} else {
// The video hasn't been downloaded so it's loading from the URL
if let videoUrlString = post?.videoUrl, let url = URL(string: videoUrlString) {
player = AVPlayer(url: url)
playerLayer = AVPlayerLayer(player: player)
playerLayer?.frame = photoImageView.bounds
photoImageView.layer.addSublayer(playerLayer!)
player?.play()
activityIndicatorView.startAnimating()
playButton.isHidden = true
print("Attempting to play video")
self.observer = self.player?.addPeriodicTimeObserver(forInterval: CMTimeMake(1, 600), queue: DispatchQueue.main) {
[weak self] time in
if self?.player?.currentItem?.status == AVPlayerItemStatus.readyToPlay {
if (self?.player?.currentItem?.isPlaybackLikelyToKeepUp) != nil {
self?.activityIndicatorView.stopAnimating()
}
}
}
NotificationCenter.default.addObserver(self, selector:#selector(self.playerDidFinishPlaying(note:)),name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: player?.currentItem)
}
}
}
func playerDidFinishPlaying(note: NSNotification){
print("Video Stopped”)
self.player?.pause()
playButton.isHidden = false
let exporter = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetHighestQuality)
let filename = self.post?.postID
let documentsDirectory = FileManager.default.urls(for: FileManager.SearchPathDirectory.documentDirectory, in: FileManager.SearchPathDomainMask.userDomainMask).last!
let archiveURL = documentsDirectory.appendingPathComponent(filename!)
exporter?.outputURL = archiveURL
exporter?.outputFileType = AVFileTypeMPEG4
let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
let url = NSURL(fileURLWithPath: path)
let filePath = url.appendingPathComponent(filename!)?.path
let fileManager = FileManager.default
if fileManager.fileExists(atPath: filePath!) {
} else {
exporter?.exportAsynchronously(completionHandler: {
print(exporter?.status.rawValue)
print(exporter?.error)
})
}
}
App I've created is able to read data from firebase no problem. However, when I try to write data to it, doesn't seem to be working. I checked my rules to make sure ".write" was set to true, still not seeing anything pop up.
Trying to write an event to firebase as follows: ref?.child(email).child("events").setValue("Test")
Email variable has a value, though to double check it wasn't something weird with it I even tried substituting email for "test". Have no idea where else I could be going wrong, any help is a godsend!
Full code for reference:
//
// NewEventToCreateVC.swift
// WSUStudentEvents
//
// Created by Colin Warn on 7/31/17.
// Copyright © 2017 Colin Warn. All rights reserved.
//
import UIKit
import FirebaseDatabase
import Firebase
class NewEventToCreateVC: UIViewController {
var eventToCreate: UserEvent?
#IBOutlet weak var titleOutlet: UILabel!
#IBOutlet weak var startTimeOutlet: UILabel!
#IBOutlet weak var endTimeOutlet: UILabel!
#IBOutlet weak var eventTypeOutlet: UILabel!
#IBOutlet weak var locationOutlet: UILabel!
#IBOutlet weak var descriptionOutlet: UITextView!
#IBOutlet weak var passwordOutlet: UILabel!
let defaults = UserDefaults.standard
var ref: DatabaseReference?
override func viewDidLoad() {
super.viewDidLoad()
ref = DatabaseReference().database.reference()
let formatter = DateFormatter()
formatter.dateStyle = .short
formatter.timeStyle = .short
var startDateString = ""
var endDateString = ""
if let startTime = eventToCreate?.startTime, let endTime = eventToCreate?.endTime {
startDateString = formatter.string(from: startTime)
endDateString = formatter.string(from: endTime)
}
titleOutlet.text = eventToCreate?.eventName
startTimeOutlet.text = startDateString
endTimeOutlet.text = endDateString
eventTypeOutlet.text = eventToCreate?.eventType
locationOutlet.text = eventToCreate?.eventLocation
descriptionOutlet.text = eventToCreate?.description
if let password = eventToCreate?.password {
if password == "" {
passwordOutlet.text = "(no password)"
} else {
passwordOutlet.text = "Password: \(password)"
}
}
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewDidAppear(_ animated: Bool) {
print("EVENT TO CREATE, new VC data transfer check")
print(eventToCreate)
print(eventToCreate?.eventName)
}
#IBAction func addEventPressed(_ sender: Any) {
uploadDataToFirebase()
}
#IBAction func backBtnPressed(_ sender: Any) {
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let nextViewController = storyBoard.instantiateViewController(withIdentifier: "AddEventViewModelVC") as! AddEventViewModelVC
if let eventName = eventToCreate?.eventName {
nextViewController.eventName = eventName
}
if let eventLocation = eventToCreate?.eventLocation {
nextViewController.eventLocation = eventLocation
}
nextViewController.startTime = eventToCreate?.startTime
nextViewController.endTime = eventToCreate?.endTime
if let description = eventToCreate?.description {
nextViewController.eventDescription = description
}
if let password = eventToCreate?.password {
nextViewController.password = password
}
if let eventType = eventToCreate?.eventType
{
nextViewController.eventType = eventType
}
nextViewController.eventEnum = .password
self.present(nextViewController, animated:true, completion: {
nextViewController.titleLabel.text = nextViewController.eventEnum.rawValue
nextViewController.textField.text = self.eventToCreate?.password
})
}
func uploadDataToFirebase(){
let email = defaults.object(forKey: "email") as! String
print(email)
//Email->Events->Data
//Set Email
//Set events
ref?.child(email).child("events").setValue("Test")
}
}
Thank you so much in advance:
Breaking things down to minimal code can often help in troubleshooting. For example, try this
#class xxxx
var ref: DatabaseReference!
override func viewDidLoad() {
super.viewDidLoad()
ref = Database.database().reference()
ref.child("events").setValue("test")
}
Which will result in a Firebase like this
root_ref
events: "test"
It's also a good idea to include closures in your Firebase calls so you can catch any errors... so instead of setValue, you could use setValue with it's completion block (closure in swift)
let eventsRef = self.ref.child("events")
eventsRef.setValue("test", withCompletionBlock: { error in
if error != nil {
print(error)
}
})
I got some error when I send photo message.
I'm a beginner with swift language. I want to create undergraduate project about chat app. I need some help to fix this problem. Everything had worked smoothly till now but I am facing a small bug that is when I receive an image then it don't appears on the left side of the screen both incoming and outgoing images appear on the right side of the screen.
import UIKit
import JSQMessagesViewController
import MobileCoreServices
import AVKit
import FirebaseDatabase
import FirebaseStorage
import FirebaseAuth
import SDWebImage
class ChatViewController: JSQMessagesViewController {
var messages = [JSQMessage]()
var avatarDict = [String: JSQMessagesAvatarImage]()
var messageRef = FIRDatabase.database().reference().child("messages")
override func viewDidLoad() {
super.viewDidLoad()
if let currentUser = FIRAuth.auth()?.currentUser
{
self.senderId = currentUser.uid
if currentUser.isAnonymous == true
{
self.senderDisplayName = "anonymous"
} else
{
self.senderDisplayName = "\(currentUser.displayName!)"
}
}
observeMessages()
}
func observeUsers(_ id: String)
{
FIRDatabase.database().reference().child("users").child(id).observe(.value, with: {
snapshot in
if let dict = snapshot.value as? [String: AnyObject]
{
let avatarUrl = dict["profileUrl"] as! String
self.setupAvatar(avatarUrl, messageId: id)
}
})
}
func setupAvatar(_ url: String, messageId: String)
{
if url != "" {
let fileUrl = URL(string: url)
let data = try? Data(contentsOf: fileUrl!)
let image = UIImage(data: data!)
let userImg = JSQMessagesAvatarImageFactory.avatarImage(with: image, diameter: 30)
self.avatarDict[messageId] = userImg
self.collectionView.reloadData()
} else {
avatarDict[messageId] = JSQMessagesAvatarImageFactory.avatarImage(with: UIImage(named: "profileImage"), diameter: 30)
collectionView.reloadData()
}
}
func observeMessages() {
messageRef.observe(.childAdded, with: { snapshot in
// print(snapshot.value)
if let dict = snapshot.value as? [String: AnyObject] {
let mediaType = dict["MediaType"] as! String
let senderId = dict["senderId"] as! String
let senderName = dict["senderName"] as! String
self.observeUsers(senderId)
switch mediaType {
case "TEXT":
let text = dict["text"] as! String
self.messages.append(JSQMessage(senderId: senderId, displayName: senderName, text: text))
case "PHOTO":
let photo = JSQPhotoMediaItem(image: nil)
let fileUrl = dict["fileUrl"] as! String
let downloader = SDWebImageDownloader.shared()
downloader.downloadImage(with: URL(string: fileUrl)!, options: [], progress: nil, completed: { (image, data, error, finished) in
DispatchQueue.main.async(execute: {
photo?.image = image
self.collectionView.reloadData()
})
})
self.messages.append(JSQMessage(senderId: senderId, displayName: senderName, media: photo))
if self.senderId == senderId {
photo?.appliesMediaViewMaskAsOutgoing = true
} else {
photo?.appliesMediaViewMaskAsOutgoing = false
}
case "VIDEO":
let fileUrl = dict["fileUrl"] as! String
let video = URL(string: fileUrl)!
let videoItem = JSQVideoMediaItem(fileURL: video, isReadyToPlay: true)
self.messages.append(JSQMessage(senderId: senderId, displayName: senderName, media: videoItem))
if self.senderId == senderId {
videoItem?.appliesMediaViewMaskAsOutgoing = true
} else {
videoItem?.appliesMediaViewMaskAsOutgoing = false
}
default:
print("unknown data type")
}
self.collectionView.reloadData()
}
})
}
override func didPressSend(_ button: UIButton!, withMessageText text: String!, senderId: String!, senderDisplayName: String!, date: Date!) {
let newMessage = messageRef.childByAutoId()
let messageData = ["text": text, "senderId": senderId, "senderName": senderDisplayName, "MediaType": "TEXT"]
newMessage.setValue(messageData)
self.finishSendingMessage()
}
override func didPressAccessoryButton(_ sender: UIButton!) {
print("didPressAccessoryButton")
let sheet = UIAlertController(title: "Media Messages", message: "Please select a media", preferredStyle: UIAlertControllerStyle.actionSheet)
let cancel = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.cancel) { (alert:UIAlertAction) in
}
let photoLibrary = UIAlertAction(title: "Photo Library", style: UIAlertActionStyle.default) { (alert: UIAlertAction) in
self.getMediaFrom(kUTTypeImage)
}
let videoLibrary = UIAlertAction(title: "Video Library", style: UIAlertActionStyle.default) { (alert: UIAlertAction) in
self.getMediaFrom(kUTTypeMovie)
}
sheet.addAction(photoLibrary)
sheet.addAction(videoLibrary)
sheet.addAction(cancel)
self.present(sheet, animated: true, completion: nil)
}
func getMediaFrom(_ type: CFString) {
print(type)
let mediaPicker = UIImagePickerController()
mediaPicker.delegate = self
mediaPicker.mediaTypes = [type as String]
self.present(mediaPicker, animated: true, completion: nil)
}
override func collectionView(_ collectionView: JSQMessagesCollectionView!, messageDataForItemAt indexPath: IndexPath!) -> JSQMessageData! {
return messages[indexPath.item]
}
override func collectionView(_ collectionView: JSQMessagesCollectionView!, messageBubbleImageDataForItemAt indexPath: IndexPath!) -> JSQMessageBubbleImageDataSource! {
let message = messages[indexPath.item]
let bubbleFactory = JSQMessagesBubbleImageFactory()
if message.senderId == self.senderId {
return bubbleFactory!.outgoingMessagesBubbleImage(with: .black)
} else {
return bubbleFactory!.incomingMessagesBubbleImage(with: .blue)
}
}
override func collectionView(_ collectionView: JSQMessagesCollectionView!, avatarImageDataForItemAt indexPath: IndexPath!) -> JSQMessageAvatarImageDataSource! {
let message = messages[indexPath.item]
return avatarDict[message.senderId]
//return JSQMessagesAvatarImageFactory.avatarImageWithImage(UIImage(named: "profileImage"), diameter: 30)
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
print("number of item:\(messages.count)")
return messages.count
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = super.collectionView(collectionView, cellForItemAt: indexPath) as! JSQMessagesCollectionViewCell
return cell
}
override func collectionView(_ collectionView: JSQMessagesCollectionView!, didTapMessageBubbleAt indexPath: IndexPath!) {
print("didTapMessageBubbleAtIndexPath: \(indexPath.item)")
let message = messages[indexPath.item]
if message.isMediaMessage {
if let mediaItem = message.media as? JSQVideoMediaItem {
let player = AVPlayer(url: mediaItem.fileURL)
let playerViewController = AVPlayerViewController()
playerViewController.player = player
self.present(playerViewController, animated: true, completion: nil)
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func logoutDidTapped(_ sender: AnyObject) {
do {
try FIRAuth.auth()?.signOut()
} catch let error {
print(error)
}
// Create a main storyboard instance
let storyboard = UIStoryboard(name: "Main", bundle: nil)
// From main storyboard instantiate a View controller
let LogInVC = storyboard.instantiateViewController(withIdentifier: "LogInVC") as! LogInViewController
// Get the app delegate
let appDelegate = UIApplication.shared.delegate as! AppDelegate
// Set LogIn View Controller as root view controller
appDelegate.window?.rootViewController = LogInVC
}
func sendMedia(_ picture: UIImage?, video: URL?) {
print(picture)
print(FIRStorage.storage().reference())
if let picture = picture {
let filePath = "\(FIRAuth.auth()!.currentUser)/\(Date.timeIntervalSinceReferenceDate)"
print(filePath)
let data = UIImageJPEGRepresentation(picture, 0.1)
let metadata = FIRStorageMetadata()
metadata.contentType = "image/jpg"
FIRStorage.storage().reference().child(filePath).put(data!, metadata: metadata) { (metadata, error)
in
if error != nil {
print(error?.localizedDescription)
return
}
let fileUrl = metadata!.downloadURLs![0].absoluteString
let newMessage = self.messageRef.childByAutoId()
let messageData = ["fileUrl": fileUrl, "senderId": self.senderId, "senderName": self.senderDisplayName, "MediaType": "PHOTO"]
newMessage.setValue(messageData)
}
} else if let video = video {
let filePath = "\(FIRAuth.auth()!.currentUser)/\(Date.timeIntervalSinceReferenceDate)"
print(filePath)
let data = try? Data(contentsOf: video)
let metadata = FIRStorageMetadata()
metadata.contentType = "video/mp4"
FIRStorage.storage().reference().child(filePath).put(data!, metadata: metadata) { (metadata, error)
in
if error != nil {
print(error?.localizedDescription)
return
}
let fileUrl = metadata!.downloadURLs![0].absoluteString
let newMessage = self.messageRef.childByAutoId()
let messageData = ["fileUrl": fileUrl, "senderId": self.senderId, "senderName": self.senderDisplayName, "MediaType": "VIDEO"]
newMessage.setValue(messageData)
}
}
}
}
extension ChatViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
print("did finish picking")
// get the image
print(info)
if let picture = info[UIImagePickerControllerOriginalImage] as? UIImage {
sendMedia(picture, video: nil)
}
else if let video = info[UIImagePickerControllerMediaURL] as? URL {
sendMedia(nil, video: video)
}
self.dismiss(animated: true, completion: nil)
collectionView.reloadData()
}
}
You just need to understand what is going on in your code , as i am looking into your code you are reloading collectionview before the JSQPhotoMediaItem or JSQVideoMediaItem objects are completely configured and added these MediaItem into your message array, so make sure you have completely configured your JSQPhotoMediaItem and JSQVideoMediaItem objects and only after that you add these object to your message array.
you can add this into your switch case condition
case "PHOTO":
let photo = JSQPhotoMediaItem(image: nil)
let fileUrl = dict["fileUrl"] as! String
let downloader = SDWebImageDownloader.shared()
downloader.downloadImage(with: URL(string: fileUrl)!, options: [], progress: nil, completed: { (image, data, error, finished) in
DispatchQueue.main.async(execute: {
photo?.image = image // you have image in your media object
if self.senderId == senderId {
photo?.appliesMediaViewMaskAsOutgoing = true
} else {
photo?.appliesMediaViewMaskAsOutgoing = false
}
// you just configured media object by using appliesMediaViewMaskAsOutgoing
self.messages.append(JSQMessage(senderId: senderId, displayName: senderName, media: photo))
// successfully added object into your message array now you should reload collectionview
self.collectionView.reloadData()
})
})
//same goes for your video condition
But still i would recommend you to follow each step one by one.
Follow these steps for adding A JSQPhotoMediaItem object
make a JSQPhotoMediaItem Object like
let photoItem = JSQPhotoMediaItem(image: UIImage(named: <your Image Object>))
make sure you have downloaded your image from server and successfully have your image object ready to add in the JSQPhotoMediaItem Object (as you are downloading it from firebase) first get the image then add it to your JSQPhotoMediaItem
now you have to tell your message type( outgoing or incoming ) so add appliesMediaViewMaskAsOutgoing property to according to you need so this would be in your code
if self.senderId == senderId {
photoItem?.appliesMediaViewMaskAsOutgoing = true
} else {
photoItem?.appliesMediaViewMaskAsOutgoing = false
}
now this is the final step for appending this object to your array
self.messages.append(JSQMessage(senderId: senderId, displayName: senderName, media: photoItem))
now reload collectionView as you have successfully configured your media item ( JSQPhotoMediaItem )
self.collectionView.reloadData()
same goes for the JSQVideoMediaItem objects.