2016-08-01 71 views
1

我有一個使用JSQMessagesViewController框架構建的簡單消息應用程序。我一直在嘗試使用CoreLocation來收集用戶的位置,我想在實際的消息內容(attributedTextForCellBottomLabelAtIndexPath)下顯示該位置。我已經想通了所有這些,但問題是每個位置對於每條單獨的消息都必須是唯一的,並且這不起作用。顯示用戶位置

例如,如果用戶從西雅圖發送消息,它應該在他們的消息下面說「西雅圖」。如果另一個用戶向San Fransisco發送另一條消息,則應在他們的消息中說「San Fransisco」。

現在發生的事情是,所有的消息都說他們來自用戶當前所在的位置(假設他們在西雅圖)。所以如果另一個人在聖弗朗西斯科並不重要,那麼這個消息會顯示它來自西雅圖。

這是一個非常混亂的問題,但一個惱人的一個,我認爲應該有一個簡單的解決...

這裏是attributedTextForCellBottomLabelAtIndexPath代碼:

override func collectionView(collectionView: JSQMessagesCollectionView!, attributedTextForCellBottomLabelAtIndexPath indexPath: NSIndexPath!) -> NSAttributedString! { 

     let message = messages[indexPath.item] 

     // Call data I have retrieved below with message 
     let text = getLocation() 

     if message.senderId == senderId { 
      return nil 
     } else { 
      return NSAttributedString(string: text) 
     } 

    } 

注:我有一個函數getLocation(),簡單地返回用戶的城市/州/國

這裏是代碼爲其餘的th上下文E級ChatViewController

/* 
* Copyright (c) 2016 Ahad Sheriff 
*/ 

import UIKit 
import Firebase 
import JSQMessagesViewController 
import CoreLocation 

class ChatViewController: JSQMessagesViewController, CLLocationManagerDelegate { 

    // MARK: Properties 

    //Firebase 
    var rootRef = FIRDatabase.database().reference() 
    var messageRef: FIRDatabaseReference! 
    var locationRef: FIRDatabaseReference! 

    //JSQMessages 
    var messages = [JSQMessage]() 
    var outgoingBubbleImageView: JSQMessagesBubbleImage! 
    var incomingBubbleImageView: JSQMessagesBubbleImage! 

    //Location 
    var city: String = "" 
    var state: String = "" 
    var country: String = "" 
    var locationManager = CLLocationManager() 
    var locationId: String = "" 

    func getLocation() -> String { 
     if city == ("") && state == ("") && country == (""){ 
      return "Planet Earth" 
     } 
     else { 
      if country == ("United States") { 
       return self.city + ", " + self.state 
      } 
      else { 
       return self.city + ", " + self.state + ", " + self.country 
      } 
     } 
    } 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     // Initialize location 
     locationManager.delegate = self 
     locationManager.requestWhenInUseAuthorization() 

     if CLLocationManager.locationServicesEnabled() { 
      //collect user's location 
      locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers 
      locationManager.requestLocation() 
      locationManager.startUpdatingLocation() 
     } 

     title = "Chat" 
     setupBubbles() 
     // No avatars 

     // Remove file upload icon 
     self.inputToolbar.contentView.leftBarButtonItem = nil; 
     // Send button 
     self.inputToolbar.contentView.rightBarButtonItem.setTitle("Send", forState: UIControlState.Normal) 

     collectionView!.collectionViewLayout.incomingAvatarViewSize = CGSizeZero 
     collectionView!.collectionViewLayout.outgoingAvatarViewSize = CGSizeZero 

