重复的消息错误

时间:2016-07-14 01:11:44

标签: swift uitabbarcontroller jsqmessagesviewcontroller

我有一个包含标签栏控制器的消息传递应用程序,一个标签是我使用JSQMessagesViewController构建的消息传递视图。当我导航到另一个选项卡并返回到消息传递视图时,我的所有消息都在视图中重复。

此外,当用户发送消息时,它会发送同一消息的多个实例,这显然不是消息应用程序的最佳选择。

我尝试将messages.removeAll()放在我的observeMessages() viewDidAppear之前,就像这个post中建议的用户一样,并且它工作了几秒钟,但最终这使得我的应用崩溃并在控制台中显示以下消息:fatal error: Index out of range

这是我所说的ViewController的代码

class ChatViewController: JSQMessagesViewController, CLLocationManagerDelegate {

    // MARK: Properties

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

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

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

    //JSQMessages
    var messages = [JSQMessage]()

    var outgoingBubbleImageView: JSQMessagesBubbleImage!
    var incomingBubbleImageView: JSQMessagesBubbleImage!



    override func viewDidLoad() {
        super.viewDidLoad()

        self.edgesForExtendedLayout = .None

        locationManager.delegate = self
        locationManager.requestWhenInUseAuthorization()

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

        title = "Group Chat"
        setupBubbles()
        // No avatars
        collectionView!.collectionViewLayout.incomingAvatarViewSize = CGSizeZero
        collectionView!.collectionViewLayout.outgoingAvatarViewSize = CGSizeZero

        // Remove file upload icon
        self.inputToolbar.contentView.leftBarButtonItem = nil;

        messageRef = rootRef.child("messages")
        locationRef = rootRef.child("locations")
    }

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

        messages.removeAll()

        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 {
            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(
            UIColor.jsq_messageBubbleBlueColor())
        incomingBubbleImageView = factory.incomingMessagesBubbleImageWithColor(
            UIColor.jsq_messageBubbleLightGrayColor())
    }

    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.blackColor()
        }

        return cell
    }

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

        self.edgesForExtendedLayout = .None

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

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

        locRef.setValue(locItem)

        JSQSystemSoundPlayer.jsq_playMessageSentSound()

        finishSendingMessage()

    }

    private func observeMessages() {

        let messagesQuery = messageRef.queryLimitedToLast(25)

        messagesQuery.observeEventType(.ChildAdded) { (snapshot: FIRDataSnapshot!) in

            let id = snapshot.value!["senderId"] as! String
            let text = snapshot.value!["text"] as! String

            self.addMessage(id, text: text)

            self.finishReceivingMessage()
        }
    }


    override func textViewDidChange(textView: UITextView) {
        super.textViewDidChange(textView)
    }


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

        let message = messages[indexPath.item]

        // Call data I have retrieved below with message 
        let text = "From: " + 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
    }


}

3 个答案:

答案 0 :(得分:1)

SELECT * FROM Customers WHERE Name = @Name AND COALESCE(BillingAccount, 0) = COALESCE(@BillingAccount, BillingAccount, 0) AND COALESCE(ShippingAccount,0) = COALESCE(@ShippingAccount, ShippingAccount, 0) 移动observeMessages()并将其放入viewDidAppear()

在不同视图之间来回切换或者在 UITableViewController 之间切换时,保证它有效。

不完全确定为什么会这样,但我遇到了同样的问题并且设法解决了它,没有更多的重复泡泡!我认为这与 UICollectionViewCell 有关,但似乎是一个简单的修复。

请告诉我这是否适合您。

答案 1 :(得分:0)

在viewDidDisappear函数中调用removeAllObservers方法。

答案 2 :(得分:0)

我有(有)重复的邮件问题。 firebase数据库中的条目很好,没有重复项。 "观察孩子添加"函数正在生成重复项,即使firebase DB中只添加了一个子项。我检查了每个重复项的密钥,它们是相同的。所以,现在我只是检查一条消息是否与前一条消息具有相同的密钥,如果有,则将其过滤掉,现在情况正常 - 有点像" hack"但我无法得到任何其他工作。