所以让我先说我对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/