     //Firebase reference 
     messageRef = rootRef.child("messages") 
     locationRef = rootRef.child("locations") 

    } 

    override func viewDidAppear(animated: Bool) { 
     super.viewDidAppear(animated) 
     observeMessages() 
    } 

    override func viewDidDisappear(animated: Bool) { 
    super.viewDidDisappear(animated) 
    } 

    func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { 
     //--- CLGeocode to get address of current location ---// 
     CLGeocoder().reverseGeocodeLocation(manager.location!, completionHandler: {(placemarks, error)->Void in 

      if let pm = placemarks?.first 
      { 
       self.displayLocationInfo(pm) 
      } 

     }) 

    } 


    func displayLocationInfo(placemark: CLPlacemark?) 
    { 
     if let containsPlacemark = placemark 
     { 
      //stop updating location 
      locationManager.stopUpdatingLocation() 

      self.city = (containsPlacemark.locality != nil) ? containsPlacemark.locality! : "" 
      self.state = (containsPlacemark.administrativeArea != nil) ? containsPlacemark.administrativeArea! : "" 
      self.country = (containsPlacemark.country != nil) ? containsPlacemark.country! : "" 

      print(getLocation()) 

     } 

    } 


    func locationManager(manager: CLLocationManager, didFailWithError error: NSError) { 
     print("Error while updating location " + error.localizedDescription) 
    } 



    override func collectionView(collectionView: JSQMessagesCollectionView!, 
           messageDataForItemAtIndexPath indexPath: NSIndexPath!) -> JSQMessageData! { 
     return messages[indexPath.item] 
    } 

    override func collectionView(collectionView: JSQMessagesCollectionView!, 
           messageBubbleImageDataForItemAtIndexPath indexPath: NSIndexPath!) -> JSQMessageBubbleImageDataSource! { 
     let message = messages[indexPath.item] // 1 
     if message.senderId == senderId { // 2 
      return outgoingBubbleImageView 
     } else { // 3 
      return incomingBubbleImageView 
     } 
    } 

    override func collectionView(collectionView: UICollectionView, 
           numberOfItemsInSection section: Int) -> Int { 
     return messages.count 
    } 

    override func collectionView(collectionView: JSQMessagesCollectionView!, 
           avatarImageDataForItemAtIndexPath indexPath: NSIndexPath!) -> JSQMessageAvatarImageDataSource! { 
     return nil 
    } 

    private func setupBubbles() { 
     let factory = JSQMessagesBubbleImageFactory() 
     outgoingBubbleImageView = factory.outgoingMessagesBubbleImageWithColor(
      purp) 
     incomingBubbleImageView = factory.incomingMessagesBubbleImageWithColor(
      redish) 
    } 

    func addMessage(id: String, text: String) { 
     let message = JSQMessage(senderId: id, displayName: "", text: text) 
     messages.append(message) 
    } 

    override func collectionView(collectionView: UICollectionView, 
           cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell { 
     let cell = super.collectionView(collectionView, cellForItemAtIndexPath: indexPath) 
      as! JSQMessagesCollectionViewCell 

     let message = messages[indexPath.item] 

     if message.senderId == senderId { 
      cell.textView!.textColor = UIColor.whiteColor() 
     } else { 
      cell.textView!.textColor = UIColor.whiteColor() 
     } 

     return cell 
    } 

    override func didPressSendButton(button: UIButton!, withMessageText text: String!, senderId: String!, 
            senderDisplayName: String!, date: NSDate!) { 

     let itemRef = messageRef.childByAutoId() // 1 
     let messageItem = [ // 2 
      "text": text, 
      "senderId": senderId 
     ] 
     itemRef.setValue(messageItem) // 3 

     let locRef = locationRef.childByAutoId() 
     let locItem = [ 
      senderId : [ 
       "location": getLocation() 
      ] 
     ] 

     locRef.setValue(locItem) 

     // 4 
     JSQSystemSoundPlayer.jsq_playMessageSentSound() 

     // 5 
     finishSendingMessage() 

     Answers.logCustomEventWithName("Message sent", customAttributes: nil) 

    } 

    private func observeMessages() { 
     // 1 
     let messagesQuery = messageRef.queryLimitedToLast(25) 
     // 2 
     messagesQuery.observeEventType(.ChildAdded) { (snapshot: FIRDataSnapshot!) in 
      // 3 
      let id = snapshot.value!["senderId"] as! String 
      let text = snapshot.value!["text"] as! String 

      // 4 
      self.addMessage(id, text: text) 

      // 5 
      self.finishReceivingMessage() 

      Answers.logCustomEventWithName("Visited RoastChat", customAttributes: nil) 

     } 
    } 


    override func collectionView(collectionView: JSQMessagesCollectionView!, attributedTextForCellBottomLabelAtIndexPath indexPath: NSIndexPath!) -> NSAttributedString! { 

     let message = messages[indexPath.item] 

     // Call data I have retrieved below with message 
     let text = getLocation() 

     if message.senderId == senderId { 
      return nil 
     } else { 
      return NSAttributedString(string: text) 
     } 

    } 

    override func collectionView(collectionView: JSQMessagesCollectionView, layout collectionViewLayout: JSQMessagesCollectionViewFlowLayout, heightForCellBottomLabelAtIndexPath indexPath: NSIndexPath) -> CGFloat { 
     return kJSQMessagesCollectionViewCellLabelHeightDefault 
    } 

} 

注意:您也可以忽略我在哪裏保存用戶位置火力地堡的代碼。

感謝您提前提供任何幫助!如果您還有其他問題,請告訴我。

回答

2

你的問題是你正在設置客戶端的底部消息標籤而不是消息中的數據。因此,每個底部標籤由用戶設置而不是消息的發起者。

我不知道這是否成立,但基本上你是在本地獲取位置數據,所以如果你在西雅圖的Mark和不在西雅圖的Deric之間有對話。

EX.Conversation

馬克嗨

溫兆倫Wazzup

它總是會說西雅圖,因爲你是從本地客戶端獲取位置數據,並在此功能的設置它。

func getLocation() 

所以,當你從Mark甚至從‘溫兆倫’消息的電話要設置基於Mark位置數據的位置談話。

所以解決這個問題的方法是將位置數據保存到消息並將其存儲在firebase中。然後改變這個函數來爲你的底部標籤提取數據。沿着這些線路的東西。

override func collectionView(collectionView: JSQMessagesCollectionView!, attributedTextForCellBottomLabelAtIndexPath indexPath: NSIndexPath!) -> NSAttributedString! { 

let message = messages[indexPath.item] 

// Call data I have retrieved below with message 
let text = message.location <- Here is a suggested solution **** 

if message.senderId == senderId { 
    return nil 
} else { 
    return NSAttributedString(string: text) 
} 

}

我希望是明確的。我知道它是一個令人困惑的問題,幾乎同樣令人困惑。但基本上,您需要將位置保存到messageData,並將其發佈到您的後端firebase,然後顯示給定消息的位置。

我想你絕對是在正確的道路上錯過了那一塊。

編輯: 我將在這個 https://firebase.googleblog.com/2015/09/introducing-multi-location-updates-and_86.html

看一看,而是讓一切變得簡單,我只想解析位置數據並將其保存到上firebase消息對象,然後你不必處理它在您嘗試顯示消息時在客戶端。

+0

感謝您的回答!你有沒有關於如何保存數據/檢索數據的想法,因爲你對這樣做的語法有什麼瞭解嗎? –

+0

這將是該文件的firebase文檔。 –

+0

我來看看 –