0

我发送照片信息时出现了一些错误。为什么传入的信息无法显示在屏幕的左侧?

enter image description here

我与迅速语言初学者。我想创建关于聊天应用程序的本科项目。我需要一些帮助来解决这个问题。一切都一直顺利到现在,但我面临一个小错误,即当我收到一个图像,然后它不会出现在屏幕的左侧,传入和传出的图像出现在屏幕的右侧。

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() 


} 
} 
+1

欢迎使用stackoverflow。这个问题还不清楚。 *一个小错误*意味着什么?什么错误?它发生了什么?而且,这对我们来说是完全太多的代码。代码应该是证明问题的最低要求。您应该包含Firebase结构的片段(作为文本),以便我们了解它的外观。请查看以下两个关于提问的指南:[我如何提出一个好问题?](https://stackoverflow.com/help/how-to-ask)和[如何创建一个最小,完整和可验证的示例](https://stackoverflow.com/help/mcve) – Jay

+0

谢谢你的建议。我会尽力解决这个问题。 –

回答

0

你只需要了解什么是在你的代码怎么回事,因为我期待到你的代码是重装collectionview完全配置和添加这些MediaItem到您的信息阵列之前的JSQPhotoMediaItemJSQVideoMediaItem对象,所以确保你已经完全配置了你的JSQPhotoMediaItemJSQVideoMediaItem对象,并且只有在你将这些对象添加到你的消息数组后。

您可以添加到这个交换机的情况下状态

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 

但我仍然会建议您按照每一个步骤一个接一个。

按照以下步骤添加JSQPhotoMediaItem对象

  1. 做出JSQPhotoMediaItem对象像

    let photoItem = JSQPhotoMediaItem(image: UIImage(named: <your Image Object>)) 
    

    确保你已经从服务器下载图像并成功有你的图像对象准备加入JSQPhotoMediaItem对象(当您从firebase下载时)首先获取图片,然后将其添加到您的图片JSQPhotoMediaItem

  2. 现在你要告诉你的消息类型(输出或输入),所以appliesMediaViewMaskAsOutgoing属性添加到根据需要那么这将是你的代码

     if self.senderId == senderId { 
          photoItem?.appliesMediaViewMaskAsOutgoing = true 
         } else { 
          photoItem?.appliesMediaViewMaskAsOutgoing = false 
         } 
    
  3. 现在这是追加该对象的最后一步您的阵列

    self.messages.append(JSQMessage(senderId: senderId, displayName: senderName, media: photoItem)) 
    
  4. 现在重装的CollectionView,你已经成功地配置您的媒体项目(JSQPhotoMediaItem

    self.collectionView.reloadData() 
    

这同样适用于JSQVideoMediaItem对象。