1

我正在尝试在我的应用程序中实现 JSQMesages,但是,我无法弄清楚为什么当我按下发送按钮时所有消息都消失了。我一步一步走,无法弄清楚,当聊天最初加载时,一切都在那里。但是然后发送按钮做了什么让这一切都消失了?

有任何想法吗?

//
//  JSQMessagesViewController.swift
//  ACSS
//
//  Created by Trever on 10/21/15.
//  Copyright © 2015 trever.me. All rights reserved.
//

    import UIKit

    class MessagesViewController: JSQMessagesViewController {

    // Refresh Messages
    var timer : NSTimer!

    // Don't double load!
    var isLoading = false

    // ID for this chatroom. Can have mutliple users
    var chatroom = ""

    // Currently only set up for two people
    var currentUser : TradeUser?
    var otherUser : PFUser?

    //Value collection so don't double load too much
    var avatars = [String:JSQMessagesAvatarImage]()
    //Array of messages
    var messages = [JSQMessage]()

    //Collection of users
    var users = [String : PFObject]()

    // Chat bubbles for conversation
    var outgoingBubbleImageView : JSQMessagesBubbleImage!
    var incomingBubbleImageView : JSQMessagesBubbleImage!

    override func viewDidLoad() {
        super.viewDidLoad()

        // Create a chatroom for each pair. Same for both
        // Smaller ID first
        self.senderId = TradeUser.currentUser()?.objectId
        self.chatroom = currentUser!.objectId > otherUser!.objectId ?
            "\(currentUser!.objectId!)-\(otherUser!.objectId!)" :
        "\(otherUser!.objectId!)-\(currentUser!.objectId!)"

        //Setup chat bubbles
        let bubbleFactory = JSQMessagesBubbleImageFactory()
        outgoingBubbleImageView = bubbleFactory.outgoingMessagesBubbleImageWithColor(UIColor.jsq_messageBubbleLightGrayColor())
        incomingBubbleImageView = bubbleFactory.incomingMessagesBubbleImageWithColor(UIColor.jsq_messageBubbleBlueColor())

        //Loading...
        isLoading = false
        self.loadMessages()

        //Check for new messages every 5 seconds
        timer = NSTimer.scheduledTimerWithTimeInterval(5.0, target: self, selector: "loadMessages", userInfo: nil, repeats: true)

        self.senderDisplayName = "test"

    }

    override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(true)
        self.collectionView?.collectionViewLayout.springinessEnabled = true
    }

    override func viewWillDisappear(animated: Bool) {
        super.viewWillDisappear(animated)
        // when they leave this screen, stop checking for messages
        timer.invalidate()
    }

    func loadMessages() {
        if !isLoading {
            isLoading = true
            let message_last = messages.last

            //Fetch Messages
            let query = TradeChat.query()!
            query.whereKey("chatRoom", equalTo: chatroom)

            //Time Base Pagination
            if message_last != nil {
                query.whereKey("createdAt", greaterThan: message_last!.date)
            }

            // Get senders ID
            query.includeKey("sender")

            //Show Messages in order
            query.orderByAscending("createdAt")
            query.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in
                if error == nil {
                    for object in objects! {
                        // Go through each message and create a message for display
                        let tradeChat = object as! PFObject
                        let senderObject = tradeChat.objectForKey("sender") as! PFObject
                        let senderFirstName = senderObject.objectForKey("firstName") as! String
                        let createdAt = tradeChat.createdAt
                        let text = tradeChat.objectForKey("chatText") as! String

                        let message = JSQTextMessage(senderId: senderObject.objectId!, senderDisplayName: senderFirstName, date: createdAt, text: text)

                        self.messages.append(message)
                        print(self.messages.count)

                        //Chache the user object for later
                        self.users[senderObject.objectId!] = senderObject

                    }
                    if !objects!.isEmpty {
                        self.finishReceivingMessage()
                    }
                }
                self.isLoading = false
            })
        }
    }

    override func didPressSendButton(button: UIButton!, withMessageText text: String!, senderId: String!, senderDisplayName: String!, date: NSDate!) {
        // When they hit send. Save the message
        let tradeChat = TradeChat()
        tradeChat.chatRoom = chatroom
        tradeChat.sender = TradeUser.currentUser()!
        tradeChat.chatText = text

        tradeChat.saveInBackgroundWithBlock { (succeeded, error) -> Void in
            if error == nil {
                JSQSystemSoundPlayer.jsq_playMessageSentSound()
                self.loadMessages()
            }
        }

        self.finishSendingMessage()

    }

    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]

        if message.senderId == self.senderId {
            return outgoingBubbleImageView
        } else {
            return incomingBubbleImageView
        }
    }

    override func collectionView(collectionView: JSQMessagesCollectionView!, avatarImageDataForItemAtIndexPath indexPath: NSIndexPath!) -> JSQMessageAvatarImageDataSource! {
        let message = messages[indexPath.item]
        if self.avatars[message.senderId] == nil {
            var imageView = JSQMessagesAvatarImage(placeholder: UIImage(named: "profile"))
            self.avatars[message.senderId] = imageView

            let user = users[message.senderId]!
            print(user)
            var parseAvatar = PFFile()

            var imageQuery = TradeUser.query()!
            imageQuery.whereKey("objectId", equalTo: user.objectId!)
            imageQuery.limit = 1

            imageQuery.findObjectsInBackgroundWithBlock({ (images: [AnyObject]?, error: NSError?) -> Void in
                if imageQuery.countObjects() == 0 {
                    return
                } else {
                    for image in images! {
                        if image.objectForKey("profileImage") == nil {
                            return
                        } else {
                            let userPic = image.objectForKey("profileImage") as! PFFile
                            userPic.getDataInBackgroundWithBlock({ (imageData: NSData?, error: NSError?) -> Void in
                                if (error == nil) {
                                    let image = UIImage(data: imageData!)
                                    imageView.avatarImage = JSQMessagesAvatarImageFactory.circularAvatarImage(UIImage(data: imageData!), withDiameter: 30)
                                }
                            })
                        }

                    }
                }
            })

            // Reload entire table now that the avatar is downloaded
            self.collectionView?.reloadData()

        }

        return self.avatars[message.senderId]
    }

    override func collectionView(collectionView: JSQMessagesCollectionView!, attributedTextForMessageBubbleTopLabelAtIndexPath indexPath: NSIndexPath!) -> NSAttributedString! {
        // Show the name every once and a while
        let message = messages[indexPath.item]

        if message.senderId == self.senderId {
            return nil
        }

        if indexPath.item - 1 > 0 {
            let prevMessage = messages[indexPath.item - 1]
            if prevMessage.senderId == message.senderId {
                return nil
            }
        }

        let firstName = otherUser?.objectForKey("firstName") as! String

        return NSAttributedString(string: firstName)
    }

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

    override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        // Grab the cell were about to show
        let cell = super.collectionView(collectionView, cellForItemAtIndexPath: indexPath) as! JSQMessagesCollectionViewCell

        //Customize it some
        let message = messages[indexPath.item]
        if message.senderId == self.senderId {
            cell.textView?.textColor = UIColor.blackColor()
        } else {
            cell.textView?.textColor = UIColor.whiteColor()
        }

        return cell
    }

    override func collectionView(collectionView: JSQMessagesCollectionView!, layout collectionViewLayout: JSQMessagesCollectionViewFlowLayout!, heightForCellTopLabelAtIndexPath indexPath: NSIndexPath!) -> CGFloat {

        // If were going to show the date/time, give it some height
        if indexPath.item % 3 == 0 {
            return kJSQMessagesCollectionViewCellLabelHeightDefault
        }

        return 0.0

    }

    override func collectionView(collectionView: JSQMessagesCollectionView!, layout collectionViewLayout: JSQMessagesCollectionViewFlowLayout!, heightForMessageBubbleTopLabelAtIndexPath indexPath: NSIndexPath!) -> CGFloat {

        let message = messages[indexPath.item]
        if message.senderId == self.senderId {
            return 0.0
        }

        if indexPath.item - 1 > 0 {
            let previousMessage = messages[indexPath.item - 1]
            if previousMessage.senderId == message.senderId {
                return 0.0
            }
        }

        return kJSQMessagesCollectionViewCellLabelHeightDefault

    }

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

        // more height logic
        return 0.0
    }

    override func collectionView(collectionView: JSQMessagesCollectionView!, header headerView: JSQMessagesLoadEarlierHeaderView!, didTapLoadEarlierMessagesButton sender: UIButton!) {
        print("tapped load earlier messages - need implementation")
    }

}
4

