所以让我先说我对swift和obj-c编程还不熟悉,所以如果我问了一些愚蠢的问题,请原谅我,我正试图用jsqmessageviewcontroller库制作一个聊天应用程序,但是我一直得到这个错误:
***由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“-[jsqMessageCollectionViewFlowLayoutValidationContext invalidateFlowLayoutMessagesCache]:发送到实例的未识别的选择器
这是我的代码:

//
//  MessagesViewController.swift
//  ChatBiz
//
//  Created by Afnan Mirza on 6/3/16.
//  Copyright © 2016 Afnan Mirza. All rights reserved.
//


import UIKit
import Foundation
import JSQMessagesViewController
import Firebase

class MessagesViewController: JSQMessagesViewController {

    var user: FAuthData?

    var messages = [Message]()
    var avatars = Dictionary<String, UIImage>()

    var senderImageUrl: String!
    var batchMessages = true
    var ref: Firebase!
    var to = String()
    var username = NSUserDefaults.standardUserDefaults().stringForKey("username")!
    var sender = String()

let bubbles = JSQMessagesBubbleImageFactory()

    var outgoingBubbleImageView: JSQMessagesBubbleImage {
        return bubbles.outgoingMessagesBubbleImageWithColor(UIColor.jsq_messageBubbleLightGrayColor())
    }
    var incomingBubbleImageView: JSQMessagesBubbleImage {
        return bubbles.incomingMessagesBubbleImageWithColor(UIColor.jsq_messageBubbleGreenColor())
    }



    // *** STEP 1: STORE FIREBASE REFERENCES
    var messagesRef: Firebase!

    func setupFirebase() {
        // *** STEP 2: SETUP FIREBASE
        messagesRef = Firebase(url: "https://chatbiz.firebaseio.com/messages/\(username)")

        // *** STEP 4: RECEIVE MESSAGES FROM FIREBASE (limited to latest 25 messages)
        messagesRef.queryLimitedToNumberOfChildren(25).observeEventType(FEventType.ChildAdded, withBlock: { (snapshot) in
            let text = snapshot.value["message"] as? String
             self.sender = (snapshot.value["sender"] as? String)!
            let imageUrl = snapshot.value["imageUrl"] as? String

            let message = Message(text: text, sender: self.sender, imageUrl: imageUrl)
            self.messages.append(message)
            self.finishReceivingMessage()
        })
    }

    func sendMessage(text: String!, sender: String!) {
        // *** STEP 3: ADD A MESSAGE TO FIREBASE
        messagesRef.childByAutoId().setValue([
            "message":text,
            "sender":sender,
            "to":to,
            "imageUrl":senderImageUrl
            ])
    }

    func tempSendMessage(text: String!, sender: String!) {
        let message = Message(text: text, sender: sender, imageUrl: senderImageUrl)
        messages.append(message)
    }

    func setupAvatarImage(name: String, imageUrl: String?, incoming: Bool) {
        if let stringUrl = imageUrl {
            if let url = NSURL(string: stringUrl) {
                if let data = NSData(contentsOfURL: url) {
                    let image = UIImage(data: data)
                    let diameter = incoming ? UInt(collectionView.collectionViewLayout.incomingAvatarViewSize.width) : UInt(collectionView.collectionViewLayout.outgoingAvatarViewSize.width)
                    let avatarImage =  JSQMessagesAvatarImageFactory.avatarImageWithImage(image, diameter: diameter)
                   // avatars[name] = avatarImage
                    return
                }
            }
        }

        // At some point, we failed at getting the image (probably broken URL), so default to avatarColor
        setupAvatarColor(name, incoming: incoming)
    }

    func setupAvatarColor(name: String, incoming: Bool) {
        let diameter = incoming ? UInt(collectionView.collectionViewLayout.incomingAvatarViewSize.width) : UInt(collectionView.collectionViewLayout.outgoingAvatarViewSize.width)

        let rgbValue = name.hash
        let r = CGFloat(Float((rgbValue & 0xFF0000) >> 16)/255.0)
        let g = CGFloat(Float((rgbValue & 0xFF00) >> 8)/255.0)
        let b = CGFloat(Float(rgbValue & 0xFF)/255.0)
        let color = UIColor(red: r, green: g, blue: b, alpha: 0.5)

        let nameLength = name.characters.count
        let initials : String? = name.substringToIndex(sender.startIndex.advancedBy(min(3, nameLength)))
        let userImage = JSQMessagesAvatarImageFactory.avatarImageWithUserInitials(initials, backgroundColor: color, textColor: UIColor.blackColor(), font: UIFont.systemFontOfSize(CGFloat(13)), diameter: diameter)

      //  avatars[name] = userImage
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        print(to)
        inputToolbar.contentView.leftBarButtonItem = nil

        navigationController?.navigationBar.topItem?.title = "Logout"

        sender = (sender != "") ? sender : "Anonymous"
        let profileImageUrl = user?.providerData["cachedUserProfile"]?["profile_image_url_https"] as? NSString
        if let urlString = profileImageUrl {
            setupAvatarImage(sender, imageUrl: urlString as String, incoming: false)
            senderImageUrl = urlString as String
        } else {
            setupAvatarColor(sender, incoming: false)
            senderImageUrl = ""
        }

        setupFirebase()
    }

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

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

