Chat - Messaging SDK for iOS

Fully featured customizable Objective-C framework to display and manage message based conversations - similar to Whats App or Messages. Quickly add text, picture and location based messaging functionality to your app. View Pricing
scroll down for more

Chat SDK Firebase

Chat SDK is light-weight and flexible providing an easy way to add instant messaging to your app.

Key Features

  • Free and open source under MIT license
  • Private messages
  • Text, Picture and location messages
  • Group / Public chat
  • User profile
  • Stand-alone or custom authentication
  • Social Login
  • Full source code provided
  • Easy to integrate with existing apps
  • Native Android version available
  • Fully inter-compatible with Chat SDK Android
  • 2-week money back guarantee
  • Supports over 100k daily active users
  • Location-based version available
  • Swift compatibledemo project included
  • Extra features (see pricing below):
    1. Two factor authentication
    2. Video / audio messages
    3. Read receipts
    4. Integration and setup service
    5. Location based chat
    6. Add contacts from phonebook

Chat SDK is designed to be as simple and flexible as possible. It functions as a stand-alone app or it can be integrated with your project using CocoaPods. You can test the app out using our live demo on the App Store.


The XMPP Chat SDK is a fully featured, white label XMPP client for iOS. It provides a standard compliant mobile XMPP client out of the box.

This product is ideal for developers who want to add XMPP based instant messaging to their apps. It’s also great for companies who already have an XMPP server and want to allow their employees to be able to communicate while using their mobile devices. When you buy a license, you get access to the complete source code in the form of an Xcode project. Once you’ve set the IP address and name of your XMPP server, you can be testing the messenger in minutes. With full access to the source code, it’s easy to integrate Chat SDK with your existing application or to change the branding and release it as a stand-alone app.

  • Standard XMPP implementation for iOS - compatible with third party XMPP messengers
  • Supports eJabberd
  • 1-to-1 and multi-party chats
  • Full vCard support
  • User search
  • Typing indicator
  • Last online
  • Presence
  • Roster integration
  • User status

A full list of features is availble here.

Hosting and Performance

The Chat SDK uses Firebase, a Google owned real-time database, to handle message delivery. Firebase is reliable, fast and cost effective. For most of our customers, the free tier provides more than enough capacity.

  • 20,000 Daily Users - Approximate number of users supported by free hosting tier
  • Chat SDK also scales well. We have clients who are using the Chat SDK with over 100,000 daily active users

Successful projects

Chat SDK is already used on hundreds of successful apps. Here are some of our most successful implementations:

Parlor - Audio social network

  • Over 100k Daily active users
  • Cross platform - iOS and Android
  • Full integration with existing authentication system

Tapatalk - Forum agrigator

  • Over 5m installs 
  • Chat SDK is used to handle private messaging
  • 3k concurrent users
  • Messaging system fully re-skinned

86 Serving - Restaurant staff communication tool

  • Communication tool for restaurant staff
  • Cross platform (iOS and Android)

Comments from our customers

"As for the code itself, it's as smooth as butter over hot fluffy pancakes. It opens up in Xcode 5.1 with zero Issues and compiles to iOS 7.1 with no errors or warnings." Greg Storm

"The code is clean, powerfull and well shaped.  It is a real pleasure to read and modify it." Zeno Pokossy

"If you are thinking about making this purchase then just do it. It is so worth the money for reasons you can't yet factor in. I'm the founder of an app with millions of downloads and built a complete messaging platform from the ground up in-house. Instead of using that we are using Chat SDK + Firebase and Parse Push." Joel Schwartz


The Licenses

Chat SDK is free and open source under the MIT license.

We also offer a full range of consulting services from a basic service to configure the Chat SDK to a full app integration service.

Here's a list of the common services we offer and the prices:

  • Chat SDK setup - $360
  • Typing Indicator - $49
  • Audio messages - $99
  • Video messages - $99
  • Audio and video message - $149
  • Location based chat - list of nearby users - $149
  • Add contacts from phone book - $149
  • Two factor authentication
    • iOS and custom PHP server license - $199
    • Setup (optional): $99
    • Hosting and support (optional): $19 per month 
  • Read receipts: $149
  • Integration with existing app from $480.

Use the "Get a quote" button for details. 

The user interface

Chat SDK Screenshot 1


The SDK provides a clean simple interface that completely decouples the creation of display of messages and thread form the way they're transmitted and received over the network. The user inteface is made from flexible components that can be mixed and matched in your project.

  • Login screen
  • Compose message token view
  • Thread list view
  • User profile view
  • Message list view
  • Expanding text input box
  • Keyboard animates up and down smoothly
  • Message copy / paste
  • iOS 7+

The back-end