1 回答 1

0

我认为您的问题在于您没有在本地保存对话的对话对象。因此,当您按send消息时,您正在发布要解析的消息,然后在后台线程中询问对话中的所有消息。

 query.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in
            if error == nil {
                for object in objects! {
                    // Go through each message and create a message for display
                    let tradeChat = object as! PFObject
                    let senderObject = tradeChat.objectForKey("sender") as! PFObject
                    let senderFirstName = senderObject.objectForKey("firstName") as! String
                    let createdAt = tradeChat.createdAt
                    let text = tradeChat.objectForKey("chatText") as! String

                    let message = JSQTextMessage(senderId: senderObject.objectId!, senderDisplayName: senderFirstName, date: createdAt, text: text)

                    self.messages.append(message)
                    print(self.messages.count)

                    //Chache the user object for later
                    self.users[senderObject.objectId!] = senderObject

                }
                if !objects!.isEmpty {
                    self.finishReceivingMessage()
                }
            }

由于这是在后台线程上,UI因此不会更新,因为它在主线程上。如果您有一个观察者或一个完成的闭包,然后在下载所有内容后调用您的集合视图以重新加载它可能会解决您的问题。

或者,您可以有一个对话对象,当您按下发送时,您将其添加到本地对话对象并将其发布到您的后端。然后在视图加载时,您只需从后端提取对话,将其保存到本地副本并从那里显示。UI如果消息发送失败并提示他们再次发送,您将有一个即时消息,并且您可以警告用户。

于 2016-02-18T20:30:35.107 回答