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對象。