Chat SDK is powered by Firebase, Google's excellent real-time database. Firebase provides powerful, secure websocket implementation to deliver data in real time. Firebase frees you from the worry and complexity of running and maintaining your own server and allows you to concentrate on what's really important, developing your product.

  • Facebook, Email, Twitter and Anoymous
  • Multiple user accounts on one device
  • Cloud message storage
  • Push notifications
  • Powerful search API
  • Add custom meta data to users' profiles
  • Lazy loading of messages
  • Scalability - the app has been tested with over 100k daily users
  • Low cost - most apps will never pay for Firebase hosting

Audio and Video Messaging

Since the first release of ChatSDK users have been asking us when the chat will support Audio and Video messages. Well today is the day! We are very excited to say that the latest version of ChatSDK is compatible with Video and Audio messages.

Audio Messages:

Hold to record snippets of audio and send them to your friends. The simple and slick design allows you to pause and play messages as well as showing you the length and time remaining for the audio.

Video Message:

Send and play video messages right from your chat window. Film from your phone or choose an existing video and send it to your friends. Then click the message to play it right then and there.

We understand that users of ChatSDK value the ability to customise the chat to their specific need. We believe that you should be able to choose what you want and what you don't. No one wants to pay for functions they won't be using!

For this reason instead of increasing the price of the ChatSDK we're selling Audio and Video messages separately meaning you can customise the chat based on exactly what you need.

Buy either Audio of Video for only $99 or get both at once for only $149!!! Want to know more? Then hit the "Get a quote" button and we can send you the modules to enable audio and video in your apps.

Related products

Along side the chat SDK we also offer two other versions:



14 day 14-day money-back guarantee


MIT license

The MIT license is an open-source license.

Need custom services for this product? Get a quote

Setup / Installation

Chat SDK - Core

This project comes as a fully functional app which you can compile straight away in Xcode. If you're just buying a license to the front end, the app is setup using the BBlankNetworkAdapter. This adapter conforms to all the necessary protocols and can be used as a starting point to interface the app to your network.

Chat SDK - Firebase

There are two ways to get started using ChatSDK. You can either start customizing the fully configured example project or you can add ChatSDK to an existing project as a dependency. In this documentation we will first look at how to add ChatSDK to your existing project and then we'll look at configuring ChatSDK with your Backendless and Firebase account details.

NOTE: ChatSDK comes as a fully functional project based on our test accounts. It is advised to use this documentation to configure the project to your own accounts.

Using the test ChatSDK project

To test out the code in the set up test project just complete the following steps:

  1. Download the project file from Binpress and unzip it
  2. Call pod install on the project folder - if you do not have Cocoapods installed then consult the instructions below
  3. Open and run the .xcworkspace file

Adding ChatSDK to an existing project

You can easily enable instant messaging for your app in only a few minutes by adding the ChatSDK to your existing project:

  1. Download the project file from Binpress and unzip it
  2. Add the development folders to the folder containing your existing project: ChatCore, ChatCoreData, ChatFirebaseAdapter and ChatUI. In the example below we are adding it to our test project called "Chat SDK Firebase"

  3. Now we link the component parts of ChatSDK with your project using Cocoapods. Each of the folders we have added is a development pod - this means when Cocoapods runs it will add the needed files for each component to the Xcode project and create a simlink to the directory containing the original version of the code. More details on development pods can be found here.

If you are not already using Cocoapods then it is recommended to set it up to use with this project. If you are then skip the next section to continue the project setup.

Installing Cocoapods

You must have Cocoapods set up on your computer to update projects by calling the pod install command. If you're not familiar with Cocoapods then here is a description of what it is:

"Cocoapods is a dependency manager for Swift and Objective-C Cocoa projects. It has almost ten thousand libraries and can help you scale your projects elegantly. CocoaPods is built with Ruby and is installable with the default Ruby available on OS X."

Cocoapods helps keep all the dependencies for your projects updated meaning that you don't have to manually download and install new versions but instead can easily download updates with only a few lines of code in the terminal. If you need help setting up Cocoapods then a tutorial can be found here.

Adding the development modules

Open your project and then open the Podfile file. You will need to edit it to contain the following code but with your project name as the target (our project is called Starter Kit).

source ''

target 'Chat SDK Firebase' do

    pod "ChatUI", :path => "ChatUI"
    pod "ChatCoreData", :path => "ChatCoreData"
    pod "ChatCore", :path => "ChatCore"
    pod "ChatFirebaseAdapter", :path => "ChatFirebaseAdapter"
    pod "ChatBackendless", :path => "ChatBackendless"

NOTE: Depending on where you put the chat pods in your project will determine the above folder structure. You should use "../ChatUI" if the ChatUI folder is in one folder up from the main project.

Finally open the terminal and cd to the directory of your existing project. Run the following command in the terminal:

pod install

This command will create a new .xcworkspace Xcode file with all the project dependancies installed. Double click this file to open your project.

Your folder structure should look similar to the image aboSeve.

Configuring ChatSDK

