Build

iOS Chat Components Release: Build Mobile Chat Experiences

8 min read Chandler Mayo on Feb 22, 2022
Try PubNub Today

Free up to 1MM monthly messages. No credit card required.

Subscribe to our newsletter

By submitting this form, you are agreeing to our Terms and Conditions and Privacy Policy.

In this tutorial you’ll discover how to set up and use PubNub's iOS Chat components to build chat in an existing app. All the steps you need to use the components are included in this post. 

We're excited to announce the release of our iOS Chat Components. We've created ready-to use-components for iOS developers that make it simple to add essential chat features to your app while reducing your time to market. With our iOS Chat Components you're free to focus on building what you actually care about. Sign up to learn more about our iOS Chat Components release using the form below. Then, read on to learn how you use our new iOS components in an existing open-source iOS app.

Register for PubNub's Chat Community

Get the most recent updates about PubNub’s newest chat features.

By signing up, you’ll also receive:

  • Free PubNub swag
  • Exclusive Q&A sessions, workshops, and webinars with our engineers and product managers
  • The opportunity to have your voice heard by influencing our chat roadmap

PubNub’s iOS Components for Chat enable mobile developers to create rich and flexible chat experiences without the opportunity cost of the time spent building chat features.

Don’t reinvent chat UI components and build the infrastructure yourself when PubNub has already done it for you - you could be focused on other parts of your application! No need to go through the complexity of designing the architecture of a realtime network. Instead, use our components, predefined repositories, and view models to create custom apps for a wide range of use cases.

Our set of iOS Chat Components are packed with the features you’d expect from any chat experience:

  • User and Channel Metadata: Fetch metadata about users, channels, and memberships from objects storage using custom hooks.

  • Channel Subscription Management: Automatic subscriptions to current channel and optional subscriptions to other channels and channel groups.

  • Messages: Publish and listen to text messages and fetch history for each channel.

  • User Presence: Fetch currently present users and listen to new presence events like a user subscribing or leaving.

  • Typing Indicators: Typing indicators displayed as text notifications or messages.

  • Persistent Data Storage: Store messages, channels, and users locally for offline use.

Our iOS Chat Components are modifiable to your requirements so you’re free to create chat for various use cases all with different functionalities and customizable looks.

Build a telemedicine chat app, multiplayer chat lobby, live support chat center, live event chat lobby, or another style of chat with minimal effort. Build a powerful and modular mobile chat app using these components as a starting point. Best of all: There’s no need to deal with server code at all. PubNub powers all of the messaging features: message delivery in real-time, metadata, user presence, and other chat related data to facilitate the actions within the chat UI components.

weather-chat-ny-chat
Weather chat powered by PubNub iOS Chat Components.

This tutorial series demonstrates how to take PubNub iOS Chat Components and integrate them into any iOS app. All the steps you need to use the components are included in this post. 

  • For this tutorial we’ve selected a open-source iOS app we found on GitHub that could benefit from chat as an additional feature.

  • This post was created with Xcode Version 13.2.1 and the latest version of our Chat Components for iOS. We recommend using the latest version of Xcode available.

  • This weather app will be used as our starting point. We’ll begin by setting this app up and then we’ll add chat powered by PubNub iOS Chat Components.

  • The end goal is a weather app where users can chat about the weather based on the location of their device or the location they selected manually.

  • We picked this app because *it wasn't created by PubNub* and we want to show you how you can use our iOS components in real apps like this one.

  • The complete app with PubNub iOS Chat Components can be found in this repo. In the complete app we’ve done everything in this tutorial and refactored the app we started with to follow best Swift practices so that you can see how you would expand further. 

How does PubNub work with iOS Chat Components?

Before using PubNub iOS Chat Components, you should know why PubNub is the best choice for powering them. PubNub is used for real-time message delivery, metadata, user presence, and other chat related data to facilitate the actions within the chat UI components.

