Ios 发送后JSQMessages为空

Ios 发送后JSQMessages为空,ios,swift,messages,jsqmessagesviewcontroller,Ios,Swift,Messages,Jsqmessagesviewcontroller,我试图在我的应用程序中实现JSQMesages,但是,我不明白为什么当我按下send按钮时,所有消息都消失了。我已经一步一步地走了,但我想不出来,当聊天开始时,一切都在那里。但是“发送”按钮会让它消失吗 有什么想法吗 // // JSQMessagesViewController.swift // ACSS // // Created by Trever on 10/21/15. // Copyright © 2015 trever.me. All rights reserved. //

我试图在我的应用程序中实现JSQMesages,但是,我不明白为什么当我按下send按钮时,所有消息都消失了。我已经一步一步地走了,但我想不出来,当聊天开始时,一切都在那里。但是“发送”按钮会让它消失吗

有什么想法吗

//
//  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")
    }

}

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

 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
不会更新,因为它位于主线程上。如果您有一个完成的观察者或闭包,然后在下载完所有内容后调用您的集合视图重新加载,它可能会解决您的问题


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

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

 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
不会更新,因为它位于主线程上。如果您有一个完成的观察者或闭包,然后在下载完所有内容后调用您的集合视图重新加载,它可能会解决您的问题


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

没有
导入JSQMessagesViewController时,它如何工作
没有
导入JSQMessagesViewController时,它如何工作
我遇到了类似的问题。视图控制器的初始加载加载一切正常。发布多条消息后(问题是间歇性的),视图将变为空白。每次发布消息时,都会在后台查询数据库,然后在主线程上更新消息数组,然后在主线程上调用reloadData()。是否有一种方法可以轻松地进一步调试此功能?您应该在哪里查找?您应该只有一个messages数组的本地实例,当您按下send按钮时,新消息将被追加。然后,如果您的post方法引发错误,请通知用户并允许他们重试。我也遇到了类似的问题。视图控制器的初始加载加载一切正常。发布多条消息后(问题是间歇性的),视图将变为空白。每次发布消息时,都会在后台查询数据库,然后在主线程上更新消息数组,然后在主线程上调用reloadData()。是否有一种方法可以轻松地进一步调试此功能?您应该在哪里查找?您应该只有一个messages数组的本地实例,当您按下send按钮时,新消息将被追加。然后,如果post方法引发错误,请通知用户并让他们能够重试。