Messaging UI components

Integrate Nabla Messaging UI components into your app

The NablaMessagingUI library is compatible with iOS 13 and higher, but some features will only be available from iOS 14 and higher:

  • selecting multiple images at once from the library.
  • uploading document from the Files app on users' phone.


This guide assumes that you want to use Nabla's built-in UI components to build your messaging experience. If you're interesting in getting only the data and build your own UI, follow our Core SDK guide.

Conversations list

Once the user is authenticated in your app, you can access their conversations and display them. Be sure to import NablaMessagingUI for Xcode to find the definition of NablaViewFactory.

To display the list of conversations your user is a part of, the Nabla SDK provides a NablaViewFactory.createConversationListView method that returns a ConversationListView.

Simply include it in your view or view controller:

Preview of the conversations list UI componentPreview of the conversations list UI component

import NablaMessagingCore
import NablaMessagingUI
import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {

        let conversationListView = NablaClient.shared.messaging.views.createConversationListView(delegate: self)


extension ViewController: ConversationListDelegate {
    func conversationList(didSelect conversation: Conversation) {
        print("User did select \(")

ConversationListView encompasses a scrollable list of all conversations, along with UI for loading and error states. The scrolling in the list is wired with a paginated loading of conversations.

Conversation screen

Preview of the conversations list UI componentPreview of the conversations list UI component

It's up to you to decide what to do when a user taps a conversation by implementing ConversationListDelegate.conversationList(didSelect:).

Usually, you will want to "open" this conversation by pushing a new screen. Change the implementation of ConversationListDelegate to be as follow:

extension ViewController: ConversationListDelegate {
    func conversationList(didSelect conversation: Conversation) {
        let destination = NablaClient.shared.messaging.views.createConversationViewController(conversation)
        navigationController?.pushViewController(destination, animated: true)

The ConversationViewController contains:

  • The timeline of conversation’s content, i.e. messages, with a pagination mechanism.
  • The composer where to type a new message or send media attachments.
  • A default navigationItem.titleView with the conversation image and title.

This screen allows users to:

  • Receive:
    • A typing indicator
    • Text messages
    • Images messages (and open them fullscreen)
    • Document messages (and open them fullscreen)
    • Voice messages (and play them)
  • Send:
    • A text message
    • An images message
    • A PDF document message (with files already existing on their device)
    • Voice messages (to record with their microphone)
  • Act on messages:
    • Delete (only their own messages)

Using the camera to send photos

In order for users to use the camera to send photo messages, you must fill your info.plist with the key NSCameraUsageDescription, otherwise the option won't show.

Setting up voice messages

In order to make the recording of voice messages work, you must fill your info.plist with the key NSMicrophoneUsageDescription, otherwise a crash might occur.

Create a new conversation

If you want your user to be able to start a new conversation, you can allow to create it into your app directly:

NablaMessagingClient.shared.createConversation() { result ->
  switch result {
    case let .success(conversation):
      print("User has a new conversation")
    case let .error(error):
      print("Error \(error)")

Lazy conversation creation

You can also opt for a lazy conversation creation (i.e. delaying the creation of the conversation until it's necessary) by using createDraftConversation(..). You can notice it does not return a Cancellable as it makes no network call.

Draft conversations are local on-device and will not be effectively created on console-side until the user successfully sends their first message. This way, you can avoid having meaningless empty conversations.

Since createDraftConversation(..) does return a Conversation just like createConversation(..), you can seamlessly use the returned id as argument for operations like watchConversationItems(..), sendMessage(..) or retrySendingMessage(..).

Did this page help you?