"Cannot call value of non-function type"



我刚刚下载了Xcode 8 Beta,这样我就可以在我的应用程序中包含一些新的iOS 10框架。然而,在将代码从Swift 2转换为Swift 3的过程中,我遇到了几个错误。除了一个超级烦人的,我把所有的都修好了。

我得到错误:

无法调用非函数类型"JSQMessagesCollectionView!"的值在以下代码行:

let cell = super.collectionView(collectionView, cellForItemAtIndexPath: indexPath) as! JSQMessagesCollectionViewCell

以下是我的整个上下文函数:

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
}

有人有主意吗?

附言:如果这有帮助的话,这是我的整个代码块:

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")
    }
}

尝试将方法更改为:

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
}

如果您正确地编写了一个重写的方法,Swift会抱怨缺少override关键字。所以,如果在这个重写的方法上找不到任何警告或错误,那么很可能是滥用了方法签名。

并且许多UICollectionViewDataSource的方法被重命名,在Swift3中"cellForItemAtIndexPath"具有以下签名:

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell

因此,Swift找不到与collectionView(_:cellForItemAtIndexPath:)匹配的方法定义,因此假设collectionView会有一个属性。(不幸的是,它在JSQMessagesViewController中声明。)

您的类中可能存在这种不匹配的方法实现。最好全部检查一遍。

好的,这就是如何正确创建和重用单元格:

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

在您的情况下,您应该创建并返回JSQMessagesCollectionViewCell实例

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

相关内容

最新更新