Group Group Group Group Group Group Group Group Group
raywenderlich.com Forums

Firebase Tutorial: Real-time Chat

Learn how to quickly build a real-time chat-enabled iOS app, written in Swift, that looks and behaves just like Messages with this Firebase tutorial.


This is a companion discussion topic for the original entry at http://www.raywenderlich.com/122148/firebase-tutorial-real-time-chat
2 Likes

Hello,

Nice tutorial so far. I’ve built a one to one chat based on this tutorial with user authentication. The way I track a conversation between two users is I sort both their uid, then I truncate each one of them to take just 10 characters then I merge them.

I chose this approach because I can’t rely on the Id generated by with chilldByAutoId() method and I don’t want to store all these ids and write a lot of logic in order to know which conversation goes with which users.

The chat is working so far but I wonder if there isn’t a better way of doing this?

Thanks :slight_smile:

Hello,

Very nice tutorial, thanks a lot!

Just one question: how to get the back button? It seems to be masked…

Regards,

When I run the app after installing the pods like you mentioned, I get an error saying:

No such module ‘Firebase’

Is there a solution to this?

Thank you for providing such great tutorial,this helped me jumpstart my app.

But the same question as thomilecool^, how can I get the back button when I am at the chat view.

Hii
Interseting tutorial. I am expecting this kind of tutorial again. Please give some suggestion about my site.
Visit: Essay writing services

Awesome tutorial! One thing you might be able to add for those who are feeling extra adventurous is how to implement the didPressAccessoryButton method. As of now the app just crashes if you press that little paper clip. Could we bring up an ImagePickerController to send a photo? What if we wanted to send a GIF? Does the JSQ Messages View Controller support these things? Thanks!

Remove print(authData) in the ChatViewController.swift file to simulate and install the build on your iPhone.

While the ChatChat app builds on the XCode iPhone simulator successfully, there was an issue in the main thread while trying to run it on my iPhone to test out the messaging function on both the XCode simulator and the iOS device I was trying to test it on.

The above fix seems to solve it.

Hi There,

I am trying to do the same as you and build in a one to one messaging feature with my app.

I am also trying to gather UID’s to make sure the messages are going to the right two people. Is there any tutorials on this as I am a bit stuck. I think I’ll use the childbyautoid to create a key in a messages node. Within this key I was then going to have ‘to: uid ( of person message is going to)’, ‘message: content’, and then maybe a ‘from: sender’.

If you can help that would be great!

Thanks

Hello,

After I downloaded and run your real-time chat project, it gives errors for

in private func observeMessages() function

    let id = snapshot.value["senderId"] as! String
        let text = snapshot.value["text"] as! String

lines; after i click on login button.

On Script, on these lines it writes: Thread 1: EXC_BAD_INSTRUCTION(Code=Exc_I386_INVOP, subcode=0x0)

and down below n log: it writes fatal error: unexpectedly found nil while unwrapping an Optional value.

I only changed firebase urls and pressed build on iphoe 6s plus.

I have tried in 2 different mac but still having same problem.

Thank you very much for the help!

I think I get the tutorial bit late … you think you can upgrade to FirebaseDatabase (3.0.1)? because I have problems with observeMessages()
Thanks and regaras.

Hello,

I have followed everything step by step and when I first try to run it, I get an error.

Module ‘Firebase’ has no member named ‘defaultConfig’

How do I solve this problem?

Thanks.

Hi,

Here is completed project updated to Firebase 3.2.0 and FirebaseDatabase 3.0.1.

