Поток 1: EXC_BAD_INSTRUCTION при попытке написать сообщение JSQMessagesViewController

Смотрите эту картинку для ошибки

Когда я пытаюсь написать сообщение, происходит сбой. Я не могу найти ошибку здесь. я получаю Thread 1: EXC_BAD_INSTRUCTION (code=EXC)_1386_INVOP, subcode=0x0. Я пытаюсь найти в чем проблема в моей строке. Извините я просто новичок на xcode

Полный код ниже

import UIKit
import JSQMessagesViewController
import MobileCoreServices
import AVKit
import FirebaseDatabase

class ChatViewController: JSQMessagesViewController {
    var messages = [JSQMessage]()

    var messageRef = FIRDatabase.database().reference().child("messages")


    override func viewDidLoad() {
        super.viewDidLoad()

        self.senderId = "1"
        self.senderDisplayName = "Ej"
        //messageRef.childByAutoId().setValue("first message")
        //messageRef.childByAutoId().setValue("2nd")
//        messageRef.observeEventType(FIRDataEventType.Value) { (snapshot: FIRDataSnapshot) in
//            if let dick = snapshot.value as? NSDictionary {
//                print(dick)
//            }
//        }
        observeMessages()


    }

    func observeMessages(){

        messageRef.observeEventType(.ChildAdded, withBlock: { snapshot in
            //print(snapshot.value)

                if let dick = snapshot.value as? [String: AnyObject]{
                //let Mediatype = dick["Mediatype"] as! String
                let senderId = dick["senderId"] as! String
                let senderName = dick["senderName"] as! String
                let text = dick["text"] as! String  
                self.messages.append(JSQMessage(senderId: senderId, displayName: senderName, text: text))
                self.collectionView.reloadData()
            }
        })
    }

    //Send Btn
    override func didPressSendButton(button: UIButton!, withMessageText text: String!, senderId: String!, senderDisplayName: String!, date: NSDate!) {

    //Messages
        //messages.append(JSQMessage(senderId: senderId, displayName: senderDisplayName, text: text))
       //self.collectionView.reloadData()
//        print(messages)

        let newMessage = messageRef.childByAutoId()
        let messageData = ["text": text, "senderId": senderId, "senderName": senderDisplayName, "Mediatype": "TEXT"]
        newMessage.setValue(messageData)



    }
    //File btn
    override func didPressAccessoryButton(sender: UIButton!) {
        // ALERT WHEN PRESSED ACCESSORY
        let sheet = UIAlertController(title: "Media Messages", message: "Select A Media", preferredStyle: UIAlertControllerStyle.ActionSheet)
        let cancel = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel) { (alert:UIAlertAction) in

        }

        let photoLibrary = UIAlertAction(title: "Photo Library", style: UIAlertActionStyle.Default) { (alert: UIAlertAction) in
            self.getMediaFrom(kUTTypeImage)
        }

        let videoLibrary = UIAlertAction(title: "Video Library", style: UIAlertActionStyle.Default) { (alert: UIAlertAction) in
            self.getMediaFrom(kUTTypeMovie)


        }

        sheet.addAction(photoLibrary)
        sheet.addAction(videoLibrary)
        sheet.addAction(cancel)
        self.presentViewController(sheet, animated: true, completion: nil)