PubNub is a fantastic backend API for all types of real-time chat applications because it offers a lot of functionality that never have to build yourself. Some essential advantages of PubNub are:

  • PubNub delivers billions of messages every day and will effortlessly scale with your application as it grows.

  • User presence features are built-in. Easily create online and offline indicators and typing indicators.

  • Storage and Playback for message history. History is essential for a complete user experience.

  • Push Notifications support for iOS and Android mobile apps. Keep users online by alerting them of new messages.

PubNub iOS Chat Components have PubNub services fully incorporated and are ready to use in an existing iOS App. It’s recommended that you’re familiar with Swift and iOS development if you wish to modify the iOS components for use in your application. However, you can absolutely follow along, explore, and use these iOS Chat Components without prior experience.

Available mobile chat components

The following chat components are included with PubNub iOS Chat Components:

  • MemberList: List of users with properties like names, titles, or avatars. 

  • MessageList: List of messages with sender details.

  • MessageInput: Field to send messages to chat rooms. When you type this component also triggers typing indicators for other users.

  • ChannelList: List of channels that represents chat rooms in the application. We won’t be using this component in this tutorial. However, it’s easy to include if it’s necessary in your application.

Now that you have an understanding of the available components for iOS, let’s explore how you set up your chat API to try them out.

Setting up a chat API for Mobile Chat Components 

You’ll need to set up a PubNub account to use PubNub iOS Chat Components. The end result will be two API keys that you’ll use in your mobile chat application. A PubNub account and API keys are always free (perfect for startups).

  1. You’ll first need to sign up for a free PubNub account.

  2. Sign in to your PubNub Dashboard.

  3. Go to Apps.

  4. Click Create New App.

  5. Give your app a name.

  6. Click Create.

  7. Click your new app to open its settings.

  8. When you create a new app the first set of keys is generated automatically. However, a single app can have as many keysets as you like. PubNub recommends that you create separate keysets for production and test environments.

  9. Select a keyset. 

  10. Enable the Channel Presence feature for your keyset. This will be used to show how many users are active.

  11. Enable the Storage and Playback feature for your keyset. If you don’t plan to need message history then you can leave this off.

  12. Enable any other functionality you plan to use (if desired).

  13. Save the changes.

  14. Copy the Publish and Subscribe keys for the next steps.

How to use iOS Chat Components in your application

Now that you have your PubNub API keys you can begin building with iOS Chat Components. Get started by downloading an existing weather app that we will add chat components to.

Getting Started with iOS Chat Components

Download this weather app at this commit. This was the last commit of the sample app before we added iOS Chat Components. We picked this app because *it wasn't created by PubNub* and we want to show you how you can use our iOS components in real apps like this one. We’ll start from there so you can add them yourself. If you clone the repo at the latest commit you’ll get the completed app.

Download the .zip of the commit and extract the folder. Or clone the repo and switch to this commit e9232c7. You can also use the 'Open with Xcode' button in GitHub.

git clone https://github.com/PubNubDevelopers/Swift-Weather-Chat/
cd Weather
git checkout -b weather_tutorial e9232c7

Open the file ‘Sun.xcodeproj’ in Xcode.

Open ‘Supporting Files > Constants.swift’. We need to configure the Weather API and add our PubNub configuration here.

Go to https://home.openweathermap.org/users/sign_up to get an API key for fetching the weather. The account is free and you can build this app without a paid plan. 

Paste your API key in the quotations beside let “apiKey =”

let apiKey = "WEATHER-KEY-HERE"

In the same file add the following at the bottom:

let PUBNUB_PUBLISH_KEY = "pub-c-key" 
let PUBNUB_SUBSCRIBE_KEY = "sub-c-key"

Replace “pub-c-key” and “sub-c-key” with your PubNub API keys.

Install iOS Chat Components

Inside the Xcode project, select File > Add Packages..., and enter the iOS Components repository URL:

https://github.com/pubnub/chat-components-ios

After the package details load, click the Add Package button in the lower right corner.

For any additional questions about adding packages in Xcode, refer to Apple documentation.

Building Chat Features with iOS Chat Components in Xcode

Open ‘View Controllers > ViewController.swift’. For the rest of this tutorial we’ll be (mostly) focusing on this file. All of our chat functionality will live here. 

Under “import CoreLocation” add the following to import PubNub, PubNubChat, and PubNubChatComponents:

import PubNub
import PubNubChat
import PubNubChatComponents

Directly under “class ViewController: UIViewController” add the following to create a ChatProvider instance, declare the variable we’ll use for the current channel, and a UIView for our chat. After that we’ll create our PubNub configuration and a function to generate a short random string to use as the UUID and username of our chat users. You must create a UUID for each unique user. All of our users in this app will be anonymous ids. 

var chatProvider: PubNubChatProvider?
    var channelId = "San Francisco" // Default channel
    var chatView: UIView!
    
    // Create PubNub Configuration
    lazy var pubnubConfiguration = {
      return PubNubConfiguration(
        publishKey: PUBNUB_PUBLISH_KEY, // see Constants.swift to set PubNub API keys
        subscribeKey: PUBNUB_SUBSCRIBE_KEY,
        uuid: randomString(length: 6)
      )
    }()
    
    func randomString(length: Int) -> String { // Used to create a random username/uuid for chat
      let letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
      return String((0..<length).map{ _ in letters.randomElement()! })
    }

Now we can create a function for handling a button press that’ll show our chat UIView. We’ll create a button to link this function to in a later step. Directly after that we’ll also create a function to load the data into the chatProvider for our chat app and handle subscribing to the current channel.

@IBAction func startChat(_ sender: UIButton) { // Show chat for current city / location
        chatView=UIView(frame: self.view.bounds)

        // PubNub.log.levels = [.all]
        // PubNub.log.writers = [ConsoleLogWriter()]
        
        guard let messageListViewModel = try! chatProvider?.messageListComponentViewModel(pubnubChannelId: channelId) else {
           preconditionFailure("Could not create initial view models")
        }
        
        let navigation = UINavigationController()
        navigation.viewControllers = [messageListViewModel.configuredComponentView()]
    
        self.show(navigation, sender: nil)
    }
    
    func preloadData(_ chatProvider: PubNubChatProvider) {
        // Create a user object with UUID
        let user = PubNubChatUser(
          id: chatProvider.pubnubConfig.uuid,
          name: chatProvider.pubnubConfig.uuid,
          avatarURL: URL(string: "https://picsum.photos/seed/\(chatProvider.pubnubConfig.uuid)/200")
        )
        
        // Create a channel object
        let channel = PubNubChatChannel(
          id: channelId,
          name: channelId,
          type: "direct",
          avatarURL: URL(string: "https://picsum.photos/seed/\(channelId)/200")
        )
        
        // Create a membership between the User and the Channel for subscription purposes
        let membership = PubNubChatMember(channel: channel, member: user)
        
        // Subscribe to the channel
        chatProvider.pubnubProvider.subscribe(.init(channels: [channelId], withPresence: true))
        
        // Fill database with the user, channel, and memberships data
        chatProvider.dataProvider.load(members: [membership])
      }

At the bottom of  “override func viewDidLoad()” add the following code to create a new chat provider and call the function to load data:

        // Create a new ChatProvider
        let provider = PubNubChatProvider(
        pubnubConfiguration: pubnubConfiguration
        )
        // Preload Data
        preloadData(provider)
        // Assign for future use
        chatProvider = provider

We also need to update the provider with new channels when the user changes location. In the function “updateInterfaceWith()” add the following inside “DispatchQueue.main.async”:

            self.channelId = weather.cityName
            if let provider = self.chatProvider {
                self.preloadData(provider) // Update chat provider with new channel data
              }

