草庐IT

ios - 已发送的消息在 JSQMessageViewController 中添加了两次

coder 2023-09-11 原文

我正在使用 JSQMessageviewcontroller 通过解析创建一个聊天客户端。除了“我发送的消息在 jsqmessage 数组中添加了两次”之外,我成功地实现了所有目标。 Althuogh 我已经检查过 JSQMessage 数组是否已经包含该消息,不应添加它,但在发送消息的情况下条件为 false。

这是我的代码:

import UIKit
import JSQMessagesViewController
import Parse

class MessageViewController: JSQMessagesViewController {

var chatWith : String?
var chattingWith = false
let incomingBubble = JSQMessagesBubbleImageFactory().incomingMessagesBubbleImageWithColor(UIColor(red: 10/255, green: 180/255, blue: 230/255, alpha: 1.0))
let outgoingBubble = JSQMessagesBubbleImageFactory().outgoingMessagesBubbleImageWithColor(UIColor.lightGrayColor())
var messages = [JSQMessage]()
var updateTimer = NSTimer()
let updateDelay = 2.0
var jsqMessages : [JSQMessage] = []

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    self.setup()

    updateTimer = NSTimer.scheduledTimerWithTimeInterval(updateDelay, target: self, selector: "update", userInfo: nil, repeats: true)

}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

override func viewDidDisappear(animated: Bool) {

    updateTimer.invalidate()

}
func reloadMessagesView() {
    self.collectionView?.reloadData()
 }
 }

//MARK - Setup
extension MessageViewController {


func setup() {
    self.senderId = PFUser.currentUser()?.objectId!
    self.senderDisplayName = PFUser.currentUser()?.username!

}
}

//MARK - Data Source
extension MessageViewController {

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

override func collectionView(collectionView: JSQMessagesCollectionView!, messageDataForItemAtIndexPath indexPath: NSIndexPath!) -> JSQMessageData! {
    let data = self.messages[indexPath.row]
    return data
}

override func collectionView(collectionView: JSQMessagesCollectionView!, didDeleteMessageAtIndexPath indexPath: NSIndexPath!) {
    self.messages.removeAtIndex(indexPath.row)
}

override func collectionView(collectionView: JSQMessagesCollectionView!, messageBubbleImageDataForItemAtIndexPath indexPath: NSIndexPath!) -> JSQMessageBubbleImageDataSource! {
    let data = messages[indexPath.row]
    switch(data.senderId) {
    case self.senderId:
        return self.outgoingBubble
    default:
        return self.incomingBubble
     }
}

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

//MARK - Toolbar
extension MessageViewController {
override func didPressSendButton(button: UIButton!, withMessageText text: String!, senderId: String!, senderDisplayName: String!, date: NSDate!) {
    let message = JSQMessage(senderId: PFUser.currentUser()?.objectId!, senderDisplayName: PFUser.currentUser()?.username!, date: date, text: text)
    print("sent messages = \(message)")
    if !self.messages.contains(message) {
       self.messages += [message]
    }

    self.sendMessageToParse(message , date: date)
    self.finishSendingMessage()
 }

override func didPressAccessoryButton(sender: UIButton!) {

}


}

//MARK - Syncano
extension MessageViewController {

func sendMessageToParse(message: JSQMessage , date : NSDate) {

    let obj = PFObject(className: "Chat")
    obj.setObject((PFUser.currentUser()?.username)!, forKey: "username")
    obj.setObject(message.text!, forKey: "Text")
    obj.setObject(chatWith!, forKey: "To")
    obj.setObject(PFUser.currentUser()!, forKey: "user")
    obj.setObject(date, forKey: "dateCreatedOn")
    try! obj.save()


 }

func update() {
    let query = PFQuery(className: "Chat")
    query.limit = 10
    query.includeKey("user")
//        query.whereKey("To", equalTo: chatWith!)
    query.findObjectsInBackgroundWithBlock {
        (results: [PFObject]?, error: NSError?) -> Void in

        for i in results! {

            if i.objectForKey("username") as? String == PFUser.currentUser()?.username! {

                let message = self.jsqMessageFromParseMessage(i, senderId: (PFUser.currentUser()?.objectId!)!, senderDisplayName: i.objectForKey("username")! as! String)
                print("received message : \(message)")
                self.jsqMessageArray(message)
            }else {

                let message = self.jsqMessageFromParseMessage(i, senderId: i.objectForKey("To")! as! String, senderDisplayName: i.objectForKey("To")! as! String)
                self.jsqMessageArray(message)
            }

        }


    }

 }



 func jsqMessageFromParseMessage(message: PFObject , senderId : String , senderDisplayName : String) -> JSQMessage {
    let jsqMessage = JSQMessage(senderId: senderId, senderDisplayName: senderDisplayName, date: message["dateCreatedOn"] as! NSDate, text: message["Text"] as! String)
    return jsqMessage
}

func jsqMessageArray(jsqmessage : JSQMessage){

    if self.messages.contains(jsqmessage) {

    }else {
        //
        self.messages.append(jsqmessage)
        self.finishReceivingMessage()
        self.reloadMessagesView()

    }

}
}

如果有人能提供帮助,将不胜感激。提前致谢。

最佳答案

有一个方法可以在 JSQMessageData 协议(protocol)上实现,叫做 messageHash。它返回一个 Int 并且它是每条消息的唯一 ID。您应该能够使用它来检查消息是否相同。

您需要创建一个遵守 JSQMessageData 协议(protocol)的对象数据类,而不是使用 JSQMessage