Thank you! excellent works, the only thing missing is me add the label name, because my app will have a group chat, try the following code that previously worked me but not anymore.

      override func collectionView(collectionView: JSQMessagesCollectionView!, attributedTextForMessageBubbleTopLabelAtIndexPath indexPath: NSIndexPath!) -> NSAttributedString! {
        let data = self.collectionView(self.collectionView, messageDataForItemAtIndexPath: indexPath)
        if (self.senderDisplayName == data.senderDisplayName()) {
            return nil
        }
        return NSAttributedString(string: data.senderDisplayName())
    }
    
    override func collectionView(collectionView: JSQMessagesCollectionView!, layout collectionViewLayout: JSQMessagesCollectionViewFlowLayout!, heightForMessageBubbleTopLabelAtIndexPath indexPath: NSIndexPath!) -> CGFloat {
        let data = self.collectionView(self.collectionView, messageDataForItemAtIndexPath: indexPath)
        if (self.senderDisplayName == data.senderDisplayName()) {
            return 0.0
        }
        return kJSQMessagesCollectionViewCellLabelHeightDefault
    }

Edit: I needed to add func displayName addMessage. Now if you show me the label of the sender.

Got this error when I tried to run it: Could not locate configuration file: ‘GoogleService-Info.plist’.

Sorry, I forgot to mention.
In order to run project, you should make some setup steps.

Create and setup project at Firebase Console.

Provide your own configuration file as described here https://firebase.google.com/docs/ios/setup#add_firebase_to_your_app

Enable Anonymous Authentication for you Firebase App.

Install pods.

Update following line in ChatViewController.swift with your own Firebase App URL.

let rootRef = FIRDatabase.database().referenceFromURL(“https://my-firebase-app.firebaseio.com/”)

And here we go.

Necessary steps to adapt to Firebase 3.2.0

Pods for ChatChat

pod ‘Firebase’
pod ‘Firebase/Database’
pod ‘Firebase/Auth’
pod ‘JSQMessagesViewController’
end

#LoginViewController:

import UIKit
import Firebase

class LoginViewController: UIViewController {

 var ref: FIRAuth!

 override func viewDidLoad() {
   super.viewDidLoad()
   ref = FIRAuth.auth()
 }

 @IBAction func loginDidTouch(sender: AnyObject) {
   ref.signInAnonymouslyWithCompletion { (user, error) in
     if error != nil { print(error!.description); return }
    
    print(self.ref.currentUser?.displayName) 
    
    self.performSegueWithIdentifier("LoginToChat", sender: self)
}

}

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    super.prepareForSegue(segue, sender: sender)
    let navigationViewController = segue.destinationViewController as! UINavigationController
    let chatViewController = navigationViewController.viewControllers.first as! ChatViewController
    chatViewController.senderId = "SomeUserId"
    chatViewController.senderDisplayName = "Some User"
}  

}

#ChatViewController:

let rootReference = FIRDatabase.database().referenceFromURL("https://sweltering-heat-3417.firebaseio.com")
var messageReference: FIRDatabaseReference!
messageReference = rootReference.child("messages")

snapshot becomes of type FIRDataSnapshot

There is a problem that I’m trying to solve: in FIRAuth docs the method signInAnonymouslyWithCompletion returns the currentUser instance. Yet when I call .displayName it returns nil.
This is why I hardcoded senderId property of chatViewController - it must not be nil.

Hope we’ll work it out, the tutorial is simple and excellent.

Hello, i am having the same issue. Did you ever get a solution to solve this issue?

Thanks in advance!

the FIRAuth method runs on a separate thread from the main thread so if your calling .displayName just after the completion block it may not be populated yet because the completion block has not finished loading yet. try putting a variable at class level that is optional and of the type of data you want to put in it. In this case, String. Inside the completion block set the variable to whatever you want to from the snapshot. Do this in viewdidLoad. Then in viewdidappear the variable should have the info you need and you can work with it from then on. The other option is a second closure that takes the FIRAuth completion as a parameter, ensuring that you have the results from the FIRAuth completion before the other closure begins.

Getting an error on the LoginViewController initial variable:

var ref: Firebase!

“Use of undeclared type ‘Firebase’”

any idea how this could be? 2 hours this has wasted already : /