Your entire “ViewController.swift” file should now look like this:

import UIKit
import CoreLocation
import PubNub
import PubNubChat
import PubNubChatComponents

class ViewController: UIViewController {
    var chatProvider: PubNubChatProvider?
    var channelId = "San Francisco" // Default channel
    var chatView: UIView!
    
    // Create PubNub Configuration
    lazy var pubnubConfiguration = {
      return PubNubConfiguration(
        publishKey: PUBNUB_PUBLISH_KEY, // see Constants.swift to set PubNub API keys
        subscribeKey: PUBNUB_SUBSCRIBE_KEY,
        uuid: randomString(length: 6)
      )
    }()
    
    func randomString(length: Int) -> String { // Used to create a random username/uuid for chat
      let letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
      return String((0..<length).map{ _ in letters.randomElement()! })
    }
    
    @IBOutlet weak var weatherIconImageView: UIImageView!
    @IBOutlet weak var cityLabel: UILabel!
    @IBOutlet weak var temperatureLabel: UILabel!
    @IBOutlet weak var feelsLikeTemperatureLabel: UILabel!
    
    var networkWeatherManager = NetworkWeatherManager()
    lazy var locationManager: CLLocationManager = {
        let lm = CLLocationManager()
        lm.delegate = self
        lm.desiredAccuracy = kCLLocationAccuracyKilometer
        lm.requestWhenInUseAuthorization()
        return lm
    }()
   
    @IBAction func searchPressed(_ sender: UIButton) {
        self.presentSearchAlertController(withTitle: "Enter city name", message: nil, style: .alert) { [unowned self] city in
            self.networkWeatherManager.fetchCurrentWeather(forRequestType: .cityName(city: city))
        }
    }
    
    @IBAction func startChat(_ sender: UIButton) { // Show chat for current city / location
        chatView=UIView(frame: self.view.bounds)

        // PubNub.log.levels = [.all]
        // PubNub.log.writers = [ConsoleLogWriter()]
        
        guard let messageListViewModel = try! chatProvider?.messageListComponentViewModel(pubnubChannelId: channelId) else {
           preconditionFailure("Could not create intial view models")
        }
        
        let navigation = UINavigationController()
        navigation.viewControllers = [messageListViewModel.configuredComponentView()]
    
        self.show(navigation, sender: nil)
    }
    
    func preloadData(_ chatProvider: PubNubChatProvider) {
        // Create a user object with UUID
        let user = PubNubChatUser(
          id: chatProvider.pubnubConfig.uuid,
          name: chatProvider.pubnubConfig.uuid,
          avatarURL: URL(string: "https://picsum.photos/seed/\(chatProvider.pubnubConfig.uuid)/200")
        )
        
        // Create a channel object
        let channel = PubNubChatChannel(
          id: channelId,
          name: channelId,
          type: "direct",
          avatarURL: URL(string: "https://picsum.photos/seed/\(channelId)/200")
        )
        
        // Create a membership between the User and the Channel for subscription purposes
        let membership = PubNubChatMember(channel: channel, member: user)
        
        // Subscribe to the channel
        chatProvider.pubnubProvider.subscribe(.init(channels: [channelId], withPresence: true))
        
        // Fill database with the user, channel, and memberships data
        chatProvider.dataProvider.load(members: [membership])
      }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        networkWeatherManager.onCompletion = { [weak self] currentWeather in
            guard let self = self else { return }
            self.updateInterfaceWith(weather: currentWeather)
        }
        
        if CLLocationManager.locationServicesEnabled() {
            locationManager.requestLocation()
        }
        