ChatSDK relies on serveral different services to be fully operational. Firebase deals with storing the user data, notifying the app when the data has changed and storing the files for the audio, video and image messages. Backendless takes care of push notifications on the app. Facebook and Twitter can also be used if you want social media login for your app. ChatSDK comes preconfigured for all these types on our test accounts meaning you will need to create your own before you can get fully up and running.

Setting up the project info.plist

ChatSDK stores all the configuration keys in the info.plist file of your project. You will need to add some additional fields to fully configure the project.

User location

To enable the app to access the user's location we need to add the location permissions. The users location will be used when sending location messages. Add the following lines to your plist:


Both of these should be String values and the string you enter will be the message displayed when requesting the users location. For example "ChatSDK wants to use your location to send location messages".

App Transport Security

For iOS 9 and above this is required for the app to authorise the upload and download of data. Without this field the app will not work correctly. Add the fields below exactly as seen:

Finally we need to add the following entries to the info.plist

The structure of this is important as the Chat looks up the values it needs during set up. If you don't want to use one of the social media options then leave the field blank. The app will pick this up and will disable the login option.

NOTE: It is important to add the dictionary keys exactly as they can be seen here (eg storage_path), if this is entered wrongly the ChatSDK won't work correctly for certain functionality.

Each needs to be of type String. Don't worry that these are all currently blank. We will be filling them in the following steps.


  1. Go to the Firebase website and create an account if you do not already have one.
  2. Create an app on the Firebase dashboard
  3. Click on this project and then click database in the left hand menu
  4. Copy the url from your browser. It will look something like this:
  5. Go to your newly created firebase -> path entry in your plist
  6. Add the url in the following format: gs://

Firebase's data structure is like a tree. The url you just added is the trunk and then we can branch off from this with different pieces of information stored in the database. We have added a root path to enable you to easily split onto different branches of the project.

For example you can easily split the app between using the test and production databases by modifying the root path in the plist:

We would recommend adding something simple into this field while you get used to how the app works. For now just enter V_0_1.

Click the cog icon at the top of the page and select Project settings. Now click add app and add an iOS app to your database. You will need to enter your project bundleID but can ignore the instructions for adding code to the project, this has already been completed. On completing this you should initialise a download of the GoogleService-Info.plist file. You will need to add this to your main project file:

To get started click the Auth tab and then Sign in method. We recommend enabling Email/Password and Anonymous login initially to allow you to get to grips with the ChatSDK.


  1. If you haven't got a Backendless account then go to the Backendless website and create one.
  2. Create a new app on the dashboard and click on it
  3. Click settings in the top menu to bring up your app keys
  4. Copy the App ID into your plist in the backendless -> app_id field
  5. Copy the iOS Secret into your plist in the backendless -> app_secret field
  6. Copy the version from the top of the screen in the backendless -> app_version field

The app is now ready to go. There is still some push notification set up to do but otherwise you can load up the app and login to your new accounts fine.

Social media login

If you don't want social media login for your app then you only need to hide or disable their respective buttons in the bLoginViewController of the app. If you do want them then there is some initial set up required to get them working:


Go to the Facebook Developers page and create a new app for the project. If you are having trouble creating your app then a guide can be found here.

NOTE: You should only use the app set up part of the guide. The framework and login code is already included in the app and shouldn't be added again

Find the app ID on the app page and copy it. We will be adding it to a number of places in our plist:

  1. Add it to the facebook -> app_id field in the plist
  2. Create a new field called FacebookAppID and add it as the String value
  3. Create a new field called FacebookDisplayName, with type String, and copy your app name into this field
  4. Create a new field called URL Types with type array. Add a dictionary as its only child. That dictionary needs to have one entry with the name URL Schemes and type array. Add a new entry to the URL Schemes array and set its value to be fb followed by your appID. Refer to the image below if you are in any doubt:


NOTE: Make sure you add fb in front of the FacebookID in URL Schemes
This is also covered in the Facebook guide mentioned above if you need further clarification

Now go to the settings tab of your Facebook developers account and add the BundleID of your app. As you can see below you can add multiple bundleIDs meaning you can use the same Facebook app for multiple versions of your app.

You MUST also add a contact email on this page.
You should also set single sign on to on, deep linking to off and automatic log to off.

Next, click the Status and Review tab and click on the switch to enable your app for access by the general public.

Click on the app dashboard and copy the AppID and App Secret. Now navigate back to your Firebase account, click into your app and then click Login & Auth in the left menu. Navigate to the Facebook tab and then enter and save your Facebook AppID and Secret. Also make sure to check the Enable Facebook Authentication box.

Next go back into your Firebase dashboard and navigation back to the authentication menu, click Facebook and then enable the login with Facebook. You need to enter your FacebookID and Facebook secret into the Firebase dashboard.
You should notice that the final step of this involves adding an OAuth redirect. Copy the link and the navigate back to your Facebook developers account.

In the bottom left hand menu you should see a products menu. Click add product and then choose Facebook login. Now add your OAuth redirect to this new view as seen below:

Finally open your project and import this library into the App Delegate file:

#import <Facebook-iOS-SDK/FBSDKCoreKit/FBSDKCoreKit.h>

Also add this to the bottom of the AppDelegate.m file:

// During the Facebook login flow, your app passes control to the Facebook iOS app or Facebook in a mobile browser.
// After authentication, your app will be called back with the session information.
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation { return [[FBSDKApplicationDelegate sharedInstance] application:application openURL:url sourceApplication:sourceApplication annotation:annotation]; }

You should now be able to login with Facebook when using the ChatSDK.


  1. Go to the Twitter Developers page and create a new app for your project.
  2. Click on the Keys and Access Tokens tab and find the Twitter API Key
  3. Add the Twitter API Key into the info.plist in your project under the twitter -> api_key field


Copy your Twitter API key and Twitter Secret and navigate back to Firebase. Click on your app, click on the Login & Auth tab and then on the Twitter tab. Now enter your Twitter details and make sure to click the Enable Twitter Authentication box.

Finally, similar to what we did for Facebook, you need to add the OAuth callback. Go to the Auth section, click Twitter and copy the OAuth callback URL. Return to the Twitter developer page, click Settings and copy the callback URL into the Callback URL field.

Setting up the App Delegate

The app needs to perform a number of actions when the state of the app changes for this reason we need to add some custom code into your App Delegate file to make sure these functions are correctly called.

Make sure the App Delegate imports the following libraries

#import "BAppDelegate.h"
#import <ChatCore/BNetworkManager.h>
#import <ChatFirebaseAdapter/BChatcatNetworkAdapter.h>
#import <Facebook-iOS-SDK/FBSDKCoreKit/FBSDKCoreKit.h> #import <ChatCore/BStorageManager.h> #import <ChatCoreData/BCoreDataManager.h>

Now make sure that the functions below are all included in your App Delegate and that the functions inside them are also added. If you have much in your App Delegate be careful to include your current code as well as the new functions:

NOTE: The code we are adding in the didFinishLaunching sets up all the network adapters that allow the Chat to function properly. It is very important that they are always called as soon as the app starts so we recommend them always being placed in the below function to ensure the SDK runs smoothly.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    // Setup Facebook
    [[FBSDKApplicationDelegate sharedInstance] application:application didFinishLaunchingWithOptions:launchOptions];
    BChatcatNetworkAdapter * adapter = [[BChatcatNetworkAdapter alloc] init];
    [[BNetworkManager sharedManager] setNetworkAdapter:adapter];
    [[BNetworkManager sharedManager] setAuthenticationAdapter:adapter];
    [[BStorageManager sharedManager] setAdapter:[[BCoreDataManager alloc] init]];
    // Register for push notifications
    [BChatcatNetworkAdapter registerForPushNotificationsWithApplication:application launchOptions:launchOptions];

BFirebaseUploadHandler * firbaseUpload = [[BFirebaseUploadHandler alloc] init];
adapter.uploadHandler = firbaseUpload;
adapter.authenticationViewController = [[BLoginViewController alloc] initWithNibName:Nil bundle:[NSBundle chatUIBundle]];

    BBackendlessHandler * backendlessHandler = [[BBackendlessHandler alloc] initWithAppKey:[BSettingsManager backendlessAppId] secretKey:[BSettingsManager backendlessSecretKey] versionKey:[BSettingsManager backendlessVersionKey]];
adapter.pushHandler = backendlessHandler;

... the rest of your own code here ...

return YES;


