Brand Messenger iOS SDK Conversation

Understand how you can initiate or launch a chat with an agent in iOS

Before we begin, make sure you have added all of the permissions as mentioned in the Add Permissions section of our Installation guide.

Initiating a chat

Implement the following code at the event or Button action designated to the conversation screen. This will launch the Chat screen.

BrandMessengerManager.show(self)
[BrandMessengerManager show:self];

If the environment is also configured with Welcome-Messages, the following can be used instead of `show(self). This will also send an API request to give the user a welcome-message.

BrandMessengerManager.showWithWelcome(vc:UIViewController?)

To just send the welcome-message API request without displaying the conversation screen, use the following

BrandMessengerManager.sendWelcomeMessageRequest { response, error in }

Intercepting Message Actions from SDK Conversation Screen

Message actions from the build-in KBMConversationViewController, such as tapping on link-buttons, can be intercepted by setting a KBMConversationViewControllerDelegate and handled outside of the SDK.

BrandMessengerManager.setMessageActionDelegate(self)
...
// Return false to let SDK handle action. Return true to handle it here.
func handleMessageAction(index: Int?, title: String?, message: KBMMessageViewModel?, cardTemplate: CardTemplate?, listAction: ListTemplate.Action?, isButtonDisabled: Bool?) -> Bool {
// There are many types of rich messages, which can return an action type 'link' to open URL.
// Below is an example to parse cardTemplate (either in single card, or card-carousel) and link-button for URLs.
    if let message = message {
        if message.messageType == .cardTemplate {
            if let index = index, let selectedButton = cardTemplate?.buttons?[index] {
                if selectedButton.action?.type == "link" {
                    let url = selectedButton.action?.payload?.url
                    print("URL on CardTemplate: \(url)")
                    return true
                }
            }
        }
        if message.messageType == .button {
            if let index = index,
               let payload = message.payloadFromMetadata()?[index],
               let type = payload["type"] as? String {
                if type == "link" {
                    let url = payload["url"]
                    print("\(url)")
                    return true
                }
            }
        }
    }
    return false;
}
//KBMConversationViewControllerDelegate cannot be used in Objective-C.

Choosing persistent or temporary storage for the conversation

Customer can switch between using persistent and temporary database for conversation data.
Default is temporary (false).
KBMUserDefaultsHandler.setUsePersistentMessagesStorage(false)

Choosing if messages should refresh on every chat screen open

The SDK fetches the latest message every time the chat-screen is opened.
This functionality can be enabled/disabled.
When disabled, new messages will only be fetched in the event where a push-notification for a new message is received, or a mqtt connection message arrives alerting the sdk of a new message.
Default is enabled (true).
KBMUserDefaultsHandler.setFetchNewOnChatOpen(true)

Detecting Conversation screen lifecycle events

When the BrandMessenger UI framework's conversation screen is used, the following can be implemented to catch when the view appears or disappears.

// viewWillAppear
NotificationCenter.default.addObserver(self, selector: #selector(sel), name: NSNotification.Name(rawValue: "KBMConversationViewController.viewWillAppear"), object: nil)

// viewDidAppear
NotificationCenter.default.addObserver(self, selector: #selector(sel), name: NSNotification.Name(rawValue: "KBMConversationViewController.viewDidAppear"), object: nil)

// viewWillDisappear
NotificationCenter.default.addObserver(self, selector: #selector(sel), name: NSNotification.Name(rawValue: "KBMConversationViewController.viewWillDisappear"), object: nil)

// viewDidDisappear
NotificationCenter.default.addObserver(self, selector: #selector(sel), name: NSNotification.Name(rawValue: "KBMConversationViewController.viewDidDisappear"), object: nil)

The conversation screen's back-button tap event can also be captured.

NotificationCenter.default.addObserver(self, selector: #selector(sel), name: NSNotification.Name(rawValue: "KBMConversationViewController.backTapped"), object: nil)

Save video to gallery

If you want to save the downloaded and captured videos to the gallery(Photos album) then use the below setting to enable it:

[BrandMessengerSettings enableSaveVideosToGallery:YES]
BrandMessengerSettings.enableSaveVideosToGallery(flag: true)

Understanding KBMMessage properties

Checking received message or sent message

if ([message.type isEqualToString:KBM_IN_BOX]) {
   // Received  message 
} else {
   // Sent message 
}
if (message.type == "4") {
    // Received  message
} else {
    // Sent message
}

Checking message content type

You can differentiate between different content types, such as text, location, attachment, contact cards, videos, etc.

if (message.isLocationMessage) {
     //Location message contentType
} else if (message.isContactMessage) {
      // Contact card attachement contentType
} else if (message.fileMeta) {
        if([message.fileMeta.contentType hasPrefix:@"image"]) {
            // Image attachemnt message contentType
      NSString *filePath =  message.imageFilePath; if its downloaded you can get the path 
        } else if ([message.fileMeta.contentType hasPrefix:@"video"]) {
            // Video message contentType
        } else if ([message.fileMeta.contentType hasPrefix:@"audio"]) {
            // Audio message contentType
        }
} else if (message.contentType == KBMMESSAGE_CONTENT_DEFAULT)  {
        //Message text contentType
} else if (message.contentType == KBMMESSAGE_CHANNEL_NOTIFICATION) {
        //Custom message like addedd,removed,created,changed name of channel
}
if (message.isLocationMessage()) {
      //Location message contentType
}  else if (message.isContactMessage()) {
      // Contact card attachement contentType
} else if ((message.fileMeta) != nil) {
          if message.fileMeta.contentType?.hasPrefix("image") ?? false {
                // Image attachemnt message contentType
                  let filePath = message.imageFilePath //if its downloaded you can get the path               
            } else if message.fileMeta.contentType?.hasPrefix("video") ?? false {
                // Video message contentType
             let filePath = message.imageFilePath //if its downloaded you can get the path 
            } else if message.fileMeta.contentType?.hasPrefix("audio") ?? false {
                // Audio message contentType
                let filePath = message.imageFilePath //if its downloaded you can get the path 
            }
 } else if message.contentType == KBMMESSAGE_CONTENT_DEFAULT {
       // Message text contentType
 }

📘

NOTE:

There are no separate content types for image, video, audio, etc.

These messages come under message.isDocumentMessage() and you can check them for the image, video, or audio prefix.

To get the message text from KBMMessage:

message.message

Checking status of the message

For checking the status of the message. These include messages that have been sent to the server, delivered to the user, and delivered and read.

Here is an example:

switch (message.status.intValue) {
            case DELIVERED_AND_READ :
            {
                //Sent message update the ui with read tick
            }
            break;
                
            case DELIVERED:
            {
                //Sent message update the UI with Deliverd tick
            }
            break;
          
            case SENT:
            {
                //Sent message update the UI with sent tick
            }
            break;
          
            default:
						// Pending state
            break;
 }
switch message.status {
     case DELIVERED_AND_READ:
        //Sent message update the ui with read tick
     case DELIVERED:
        //Sent message update the UI with Deliverd tick
      case SENT:
        //Sent message update the UI with sent tick
      default:
      // Pending state
       break
 }

Location message JSON parsing

You can parse the location message and show it in stack map view:

NSData *objectData = [message.message dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *jsonStringDic = [NSJSONSerialization JSONObjectWithData:objectData
                               options:NSJSONReadingMutableContainers
                               error:&error];
  
NSArray* latLog = [[NSArray alloc] initWithObjects:[jsonStringDic valueForKey:@"lat"],[jsonStringDic valueForKey:@"lon"], nil];

NSString *latLongArgument = [NSString stringWithFormat:@"%@,%@", latLog[0], latLog[1]];
let objectData: Data? = message.message.data(using: String.Encoding.utf8.rawValue)
 var jsonStringDic: [AnyHashable : Any]? = nil
    if let aData = objectData {
            jsonStringDic = try? JSONSerialization.jsonObject(with: aData, options: .mutableContainers) as? [AnyHashable : Any]
     }
 let latLog = [jsonStringDic?["lat"], jsonStringDic?["lon"]]

 let latLongArgument = "\(latLog[0]),\(latLog[1])"