        // Create a new ChatProvider
        let provider = PubNubChatProvider(
        pubnubConfiguration: pubnubConfiguration
        )
        // Preload Data
        preloadData(provider)
        // Assign for future use
        chatProvider = provider

    }
    
    func updateInterfaceWith(weather: CurrentWeather) {
        DispatchQueue.main.async {
            self.channelId = weather.cityName
            if let provider = self.chatProvider {
                self.preloadData(provider) // Update chat provider with new channel data
              }
            self.cityLabel.text = weather.cityName
            self.temperatureLabel.text = weather.temperatureString
            self.feelsLikeTemperatureLabel.text = weather.feelsLikeTemperatureString
            self.weatherIconImageView.image = UIImage(systemName: weather.systemIconNameString)
        }
    }
}

// MARK: - CLLocationManagerDelegate

extension ViewController: CLLocationManagerDelegate {
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        guard let location = locations.last else { return }
        let latitude = location.coordinate.latitude
        let longitude = location.coordinate.longitude
        
        networkWeatherManager.fetchCurrentWeather(forRequestType: .coordinate(latitude: latitude, longitude: longitude))
    }
    
    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
        print(error.localizedDescription)
    }
}

The next step is to create a button to show the chat UIView and link it to the “startChat” function. 

Open “Main.storyboard”. Duplicate the search button in the view (or make a new button), change the icon to “paperplane.circle”, and position the button where you want to. You should now have something that looks like this:

ios components Screen Shot 2

Switch to the Connections inspection (last tab on the right) and remove the link on “Touch Up Inside” if you duplicated the search button. Add a second editor and open ‘View Controllers > ViewController.swift’. Create a new link between “Touch Up Inside” and the “startChat” function by dragging from the empty circle beside “Touch Up Inside” to the “startChat” function.

ios components Screen Shot 3
Linking ibaction to button

[Optional step] Uncomment the following lines in “ViewController.swift” to see PubNub publish events, subscribes, and messages moving through the network:

// PubNub.log.levels = [.all]
// PubNub.log.writers = [ConsoleLogWriter()]

Start the app in the simulator. Allow location or search for a location. Click the chat icon to open the chat window and start chatting!

ios components screenshot 6

ios components screenshot 5

What’s Next with iOS Chat Components

In this tutorial we took a look at how PubNub iOS Chat Components can be implemented in an existing app and we configured and started customizing the iOS Chat Components.

The complete Weather-Chat app with PubNub iOS Chat Components can be found in this repo. In the complete app we’ve done everything in this tutorial and refactored the app to follow best Swift practices so that you can see how you would expand further.

With PubNub iOS chat components you can build chat in a way that’s customized perfectly for your needs. PubNub provides a real-time publish/subscribe messaging API built on a global network. PubNub has multiple points of presence on every inhabited continent, supports dozens of SDKs, and has lots of features you’ll need in a chat application use case.

PubNub iOS Chat Components make a great starting point to build chat that you can customize to your exact needs. There isn’t any one size fits all Chat Components solution, but PubNub iOS Chat Components offer the most popular chat functionality that we have seen developers implement.

Use PubNub to build features into your application like:

Need some assistance modifying or building with iOS Chat Components? Get in touch with our sales team and we’ll help you get started.

More from PubNub

Comparing Game Engines: Unity vs Unreal vs the Rest
Real-Time Gaming BlogSep 21, 20225 min read

Comparing Game Engines: Unity vs Unreal vs the Rest

Comparing the major game engines: Unity vs Unreal Engine vs Corona SDK vs GameMaker Studio, including the benefits and cons of...

PubNub Staff

PubNub Staff

Python Socket Programming: Client, Server and Peer Libraries
BuildSep 21, 20226 min read

Python Socket Programming: Client, Server and Peer Libraries

Sockets (aka socket programming) enable programs to send and receive data, bi-directionally, at any given moment. This tutorial...

PubNub Staff

PubNub Staff

Node.js WebSocket Programming Examples
BuildSep 21, 20226 min read

Node.js WebSocket Programming Examples

An overview and examples of basic socket and WebSocket programming with Node.js.

PubNub Staff

PubNub Staff