I have just downloaded the Xcode 8 Beta so that I can include some of the new iOS 10 frameworks in my app. However, during the process of converting my code from Swift 2 to Swift 3, I ran into several errors. I fixed all but one super annoying one.
I am getting the error:
Cannot call value of non-function type 'JSQMessagesCollectionView!' at the following line of code:
let cell = super.collectionView(collectionView, cellForItemAtIndexPath: indexPath) as! JSQMessagesCollectionViewCell
Here is my entire function for context:
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell{
let cell = super.collectionView(collectionView, cellForItemAtIndexPath: indexPath) as! JSQMessagesCollectionViewCell
let message = messages[indexPath.item]
if message.senderId == senderId {
cell.textView!.textColor = UIColor.whiteColor()
} else {
cell.textView!.textColor = UIColor.blackColor()
}
return cell
}
Does anybody have an ideas?
P.s. If this helps, here is my entire block of code:
import UIKit
import Firebase
import JSQMessagesViewController
class ChatViewController: JSQMessagesViewController {
// MARK: Properties
var rootRef = FIRDatabase.database().reference()
var messageRef: FIRDatabaseReference!
var messages = [JSQMessage]()
var outgoingBubbleImageView: JSQMessagesBubbleImage!
var incomingBubbleImageView: JSQMessagesBubbleImage!
var userIsTypingRef: FIRDatabaseReference! // 1
private var localTyping = false // 2
var isTyping: Bool {
get {
return localTyping
}
set {
// 3
localTyping = newValue
userIsTypingRef.setValue(newValue)
}
}
var usersTypingQuery: FIRDatabaseQuery!
override func viewDidLoad() {
super.viewDidLoad()
// Change the navigation bar background color to blue.
// navigationController!.navigationBar.barTintColor = UIColor.init(red:252/255, green: 87/255, blue: 68/255, alpha: 1)
navigationController!.navigationBar.barTintColor = UIColor.init(red:250/255, green: 69/255, blue: 85/255, alpha: 1)
title = "RoastChat"
setupBubbles()
// No avatars
collectionView!.collectionViewLayout.incomingAvatarViewSize = CGSize.zero
collectionView!.collectionViewLayout.outgoingAvatarViewSize = CGSize.zero
// Remove file upload icon
self.inputToolbar.contentView.leftBarButtonItem = nil;
messageRef = rootRef.child("messages")
}
func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
observeMessages()
observeTyping()
}
func viewDidDisappear(animated: Bool) {
super.viewDidDisappear(animated)
}
func collectionView(collectionView: JSQMessagesCollectionView!,
messageDataForItemAtIndexPath indexPath: NSIndexPath!) -> JSQMessageData! {
return messages[indexPath.item]
}
func collectionView(collectionView: JSQMessagesCollectionView!,
messageBubbleImageDataForItemAtIndexPath indexPath: NSIndexPath!) -> JSQMessageBubbleImageDataSource! {
let message = messages[indexPath.item] // 1
if message.senderId == senderId { // 2
return outgoingBubbleImageView
} else { // 3
return incomingBubbleImageView
}
}
func collectionView(collectionView: UICollectionView,
numberOfItemsInSection section: Int) -> Int {
return messages.count
}
func collectionView(collectionView: JSQMessagesCollectionView!,
avatarImageDataForItemAtIndexPath indexPath: NSIndexPath!) -> JSQMessageAvatarImageDataSource! {
return nil
}
private func setupBubbles() {
let factory = JSQMessagesBubbleImageFactory()
outgoingBubbleImageView = factory?.outgoingMessagesBubbleImage(
// UIColor.init(red:250/255, green: 69/255, blue: 85/255, alpha: 1))
with: UIColor.init(red:47/255, green: 53/255, blue: 144/255, alpha: 1))
incomingBubbleImageView = factory?.incomingMessagesBubbleImage(
with: UIColor.jsq_messageBubbleLightGray())
}
func addMessage(id: String, text: String) {
let message = JSQMessage(senderId: id, displayName: "", text: text)
messages.append(message!)
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell{
let cell = super.collectionView(collectionView, cellForItemAtIndexPath: indexPath) as! JSQMessagesCollectionViewCell
let message = messages[indexPath.item]
if message.senderId == senderId {
cell.textView!.textColor = UIColor.whiteColor()
} else {
cell.textView!.textColor = UIColor.blackColor()
}
return cell
}
func didPressSendButton(button: UIButton!, withMessageText text: String!, senderId: String!,
senderDisplayName: String!, date: NSDate!) {
let itemRef = messageRef.childByAutoId() // 1
let messageItem = [ // 2
"text": text,
"senderId": senderId
]
itemRef.setValue(String(messageItem)) // 3
// 4
JSQSystemSoundPlayer.jsq_playMessageSentSound()
// 5
finishSendingMessage()
isTyping = false
}
private func observeMessages() {
// 1
let messagesQuery = messageRef.queryLimited(toLast: 25)
// 2
messagesQuery.observe(.childAdded) { (snapshot: FIRDataSnapshot!) in
// 3
let id = snapshot.value!["senderId"] as! String
let text = snapshot.value!["text"] as! String
// 4
self.addMessage(id: id, text: text)
// 5
self.finishReceivingMessage()
}
}
private func observeTyping() {
let typingIndicatorRef = rootRef.child("typingIndicator")
userIsTypingRef = typingIndicatorRef.child(senderId)
userIsTypingRef.onDisconnectRemoveValue()
// 1
usersTypingQuery = typingIndicatorRef.queryOrderedByValue().queryEqual(toValue: true)
// 2
usersTypingQuery.observe(.value) { (data: FIRDataSnapshot!) in
// 3 You're the only typing, don't show the indicator
if data.childrenCount == 1 && self.isTyping {
return
}
// 4 Are there others typing?
self.showTypingIndicator = data.childrenCount > 0
self.scrollToBottom(animated: true)
}
}
func textViewDidChange(textView: UITextView) {
super.textViewDidChange(textView)
// If the text is not empty, the user is typing
isTyping = textView.text != ""
}
func collectionView(collectionView: JSQMessagesCollectionView!, attributedTextForCellBottomLabelAtIndexPath indexPath: NSIndexPath!) -> AttributedString! {
return AttributedString(string:"test")
}
}
Try changing the method as:
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: NSIndexPath) -> UICollectionViewCell{
let cell = super.collectionView(collectionView, cellForItemAt: indexPath) as! JSQMessagesCollectionViewCell
let message = messages[indexPath.item]
if message.senderId == senderId {
cell.textView!.textColor = UIColor.whiteColor()
} else {
cell.textView!.textColor = UIColor.blackColor()
}
return cell
}
If you are writing an overridden method correctly, Swift complains about missing override
keyword. So, if you cannot find any warnings or errors on this overridden method, you are very likely misusing method signature.
And many UICollectionViewDataSource
s methods are renamed, in Swift3 "cellForItemAtIndexPath" has this signature:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
So, Swift cannot find a method definition matching collectionView(_:cellForItemAtIndexPath:)
, so assuming the collectionView
there would be a property. (Unfortunately, it is declared in JSQMessagesViewController
.)
You may have this sort of mismatching method implementations in your class. Better check them all.