简体   繁体   中英

“Cannot call value of non-function type”

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?

Ps 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.

Ok, this is how to create and reuse cell properly:

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCellWithReuseIdentifier("reuseId", forIndexPath: indexPath) as! UICollectionViewCell

    //update cell subviews here 
    return cell
}

In your case you should create and return JSQMessagesCollectionViewCell instance

let cell = collectionView.dequeueReusableCellWithReuseIdentifier("reuseId", forIndexPath: indexPath) as! JSQMessagesCollectionViewCell

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM