显示用户位置

时间:2016-08-01 06:16:00

标签: swift core-location jsqmessagesviewcontroller

我有一个使用JSQMessagesViewController框架构建的简单消息传递应用程序。我一直在尝试使用CoreLocation来收集用户的位置,我想在实际的消息内容(attributedTextForCellBottomLabelAtIndexPath)下显示该位置。我已经想到了所有这些,但问题是每个位置都需要对每条消息都是唯一的,而且不起作用。

例如,如果用户从西雅图发送消息,则应在其消息下说“西雅图”。如果另一个用户向San Fransisco发送另一条消息,它应该在他们的消息下说“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()的函数,它只返回用户的城市/州/国家

以下是上下文的其余类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
    }

}

注意:您也可以忽略我将用户位置保存到Firebase的代码。

提前感谢您的帮助!如果您有任何其他问题,请与我们联系。

1 个答案:

答案 0 :(得分:2)

您的问题是您使用客户端设置底部消息标签而不是消息中的数据。因此,每个底部标签都由用户设置,而不是消息的发起者。

我不知道是否自那以后,但基本上你是在本地获取位置数据,所以如果你在西雅图的Mark与不在的Deric之间进行对话西雅图。

EX.Conversation

Mark Hi

Deric 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上的消息对象中。当您尝试显示时,您不必在客户端处理它消息。