  class Message: JSQMessageData {

       func senderId()-> String {
          return //the result of currentUser()?.objectId
       }

      func senderDisplayName()-> String {
         return //the result of currentUser()?.username!
      }

      func date()-> NSDate {
         return // date
      }

      func isMediaMessage() -> Bool {
         return false
      }

      func messageHash()-> String {
         return //return a uniquely created id
      }

      func text()-> String {
         return // text
      }

  }

您应该可以在 PFUser 上执行此操作,尽管我对 Parse 不够熟悉,无法告诉您这是否可能,但您实际上只是将现有属性重新映射为新名称,所以不应该一个问题

关于ios - 已发送的消息在 JSQMessageViewController 中添加了两次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34448685/

有关ios - 已发送的消息在 JSQMessageViewController 中添加了两次的更多相关文章

  1. ruby-on-rails - 如何在 Rails View 上显示错误消息? - 2

    我是rails的新手,想在form字段上应用验证。myviewsnew.html.erb.....模拟.rbclassSimulation{:in=>1..25,:message=>'Therowmustbebetween1and25'}end模拟Controller.rbclassSimulationsController我想检查模型类中row字段的整数范围,如果不在范围内则返回错误信息。我可以检查上面代码的范围,但无法返回错误消息提前致谢 最佳答案 关键是您使用的是模型表单,一种显示ActiveRecord模型实例属性的表单。c

  2. ruby - 如何验证 IO.copy_stream 是否成功 - 2

    这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下

  3. Ruby 文件 IO 定界符? - 2

    我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的

  4. jquery - 我的 jquery AJAX POST 请求无需发送 Authenticity Token (Rails) - 2

    rails中是否有任何规定允许站点的所有AJAXPOST请求在没有authenticity_token的情况下通过?我有一个调用Controller方法的JqueryPOSTajax调用,但我没有在其中放置任何真实性代码,但调用成功。我的ApplicationController确实有'request_forgery_protection'并且我已经改变了config.action_controller.consider_all_requests_local在我的environments/development.rb中为false我还搜索了我的代码以确保我没有重载ajaxSend来发送

  5. ruby - 使用 Ruby 通过 Outlook 发送消息的最简单方法是什么? - 2

    我的工作要求我为某些测试自动生成电子邮件。我一直在四处寻找,但未能找到可以快速实现的合理解决方案。它需要在outlook而不是其他邮件服务器中,因为我们有一些奇怪的身份验证规则,我们需要保存草稿而不是仅仅发送邮件的选项。显然win32ole可以做到这一点,但我找不到任何相当简单的例子。 最佳答案 假设存储了Outlook凭据并且您设置为自动登录到Outlook,WIN32OLE可以很好地完成此操作:require'win32ole'outlook=WIN32OLE.new('Outlook.Application')message=

  6. Ruby - 如何将消息长度表示为 2 个二进制字节 - 2

    我正在使用Ruby,我正在与一个网络端点通信,该端点在发送消息本身之前需要格式化“header”。header中的第一个字段必须是消息长度,它被定义为网络字节顺序中的2二进制字节消息长度。比如我的消息长度是1024。如何将1024表示为二进制双字节? 最佳答案 Ruby(以及Perl和Python等)中字节整理的标准工具是pack和unpack。ruby的packisinArray.您的长度应该是两个字节长,并且按网络字节顺序排列,这听起来像是n格式说明符的工作:n|Integer|16-bitunsigned,network(bi

  7. Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting - 2

    1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里

  8. ruby-on-rails - 在 Flash 警报 Rails 3 中显示错误消息 - 2

    如果我在模型中设置验证消息validates:name,:presence=>{:message=>'Thenamecantbeblank.'}我如何让该消息显示在闪光警报中,这是我迄今为止尝试过的方法defcreate@message=Message.new(params[:message])if@message.valid?ContactMailer.send_mail(@message).deliverredirect_to(root_path,:notice=>"Thanksforyourmessage,Iwillbeintouchsoon")elseflash[:error]

  9. ruby-on-rails - Rake 任务仅调用一次时执行两次 - 2

    我写了一个非常简单的rake任务来尝试找到这个问题的根源。namespace:foodotaskbar::environmentdoputs'RUNNING'endend当在控制台中执行rakefoo:bar时,输出为:RUNNINGRUNNING当我执行任何rake任务时会发生这种情况。有没有人遇到过这样的事情?编辑上面的rake任务就是写在那个.rake文件中的所有内容。这是当前正在使用的Rakefile。requireFile.expand_path('../config/application',__FILE__)OurApp::Application.load_tasks这里

  10. ruby-on-rails - 在 RSpec 中,如何以任意顺序期望具有不同参数的多条消息? - 2

    RSpec似乎按顺序匹配方法接收的消息。我不确定如何使以下代码工作:allow(a).toreceive(:f)expect(a).toreceive(:f).with(2)a.f(1)a.f(2)a.f(3)我问的原因是a.f的一些调用是由我的代码的上层控制的,所以我不能对这些方法调用添加期望。 最佳答案 RSpecspy是测试这种情况的一种方式。要监视一个方法,用allowstub,除了方法名称之外没有任何约束,调用该方法,然后expect确切的方法调用。例如:allow(a).toreceive(:f)a.f(2)a.f(1)

随机推荐