        if ref != nil {
            ref.unauth()
        }
    }

    // ACTIONS

    func receivedMessagePressed(sender: UIBarButtonItem) {
        // Simulate reciving message
        showTypingIndicator = !showTypingIndicator
        scrollToBottomAnimated(true)
    }

     func didPressSendButton(button: UIButton!, withMessageText text: String!, sender: String!, date: NSDate!) {
        JSQSystemSoundPlayer.jsq_playMessageSentSound()

        sendMessage(text, sender: sender)

        finishSendingMessage()
    }

    override func didPressAccessoryButton(sender: UIButton!) {
        print("Camera pressed!")
    }

    override func collectionView(collectionView: JSQMessagesCollectionView!, messageDataForItemAtIndexPath indexPath: NSIndexPath!) -> JSQMessageData! {
        return messages[indexPath.item] as! JSQMessageData
    }

     func collectionView(collectionView: JSQMessagesCollectionView!, bubbleImageViewForItemAtIndexPath indexPath: NSIndexPath!) -> UIImageView! {
        let message = messages[indexPath.item]

        if message.sender() == sender {
            return UIImageView(image: outgoingBubbleImageView.messageBubbleImage, highlightedImage: outgoingBubbleImageView.messageBubbleHighlightedImage)
        }

        return UIImageView(image: incomingBubbleImageView.messageBubbleImage, highlightedImage: incomingBubbleImageView.messageBubbleHighlightedImage)

    }

    func collectionView(collectionView: JSQMessagesCollectionView!, avatarImageViewForItemAtIndexPath indexPath: NSIndexPath!) -> UIImageView! {
        let message = messages[indexPath.item]
        if let avatar = avatars[message.sender()!] {
            return UIImageView(image: avatar)
        } else {
            setupAvatarImage(message.sender()!, imageUrl: message.imageUrl(), incoming: true)
            return UIImageView(image:avatars[message.sender()!])
        }
    }

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

    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.sender() == sender {
            cell.textView.textColor = UIColor.blackColor()
        } else {
            cell.textView.textColor = UIColor.whiteColor()
        }

        let attributes : [String:AnyObject] = [NSForegroundColorAttributeName:cell.textView.textColor!, NSUnderlineStyleAttributeName: 1]
        cell.textView.linkTextAttributes = attributes

        //        cell.textView.linkTextAttributes = [NSForegroundColorAttributeName: cell.textView.textColor,
        //            NSUnderlineStyleAttributeName: NSUnderlineStyle.StyleSingle]
        return cell
    }


    // View  usernames above bubbles
    override func collectionView(collectionView: JSQMessagesCollectionView!, attributedTextForMessageBubbleTopLabelAtIndexPath indexPath: NSIndexPath!) -> NSAttributedString! {
        let message = messages[indexPath.item];

        // Sent by me, skip
        if message.sender() == sender {
            return nil;
        }

        // Same as previous sender, skip
        if indexPath.item > 0 {
            let previousMessage = messages[indexPath.item - 1];
            if previousMessage.sender() == message.sender() {
                return nil;
            }
        }

        return NSAttributedString(string:message.sender())
    }

    override func collectionView(collectionView: JSQMessagesCollectionView!, layout collectionViewLayout: JSQMessagesCollectionViewFlowLayout!, heightForMessageBubbleTopLabelAtIndexPath indexPath: NSIndexPath!) -> CGFloat {
        let message = messages[indexPath.item]

        // Sent by me, skip
        if message.sender() == sender {
            return CGFloat(0.0);
        }

        // Same as previous sender, skip
        if indexPath.item > 0 {
            let previousMessage = messages[indexPath.item - 1];
            if previousMessage.sender() == message.sender() {
                return CGFloat(0.0);
            }
        }

        return kJSQMessagesCollectionViewCellLabelHeightDefault
    }
}

最佳答案

很抱歉回复太晚了,但您崩溃的原因是“springinessEnabled”仍在开发中,所以请尝试将其设置为false。

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)
    collectionView.collectionViewLayout.springinessEnabled = false // Changed to false
}

有关更多信息,请参见link

关于ios - 原因:'-[JSQMessagesCollectionViewFlowLayoutInvalidationContext invalidateFlowLayoutMessagesCache]:无法识别的选择器已发送到实例,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/37634367/

10-15 08:17