        //let imagePicker = UIImagePickerController()
        //imagePicker.delegate = self
        //self.presentViewController(imagePicker, animated: true, completion: nil)


        }

    func getMediaFrom(type: CFString) {
        print(type)
        let mediaPicker = UIImagePickerController()
        mediaPicker.delegate = self
        mediaPicker.mediaTypes = [type as String]
        self.presentViewController(mediaPicker, animated: true, completion: nil)



    }


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

    //BUBBLE CHAT
    override func collectionView(collectionView: JSQMessagesCollectionView!, messageBubbleImageDataForItemAtIndexPath indexPath: NSIndexPath!) -> JSQMessageBubbleImageDataSource! {
        let bubbleFactory = JSQMessagesBubbleImageFactory()
        return  bubbleFactory.outgoingMessagesBubbleImageWithColor(.lightGrayColor())
    }

    override func collectionView(collectionView: JSQMessagesCollectionView!, avatarImageDataForItemAtIndexPath indexPath: NSIndexPath!) -> JSQMessageAvatarImageDataSource! {
        return nil
    }





    override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        print("number of items  \(messages.count)")
        return messages.count
    }


    override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        let cell = super.collectionView(collectionView, cellForItemAtIndexPath: indexPath) as! JSQMessagesCollectionViewCell

        return cell
    }


   override func collectionView(collectionView: JSQMessagesCollectionView!, didTapMessageBubbleAtIndexPath indexPath: NSIndexPath!) {

        print("didTappedMessageBubbleAtIndexPath \(indexPath.item)")
        let message = messages[indexPath.item]
    if message.isMediaMessage {
        if let mediaitem = message.media as? JSQVideoMediaItem{
            let player = AVPlayer(URL: mediaitem.fileURL)
            let playerView = AVPlayerViewController()
            playerView.player = player

            self.presentViewController(playerView, animated: true, completion: nil)
        }

    }

    }



    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    @IBAction func LogOutTapped(sender: AnyObject) {
       print ("User Logged Out")
        //Goes on to Chat View




        //Main Stroryboard Interface
        _ = UIStoryboard(name: "Main", bundle: nil)



        //From MainStoryboard instatiate a navigation controller

        let LoginVC = storyboard?.instantiateViewControllerWithIdentifier("LoginVC") as! LogInViewController



        //Get app delegate

        let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate




        //Navigation Controller as root view controller

        appDelegate.window?.rootViewController = LoginVC


    }


}


extension ChatViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {

    func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
        print("finish picking")
        print(info)
        if let picture = info[UIImagePickerControllerOriginalImage] as? UIImage {
            let photo = JSQPhotoMediaItem(image: picture)
            messages.append(JSQMessage(senderId: senderId, displayName: senderDisplayName, media: photo))
        }else if let video = info[UIImagePickerControllerMediaURL] as? NSURL{
            let videoitem = JSQVideoMediaItem(fileURL: video, isReadyToPlay: true)
            messages.append(JSQMessage(senderId: senderId, displayName: senderDisplayName, media: videoitem))
        }

        self.dismissViewControllerAnimated(true, completion: nil)
        collectionView.reloadData()
    }



}

2 ответа

Ошибка говорит вам, что dick["text"] на самом деле неожиданный ноль.

Попробуйте сделать это:

let text = dick["text"] ?? ""

который должен заменить ноль пустой строкой.

Я хотел бы предложить вам посмотреть на guard заявление. Это утверждение, которое позволяет вам проверить значение необязательного "?" и если он равен nil, он обрабатывает эту ситуацию, потому что, если у вас нет всей необходимой информации IE сообщений, если в сообщениях нет текста, вы не хотите показывать это в разговоре. Это очень похоже на if let Заявление, которое вы уже сделали, но делает так, что вам не нужно вкладывать if let Внутри if let Поэтому я бы предложил изменить вашу логику на что-то более подобное.

messageRef.observeEventType(.ChildAdded, withBlock: { snapshot in
   guard let dick = snapshot.value as? [String: AnyObject] else { return } 
     // This will return if the snapshot cannot be mapped to the dictionary format [String: AnyObject]    
   guard let senderId = dick["senderId"] as! String, senderName = dick["senderName"] as! String, text = dick["text"] as! String else { return } 
     // This will return if the "dick" object does not contain all the elements necessary to create a JSQMessage
     // Otherwise we want to add it to our messages list   
            self.messages.append(JSQMessage(senderId: senderId, displayName: senderName, text: text))
            self.collectionView.reloadData()
        }

Теперь вы также можете посмотреть на эту логику. Ваш dick объект больше похож на общий объект сообщения. независимо от того, был ли "член" человеком, отправившим сообщение, или нет. Если вы не ссылаетесь на "член" конкретно через ваш путь к firebase, Судя по всему, эта линия var messageRef = FIRDatabase.database().reference().child("messages") Я предполагаю, что именно там вы храните все сообщения на вашем бэкэнде. Я, возможно, не полностью понимаю цель здесь, но я надеюсь, что это помогает. Дайте мне знать, если у вас есть дополнительные вопросы.

Другие вопросы по тегам