- (void)applicationDidBecomeActive:(UIApplication *)application {

[FBSDKAppEvents activateApp];
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.


-(void) application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {

[[BNetworkManager sharedManager].adapter application:application didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];

-(void) application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {

[[BNetworkManager sharedManager].adapter application:application didReceiveRemoteNotification:userInfo];

Push notifications

All the code for Push Notifications is already included in ChatSDK. Getting them working only requires a small amount of configuration. For help regarding this you can take a look at the Backendless guide.

NOTE: Some of the steps in this tutorial include adding code to the app, these steps should be unnecessary as they have already been added to the project.

NOTE: If you want push notifications to work in Development mode make sure to configure them in your provisioning profile for both development and production.


Firebase starts of with very lax security rules. That would mean that anyone could delete all the data in your database by writing one JavaScript query. To stop this, open the dashboard and click on the "Security" tab. Copy the following code:

  "rules": {
    ".read": true,
    ".write": "auth != null"

This will mean that only authenticated users can modify your data. To read more about Firebase security look here.

NOTE: The security rules provided above are very basic and would allow any authenticated user to have full control over your database! The reason that I've not provided more sophisticated rules is becuase I think it's important that **you** understand Firebase security. If I provide a set of rules it would be very tempting to just add them to your Firebase and forget about them. This may cause problems down the line when your chat gets hacked.

I can't guarantee that any set of rules that I would write would be completely secure. One mistake in my rules may cause your chat app to be hacked. For that reason, it's really important that you take the time to understand Firebase security and write your own set of secure rules.

Now the app should be ready to go!

If you have any problems Firebase offer good documentation and Facebook have an integration guide.


For a guide on how to add the Chat SDK to an existing project, please see the integration guide.


Periodically, we will be releasing updates of the Chat SDK. In order to make upgrading as easy as possible you should adhere to the following guidelines:

  • Where possible, don't modify Chat SDK code. If you can, you should make subclasses of existing classes rather than modifying the original class. 
  • If you need to modify a function contained in a category, create a new category and a new function with a different name. Then subclass the classes that use the original funcition and call your new function instead
  • Sometimes this approach may not be possible. In that case you can do the following. 
    • Track your project using Git
    • Modify the Chat SDK files on the master branch
    • When you want to update, create a new update branch
    • Delete your modified files and copy in the Chat SDK files
    • Merge your update branchy with your master branch
    • Resolve any conflicts

Using these approaches it's possible to keep up to date with the latest version of the Chat SDK fairly easily.



ChatSDK Back End

Understanding how the app conceptually fits together will help you integrate it with your own project more quickly.

ChatSDK uses three systems to store data: Coredata, Parse and Firebase.

  • Coredata is an ORM which comes with the iOS development environment. Each entity in the SDK is represented by an object: message, thread, user etc... When data changes on the Firebase server, the data is automatically updated and saved locally.
  • Parse is a powerful online database service which is especially good for storing files and making location based queries. We use Parse for two main functions. Firstly, to store photos, audio files and video files. The URL of the message type is then stored on Firebase allowing us to access it quickly. Second, Parse is used to handle push notifications.
  • Firebase is a real-time database which stores all the information produced by the user in a JSON format. Firebase creates a two-way data stream allowing us to save data on the remote server and register for notifications when the remote data changes.

Chat Modules

The chat has been split up into 4 distinct modules. This is to enable mix and matching of parts of the app, if you want to use the entire app except the user interface then it is easy to leave out this module and still integrate the app into your project. All the functionality from the app has been split out into four distinct libraries these are: ChatCore, ChatCoreData, ChatUI and ChatFirebaseAdapter.

  • ChatCore contains helper classes that are required by all modules.
  • ChatCoreData deals with Coredata and the data objects stored on your phone.
  • ChatUI deals with the user interface in the app.
  • FirebaseNetworkAdapter deals with all network communication.

This module structure means that the front end is completely decoupled from the back end of the app.

The easiest way to understand is to look at some examples:

Sending a message - part 1

In the SDK all entities are persisted using CoreData. Before creating a message, it's a good idea to create a new undo grouping. This means that if there's an error sending the message, the database state can be rolled back.

[[BCoreDataManager sharedManager].managedObjectContext.undoManager beginUndoGrouping];

Next the message is created:

CDMessage * message = [[BCoreDataManager sharedManager] createEntity:bMessageEntity];
message.text = @"Test Message";
message.type = @(bMessageTypeText); = [NSDate date];
message.user = (CDUser *) self.currentUser.model;
message.delivered = @(NO); = @(YES);
message.flagged = @(NO);
message.thread = [[BCoreDataManager sharedManager] fetchEntityWithID:threadID withType:bThreadEntity];

NOTE: You might notice we set the to @(YES), this is becuase as you have written the message you have already read it. This means that you won't get a "new message" indicator when this message is downloaded.

Here it would also be possible to customize the message's font, text color or bubble colour. Before sending we need to end the undo grouping:

[[BCoreDataManager sharedManager].managedObjectContext.undoManager endUndoGrouping];

Then we send the message using the network adapter:

return [self sendMessage:message.model];

Creating a new thread follows a similar pattern. It’s just necessary to call a different method on the network adapter.

Sending a message - part 2

In the last section we looked at how to send a message. We didn't look into how a message is actually sent though. Depending on your app depends on how much you need to know about how this all works. If you are going to be creating custom cells then it is well worth understanding the flow to send a message in ChatSDK.

NOTE: Depending on how well acquainted you are with the code, you might notice that the flow to send messages is the same to create new threads and new users. You'd be correct they all follow the same pattern: create object, serialize for Firebase, push to Firebase, deserialise from Firebase, update Coredata object.

A briefly mentioned above the flow for sending a message is simple.

  1. Create a Coredata object
    The first thing we do is create a new Coredata object for our new message. This can be seen in the messageWithModel function. When ever you create a new message that message will need to be represented by an object in Coredata.
  2. Serialize message information
    Firebase is a real time database which can only store JSON information. This means that all the information on the Message object will need to be converted to JSON format. We then place this data into an NSDictionary ready to be uploaded to Firebase.
  3. Push to Firebase
    As mentioned above, the data structure in Firebase is like a tree. The trunk is the app Firebase URL and then other pieces of information are added as branches. For this reason we need to add the message dictionary in the right place. As it is a message we will add it with the other messages but on its only smaller branch named after its entityID. We then use the Firebase function setValue to push this message dictionary to the database.
  4. Deserialize message information
    An important part about running an instant messenger is to ensure data stored on the database is the same as saved on each device. Once a message has been sent the app receives a notification that a new message has been added. We then download that message and deserialize it. This is the complete reverse of serialization as it converts a dictionary object from JSON to the Coredata formats we want.
  5. Update Coredata
    It might seem strange to create a new message object and then to update it with the data downloaded from Firebase but when thinking about the consistency of multiple devices it makes sense. Although your device already contains the Coredata object for this message none of the other devices do. This means that by checking if the Coredata object exists and updating it with the latest data from Firebase we ensure all devices are consistent with the information uploaded.

Once you have got an understanding of this then you can also understand creating new threads or new users. They are done in exactly the same way and with exactly the same functions. We use [user push] to update a user, [thread push] to update or create a thread and although messages seem to be sent with [message send] if you look into that function you'll see that [self push] is immediately called.

Receiving a message

To receive a message ChatSDK needs to be observing the message path in Firebase. This means when a message is sent it will alert the app do download the new message and refresh the thread view to display it.

When a user logs on to the app the function userOn is called in the BStatemanager.m. This loops through all the users threads and contacts and adds observers. When a user logs off then these observers are removed.

We're going to look at public messages as the concepts apply to public messages and contact details. As you can see we get the thread path on Firebase an add an observer to check if a thread is added to the path.

Firebase * threadsRef = [Firebase userThreadsRef:entityID];
[threadsRef observeEventType:FEventTypeChildAdded withBlock:^(FDataSnapshot * snapshot) {
    // Returns threads one by one
    if (snapshot.value != [NSNull null]) {
        // Make the new thread
        CCThreadWrapper * thread = [CCThreadWrapper threadWithEntityID:snapshot.key];
        id<PUser> user = [BNetworkManager sharedManager].adapter.currentUserModel;
        if (![thread.model.users containsObject:user]) {
            [thread.model addUser:user];
        [thread on];
        [thread messagesOn];
        [thread usersOn];

When a new thread is added then the code inside is called. First we make sure we have all users in the thread added on our device and then we add observers to the thread, the messages and the users in the thread:

  • [thread on]
    We add an observer to the new thread looking at when the value changes with regard to the thread. We also download and add the thread to our Coredata.
  • [thread messagesOn]
    We set an observer to check when a new message is added to the thread. When a new message is added we download the message to Coredata and notify the entire app so we can refresh the threads.
  • [thread usersOn]
    For the user in the thread we add observers to check if their personal meta data changes and also add the user to our device.

When a message has been received we send a device wide notification. This can be received with the following code.

_messageObserver = [[NSNotificationCenter defaultCenter] addObserverForName:bMessageAddedNotification object:Nil queue:Nil usingBlock:^(NSNotification * notification) {

    // Enter code here

The code inside will be run when a new message has been added - currently we use this to refresh the threads view and chat view controller.


Promises are used heavily in this project and if you have never encountered them before it’s worth taking the time to understand them conceptually to help while working on the project.

You can find the Promise library here.

An introduction and guide to promises in iOS can be found here and they are quickly being used in all types of programming.

Promises are very good at simplifying asycronous code. Instead of requiring functions nested in nested functions we can instead create an elegant chain of promises. If we error at any stage of this chain we can easily deal with it in our error block as we merely return with the error. There are also clever ways in which you can run an array of promises meaning you can asycronously run multiple functions and only return in the completion block when they have all returned successfully. Checkout the link to the library above which contains some good examples and explanations.


This should give you an idea of the basic principles of the Firebase back end. The Firebase code is quite concise - the bulk of the network functionality is handled by two fairly short classes. However, conceptually it can take some time to fully understand the patterns used when working with Firebase as opposed to a standard relational database.

While looking at the excellent documentation provided by Firebase. I'm also always available to answer queries - I usually reply in less than an hour.


In this section we are going to be listing some of the well used functions in ChatSDK. This means if you are stuck then this area is a good first port of call to especially for the bread and butter functions in ChatSDK. Search for the topic title to quickly navigate to the answer:

  • How do I add a new database field?
  • Storyboard integration
  • How is a user created?
  • How can I add more information to the user object?
  • How do I get a user object from a user ID?
  • How can I create a thread with a userID or multiple userIDs?
  • How can I create or fetch a thread with the threadID?
  • How can I compile a list of threads for the current user?

How do I add a new database field?

If you want to extend the chat component to add your own data you're going to need to add new fields both to the app's CoreData storage and to Firebase.


First we need to add the property to the CoreData schema. Open ChatSDK.xcdatamodeld in the left navigation bar and create a new version of the model.

Editor->Add Model Version

Call it DataModel v[next version number]

Click ChatSDK.xcdatamodeld again and open the right side bar. Click the icon that looks like a piece of paper at the top then change Model Version to the new model version you created.

In the left navigation bar again, expand the ChatSDK.xcdatamodeld by clicking the little arrow and select the model version. After that make the changes you need to make to the entities.

In this example, I’m going to add a last online property to the user entity.

Under the “entities” heading click the BUser entity. Under attributes click + to add a new attribute. Set the name for the variable and choose it’s type. In this case we choose Date.

Now we need to update the entities. Right click on the left in the CoreDataEntities folder and choose New File then choose Core Data then NSManagedObject subclass, select the new DataModel you created then select all the entities. Click Next and select the folder CoreDataEntities. Click Create.

This will write over the existing entities updating them with the properties you added.

CoreData will automatically update the database when you next open the app.

Next we need to update the User protocol. The user protocol encapsulates the user object. This means that if you wanted to design your own user object or use a different storage type, you could implement the protocol with your new object and it would work perfectly with the existing chat component.

Open PUser.h and add a new method to access the last updated property.

-(NSDate *) lastOnline; -(void) setLastOnline: (NSDate *) lastOnline;;

Now we can access the variable from within the chat component and we can save the variable to CoreData.


Now we need to make sure that the variable can be saved in Firebase.

The Chat SDK comes with a framework which simplifies working with Firebase.

In order for our objects to be added to Firebase they need to be serialized. When we receive an object from Firebase it then needs to be de-serialized. The framework will handle most of the details but we still need to add the serialization and deserialization code.

Open BUser+Additions.h and find the method called “asDictionary”. We need to add this variable to the dictionary so when the user is uploaded this variable is set as well.

First we’re going to create a new key. Open BDefines.h and add a new key:

#define b_LastOnline @"last-online”

Then add the property to the user’s dictionary:

return @{b_Name:,
         b_FacebookID: self.facebookID,
         b_PictureURL: self.pictureURL,
         b_PictureExists: self.pictureExists,
         b_LastOnline: @(self.lastOnline.timeIntervalSince1970)};

Now when we push a user the lastOnline value will also be pushed. We add the time interval since 1970 because Firebase can only store basic data types - not NSDates.

Now we need to make sure that when we are pushed a new user from the Firebase, that the locally stored user object is also updated.

Look at the updateFromDicationary method in BUser+Additions.m. This method updates the object when provided with a dictionary of serialized data.

NSNumber * lastOnline = snapshot.value[b_LastOnline];
if (lastOnline) {
    user.lastOnline = [NSDate  dateWithTimeIntervalSince1970:lastOnline.doubleValue];

Here we extract the last online time from the user and add it to the database object.

That's pretty much it. Now all we need to do is set the value and when we select or push a user object, the last online field will be updated automatically.

Storyboard integration

Many people think that Storyboards and XIBs can't be used together. That you either have to create the whole app in one monolithic Storyboard or you have to use hundreds of interconnected XIB files. In fact, Storyboards are just an extra tool that can be used for interface creation along side XIBs and code. In some situations it's useful to use a Storyboard and in others it's better to use an XIB.

Lets say that you want to launch the Threads view from your Storyboard using a button. First, you'd need to right click drag the button from the Storyboard into the relevant .m file to create an action. You'd end up with an action like this:

- (IBAction) openChatButtonPressed:(UIButton *)sender {


Now, whenever you click this button, this code will be called.

Inside this method we're going to load up the threads view controller of the group Chat SDK.

[self.navigationController pushViewController:[[BThreadsViewController alloc] initWithNibName:Nil bundle:Nil] animated:YES];

This will create a new instance of the threads view (obviously in the Firebase version, you would have had to have authenticated with Firebase before doing this). Since Storyboards use the same navigation controller as XIBs, we can just push the new view onto the stack.

To get back to our Storyboard, we would just pop the view controller:

[self.navigationController popViewControllerAnimated:YES];

This will take us back to the previous Storyboard view.

How is a user created?

To find where a user is created we need to look at the BFirebaseNetworkAdapter class. When the app first loads up it will try to authenticate the user. Once that's successful it will call the handleFAUser method:

promise.thenOnMain(^id(FAuthData * firebaseUser) {
    return [self handleFAUser: firebaseUser];
}, Nil);

The purpose of this method is to get the app up-to-date with the server. Lets go through the function in detail to see what's happening.

First we check if the user has been correctly authenticated with Firebase. We do this by checking the Firebase user object returned and also a manual _userAuthenticated flag.

Next we create a new user object with the userWithAuthData function:

CCUserWrapper * user = [CCUserWrapper userWithAuthData:firebaseUser];

This function will either fetch or create a user object with the entityID of the Firebase user. It then updates the user object using the Firebase user object:

Depending on the login method depends on how we update the user but the principle of what is happening is the same for all login methods. Below we will look at the updating the user object for a Twitter login:

else if ([data.provider isEqualToString:@"twitter"]) {
    NSString * name = userData[@"displayName"];
    if (name && ! { = name;
    // Check to see if this twitter account is already linked to the user
    CDUserAccount * account = [_model accountWithType:bAccountTypeTwitter];
    if (!account) {
        account = [[BCoreDataManager sharedManager] createEntity:bUserAccountEntity];
        account.type = @(bAccountTypeTwitter);
        [_model addLinkedAccountsObject:account];
    account.token = userData[@"accessToken"];
    NSString * url = userData[@"cachedUserProfile"][@"profile_image_url_https"];
    NSString * fixedURL = [url stringByReplacingOccurrencesOfString:@"_normal" withString:@""];
    [[BNetworkManager sharedManager] setProfilePictureWithImageURL:fixedURL];
  • Check if the user object already has a name - if not then set one
  • Set the account token for the user if it doesn't already have one
  • Set the profile picture for the user if it doesn't have one set

Now we have updated the user object we need to push this object to the Firebase database. The once function updates the user from the remote server.

There are a few functions contained in [user once] which add observers to the user and save the Coredata database before we finally push the user to the database with [user push];

We have talked about this in the documentation above, we convert the data on the user object into JSON format in an NSDictionary before setting the value on Firebase to be this dictionary value.

An important thing to note in user creation is that a user is always identified by the entityID set when it is created in Coredata. Setting this as the path name on Firebase means we can always fetch the appropriate user object if we need to or create identical Coredata entries between devices.

How can I add more information to the user object?

In ChatSDK custom user data is stored as meta-data on the firebase database. This makes it very easy to access, add or remove custom fields. The code is already set up with setter and getter functions to make it even easier to add your own fields:

This function sets a custom piece of meta data:

[user setMetaString:@”” forKey:bEmailKey];

This function will return the custom emta data:

[user metaStringForKey:bEmailKey];

NOTE: You might notice we use an email key instead of an @”email” string. This is so that typos aren’t accidentally made and so the same string can be used throughout the entire app. The current defines variables are contained in the bDefines.h file


#define bEmailKey @"email"

Remember to import the bDefines.h file if you need these keys in a separate class. Lastly you need to push the user object to the database, this will update the firebase database and save the data for the next time it is retrieved. This also updates the coreData object with the newly added data. The function which does this is:

[[BNetworkManager sharedManager].adapter pushUser];

If I wanted to add hairColor to a user meta data I would go through these steps with my custom information.

1. Add to the defines file

#define bHairColorKey @"hairColor"

2. In my code set the user data

[user setMetaString:@”Brown” forKey:bHairColorKey];

3. Push the user

[[BNetworkManager sharedManager].adapter pushUser];

How do I get a user object from a user ID?

You have two options here:

1. You can get the current user object

There is a function especially for getting the current user

id<PUser> currentUser = [BNetworkManager sharedManager].adapter.currentUserModel;

2. You can get a user object using a userID.

Just fetch it from your coredata database. If it doesn’t exist, with the given userID, then a user will be created with that ID.

id<PUser> otherUser = [[BCoreDataManager sharedManager] fetchOrCreateEntityWithID:userID withType:bUserEntity];

How can I create a thread with a userID or multiple userIDs?

It doesn't matter how many users you want in a thread, the method for creating them is the same. A thread is created with an array of user objects, if you only have one user then the array will only contain one user object. A group thread would have multiple user objects in the array input. There are two parts to thread creation:

  1. Create the thread
  2. Load the thread so the user can type in it.

Creating the thread can be achieved with the createThread function:

[[BNetworkManager sharedManager].adapter createThreadWithUsers:userIDArray threadCreated:^(NSError * error, id<PThread> thread) {
if (!error) {
[self pushChatViewControllerWithThread:thread];
else {
[UIView alertWithTitle:bErrorTitle withMessage:[NSBundle t:bThreadCreationError]];

We input an array of userIDs (userIDArray) and the thread object is returned in the completion block.

Now we have the option of loading the thread to the current view. This can be achieved once a thread object has been returned without error callinging pushChatViewControllerWithThread funtcion:

In this example you can see the error checking which ensures the thread has been created correctly.


How can I create or fetch a thread with the threadID?

Simply call this function to fetch or create a thread with a certain threadID:

[[BCoreDataManager sharedManager] fetchEntityWithID:threadID withType:bThreadEntity];

How can I compile a list of threads for the current user?

A user might have multiple threads and so these can be put into an array with the below function, this will fetch all the public threads a user is a member of. To fetch the private threads just use a bThreadTypePrivate type:

NSArray * threads = [[BNetworkManager sharedManager].adapter threadsWithType:bThreadTypePublic];

NOTE: Remember fetching threads will only fetch them from the Coredata database. You cannot get a list of another users threads if the current user is not a member of them as they will not have been created in Coredata so won't be fetched.