# Use in-meeting chat > The code on this page works with either the **default UI** or the **custom UI**. The Meeting SDK lets you [use in-meeting chat](https://support.zoom.com/hc/en/article?id=zm_kb&sysparm_article=KB0064400) to communicate with other participants in the same meeting. Handle chat functionality through the `InMeetingChatController` interface. ```swift if let meetingChatController = ZoomSDK.shared().getMeetingService()?.getMeetingChatController() { } ``` ```objectivec ZoomSDKMeetingChatController *meetingChatController = [[[ZoomSDK sharedSDK] getMeetingService] getMeetingChatController]; if (meetingChatController) { } ``` ## Control chat settings Before you use in-meeting chat, check if the current meeting or webinar supports chat, and then look at which participants or attendees can use chat. ### Chat settings in a meeting In a meeting, use ZoomSDKMeetingActionController. ```swift if let meetingActionCtrl = ZoomSDK.shared().getMeetingService()?.getMeetingActionController() { if meetingActionCtrl.isParticipantsChatAllowed() { } // OR for more breakdown if let normalMeetingPrivilege = meetingActionCtrl.getChatStatus()?.getNormalMeetingPrivilege() { normalMeetingPrivilege.canChat normalMeetingPrivilege.canChatToAll normalMeetingPrivilege.canChatToIndividual normalMeetingPrivilege.isOnlyCanChatToHost } } ``` ```objectivec ZoomSDKMeetingActionController *meetingActionCtrl = [[[ZoomSDK sharedSDK] getMeetingService] getMeetingActionController]; if (meetingActionCtrl) { if (meetingActionCtrl.isParticipantsChatAllowed) { } // OR for more breakdown ZoomSDKNormalMeetingChatPrivilege *normalMeetingPrivilege = [[meetingActionCtrl getChatStatus] getNormalMeetingPrivilege]; if (normalMeetingPrivilege) { normalMeetingPrivilege.canChat; normalMeetingPrivilege.canChatToAll; normalMeetingPrivilege.canChatToIndividual; normalMeetingPrivilege.isOnlyCanChatToHost; } } ``` The `ZoomSDKNormalMeetingChatPrivilege` has these values. - `canChat` - The user may use chat to send both private and public messages. - `canChatToAll` - The user may use chat, but private messages are not allowed. - `canChatToIndividual` - The user may use chat only to individual user. - `isOnlyCanChatToHost` - The user may use chat only to host. If the current user is the meeting's host, they can control chat settings by specifying a `ZoomSDKChatPrivilegeType`. ```swift meetingActionCtrl.setParticipantsChatPrivilege(ZoomSDKChatPrivilegeType_To_Everyone) meetingActionCtrl.setParticipantsChatPrivilege(ZoomSDKChatPrivilegeType_To_Host) meetingActionCtrl.setParticipantsChatPrivilege(ZoomSDKChatPrivilegeType_Disable_Attendee_Chat) meetingActionCtrl.setParticipantsChatPrivilege(ZoomSDKChatPrivilegeType_Host_Public) ``` ```objectivec [meetingActionCtrl setParticipantsChatPrivilege: ZoomSDKChatPrivilegeType_To_Everyone]; [meetingActionCtrl setParticipantsChatPrivilege: ZoomSDKChatPrivilegeType_To_Host]; [meetingActionCtrl setParticipantsChatPrivilege: ZoomSDKChatPrivilegeType_Disable_Attendee_Chat]; [meetingActionCtrl setParticipantsChatPrivilege: ZoomSDKChatPrivilegeType_Host_Public]; ``` ### Chat settings in a webinar In a webinar, use `ZoomSDKMeetingActionController` or `ZoomSDKWebinarController`. ```swift if let webinarCtrl = ZoomSDK.shared().getMeetingService()?.getWebinarController() { // Attendee - ZoomSDKWebinarController doesn't seem to have a getAttendeeChatPriviledge and only has getPanelistChatPrivilege // Panelist var panelistChatPriviledge: ZoomSDKPanelistChatPrivilege = ZoomSDKPanelistChatPrivilege_PanelistOnly if webinarCtrl.getPanelistChatPrivilege(&panelistChatPriviledge) == ZoomSDKError_Success { switch panelistChatPriviledge { case ZoomSDKPanelistChatPrivilege_PanelistOnly: // Allow panelists only to chat with each other return case ZoomSDKPanelistChatPrivilege_All: // Allow panelist to chat with everyone return default: // There won't be a default case return } } } // OR for more breakdown if let meetingActionCtrl = ZoomSDK.shared().getMeetingService()?.getMeetingActionController() { // Attendee if let webinarAttendeeChatPrivilege = meetingActionCtrl.getChatStatus()?.getWebinarAttendeePrivilege() { webinarAttendeeChatPrivilege.canChat webinarAttendeeChatPrivilege.canChatToAllPanellist webinarAttendeeChatPrivilege.canChatToAllPanellistAndAttendee } // Panelist if let webinarPanelistChatPrivilege = meetingActionCtrl.getChatStatus()?.getWebinarPanelistPrivilege() { webinarPanelistChatPrivilege.canChatToIndividual webinarPanelistChatPrivilege.canChatToAllPanellist webinarPanelistChatPrivilege.canChatToAllPanellistAndAttendee } } ``` ```objectivec ZoomSDKWebinarController *webinarCtrl = [[[ZoomSDK sharedSDK] getMeetingService] getWebinarController]; if (webinarCtrl) { // Attendee - ZoomSDKWebinarController doesn't seem to have a getAttendeeChatPriviledge and only has getPanelistChatPrivilege // Panelist ZoomSDKPanelistChatPrivilege panelistChatPriviledge = ZoomSDKPanelistChatPrivilege_PanelistOnly; if ([webinarCtrl getPanelistChatPrivilege:&panelistChatPriviledge] == ZoomSDKError_Success) { switch (panelistChatPriviledge) { case ZoomSDKPanelistChatPrivilege_PanelistOnly: return; case ZoomSDKPanelistChatPrivilege_All: // Allow panelists to chat with everyone return; default: // There won't be a default case return; } } } // OR for more breakdown ZoomSDKMeetingActionController *meetingActionCtrl = [[[ZoomSDK sharedSDK] getMeetingService] getMeetingActionController]; if (meetingActionCtrl) { // Attendee ZoomSDKWebinarAttendeeChatPrivilege *webinarAttendeeChatPrivilege = [[meetingActionCtrl getChatStatus] getWebinarAttendeePrivilege]; if (webinarAttendeeChatPrivilege) { webinarAttendeeChatPrivilege.canChat; webinarAttendeeChatPrivilege.canChatToAllPanellist; webinarAttendeeChatPrivilege.canChatToAllPanellistAndAttendee; } // Panelist ZoomSDKWebinarPanelistChatPrivilege *webinarPanelistChatPrivilege = [[meetingActionCtrl getChatStatus] getWebinarPanelistPrivilege]; if (webinarPanelistChatPrivilege) { webinarPanelistChatPrivilege.canChatToIndividual; webinarPanelistChatPrivilege.canChatToAllPanellist; webinarPanelistChatPrivilege.canChatToAllPanellistAndAttendee; } } ``` The `ZoomSDKWebinarAttendeeChatPrivilege` uses one of these values. - `canChat` - Attendee can send message to chat. - `canChatToAllPanellist` - Can send message to all the panelists. - `canChatToAllPanellistAndAttendee` - Can send message to all the panelists and attendees. The `ZoomSDKWebinarPanelistChatPrivilege` uses one of these values. - `canChatToIndividual` - Can send message to individual attendee. - `canChatToAllPanellist` - Can send message to all the panelists. - `canChatToAllPanellistAndAttendee` - Can send message to all. Update a webinar's chat settings by setting a `ZoomSDKChatPrivilegeType`. ```swift meetingActionCtrl.setParticipantsChatPrivilege(ZoomSDKChatPrivilegeType_To_Everyone) meetingActionCtrl.setParticipantsChatPrivilege(ZoomSDKChatPrivilegeType_To_All_Panelist) meetingActionCtrl.setParticipantsChatPrivilege(ZoomSDKChatPrivilegeType_Disable_Attendee_Chat) ``` ```objectivec [meetingActionCtrl setParticipantsChatPrivilege: ZoomSDKChatPrivilegeType_To_Everyone]; [meetingActionCtrl setParticipantsChatPrivilege: ZoomSDKChatPrivilegeType_To_All_Panelist]; [meetingActionCtrl setParticipantsChatPrivilege: ZoomSDKChatPrivilegeType_Disable_Attendee_Chat]; ``` ## Send messages To send a public message in either a meeting or a webinar, instantiate a `ChatMessageBuilder` and set the content and message type. ```swift if let meetingChatController = ZoomSDK.shared().getMeetingService()?.getMeetingChatController() { let chatMsgInfoBuilder = ZoomSDKChatMsgInfoBuilder() /* Receiver (userID parameter) - For sending to all or all panelist: 0 For sending to a specific user: the user's userID MessageType (ZoomSDKChatMessageType) - ZoomSDKChatMessageType_To_All - Meeting = to everyone or Webinar = to all panelist and attendees ZoomSDKChatMessageType_To_All_Panelist - Webinar = to all panelists ZoomSDKChatMessageType_To_Individual_Panelist - Webinar = to individual panelist ZoomSDKChatMessageType_To_Individual - To individual user */ chatMsgInfoBuilder.setContent("Hello World!").setReceiver(0).setMessageType(ZoomSDKChatMessageType_To_All) let chatInfo = chatMsgInfoBuilder.build() meetingChatController.sendChatMsg(to: chatInfo) } ``` ```objectivec ZoomSDKMeetingChatController *meetingChatController = [[[ZoomSDK sharedSDK] getMeetingService] getMeetingChatController]; if (meetingChatController) { ZoomSDKChatMsgInfoBuilder *chatMsgInfoBuilder = [[ZoomSDKChatMsgInfoBuilder alloc] init]; /* Receiver (userID parameter) - For sending to all or all panelist: 0 For sending to a specific user: the user's userID MessageType (ZoomSDKChatMessageType) - ZoomSDKChatMessageType_To_All - Meeting = to everyone or Webinar = to all panelist and attendees ZoomSDKChatMessageType_To_All_Panelist - Webinar = to all panelists ZoomSDKChatMessageType_To_Individual_Panelist - Webinar = to individual panelist ZoomSDKChatMessageType_To_Individual - To individual user */ [[[chatMsgInfoBuilder setContent:@"Hello World!"] setReceiver:0] setMessageType:ZoomSDKChatMessageType_To_All]; ZoomSDKChatInfo *info = [chatMsgInfoBuilder build]; ZoomSDKError error = [meetingChatController sendChatMsgTo:info]; } ``` To reply to an existing message in a thread, first get a `threadId` for the message being responded to. For more information on how to get the `threadId`, see [Receive messages](#receive-messages). Once you've retrieved the thread ID, pass it in and set the type based on whether the parent message is public or private. ```swift if let meetingChatController = ZoomSDK.shared().getMeetingService()?.getMeetingChatController() { // 1. Identify the message (ZoomSDKChatInfo) you want to reply to and get its threadID let chatInfo: ZoomSDKChatInfo? = nil guard let chatInfo = chatInfo else { return } let threadID = chatInfo.getThreadID() // 2. Build ZoomSDKChatMsgInfoBuilder with threadID let threadReplyMessage = ZoomSDKChatMsgInfoBuilder().setThreadId(threadID).setContent("Reply to Hello World!").setMessageType(ZoomSDKChatMessageType_To_All).build() // 3. Send reply message meetingChatController.sendChatMsg(to: threadReplyMessage) } ``` ```objectivec ZoomSDKMeetingChatController *meetingChatController = [[[ZoomSDK sharedSDK] getMeetingService] getMeetingChatController]; if (meetingChatController) { // 1. Identify the message (ZoomSDKChatInfo) you want to reply to and get its threadID ZoomSDKChatInfo *chatInfo = nil; if (!chatInfo) { return; } NSString *threadID = chatInfo.getThreadID; // 2. Build ZoomSDKChatMsgInfoBuilder with threadID ZoomSDKChatMsgInfoBuilder *chatMsgInfoBuilder = [[ZoomSDKChatMsgInfoBuilder alloc] init]; ZoomSDKChatInfo *threadReplyMessage = [[[[chatMsgInfoBuilder setThreadId:threadID] setContent:@"Reply to Hello World!"] setMessageType:ZoomSDKChatMessageType_To_All] build]; // 3. Send reply message ZoomSDKError error = [meetingChatController sendChatMsgTo:threadReplyMessage]; } ``` Messages sent from the SDK can also include quoted text. The quote position specifies the start and end characters in the quoted text string. ```swift if let meetingChatController = ZoomSDK.shared().getMeetingService()?.getMeetingChatController() { // Using positionStart as 0 and positionEnd as 42 as an example let quoteMessage = ZoomSDKChatMsgInfoBuilder().setQuotePosition(0, positionEnd: 42).setContent("This is a sample message stylized as a quote").setMessageType(ZoomSDKChatMessageType_To_All).build() meetingChatController.sendChatMsg(to: quoteMessage) } ``` ```objectivec ZoomSDKMeetingChatController *meetingChatController = [[[ZoomSDK sharedSDK] getMeetingService] getMeetingChatController]; if (meetingChatController) { // Using positionStart as 0 and positionEnd as 42 as an example ZoomSDKChatMsgInfoBuilder *chatMsgInfoBuilder = [[ZoomSDKChatMsgInfoBuilder alloc] init]; ZoomSDKChatInfo *quoteMessage = [[[[chatMsgInfoBuilder setQuotePosition:0 positionEnd:42] setContent:@"This is a sample message stylized as a quote"] setMessageType:ZoomSDKChatMessageType_To_All] build]; ZoomSDKError error = [meetingChatController sendChatMsgTo:quoteMessage]; } ``` ## Receive messages To display content from chat messages, the SDK provides a callback to get notified of when a new message is sent to the meeting. You can also use this callback to confirm that a message sent by the current user has successfully been posted to the meeting chat. Confirm to the `ZoomSDKMeetingChatControllerDelegate` protocol first, then use the `chatInfo` parameter within `onChatMessageNotification` to get information about the chat message. Some data, like `receiverID`, will only be available for specific types of messages. ```swift if let meetingChatController = ZoomSDK.shared().getMeetingService()?.getMeetingChatController() { meetingChatController.delegate = self } func onChatMessageNotification(_ chatInfo: ZoomSDKChatInfo) { chatInfo.getMessageID() // A unique identifier assigned to this message. chatInfo.getMsgContent() // The content of the message that is visible to users in the meeting. chatInfo.getTimeStamp() // The time at which the message was sent. chatInfo.getSenderUserID() // The Zoom user ID of the user who sent the message. chatInfo.getSenderDisplayName() // The display name of the user who sent the message. chatInfo.getReceiverUserID() // The Zoom user ID of the user on the receiving end of a private message. chatInfo.getReceiverDisplayName() // The display name of the user on the receiving end of a private message. chatInfo.isChatToWaitingRoom() // Whether the message was sent to the waiting room. chatInfo.getChatMessageType() // The message type, see "ZoomSDKChatMessageType". chatInfo.isComment() // Whether the chat message is a comment responding to a thread. chatInfo.isThread() // Whether the chat message is a thread with comments. chatInfo.getThreadID() // The unique identifier associated with a thread chatInfo.getSegmentDetails() // Get the detailed attributes such as bold, italic, strikethrough and more. } ``` ```objectivec // In your .h file @interface ZMSDKWindow : NSWindowController { } // In your .m file - (void)onChatMessageNotification:(ZoomSDKChatInfo *)chatInfo { [chatInfo getMessageID]; // A unique identifier assigned to this message. [chatInfo getMsgContent]; // The content of the message that is visible to users in the meeting. [chatInfo getTimeStamp]; // The time at which the message was sent. [chatInfo getSenderUserID]; // The Zoom user ID of the user who sent the message. [chatInfo getSenderDisplayName]; // The display name of the user who sent the message. [chatInfo getReceiverUserID]; // The Zoom user ID of the user on the receiving end of a private message. [chatInfo getReceiverDisplayName]; // The display name of the user on the receiving end of a private message. [chatInfo isChatToWaitingRoom]; // Whether the message was sent to the waiting room. [chatInfo getChatMessageType]; // The message type, see "ZoomSDKChatMessageType". [chatInfo isComment]; // Whether the chat message is a comment responding to a thread. [chatInfo isThread]; // Whether the chat message is a thread with comments. [chatInfo getThreadID]; // The unique identifier associated with a thread [chatInfo getSegmentDetails]; // Get the detailed attributes such as bold, italic, strikethrough and more. } ``` ## Delete messages To delete a message sent by the current user, call the `deleteChatMessage` method under `ZoomSDKMeetingActionController` with the `msgId`. This will trigger the `onChatMsgDeleteNotification` callback under `ZoomSDKMeetingActionControllerDelegate` ```swift if let meetingActionController = ZoomSDK.shared().getMeetingService()?.getMeetingActionController() { let msgID: String = "" if meetingActionController.isChatMessageCanBeDeleted(msgID) { meetingActionController.deleteChatMessage(msgID) } } ``` ```objectivec - (void) deleteMessage { ZoomSDKMeetingActionController *meetingActionController = [[[ZoomSDK sharedSDK] getMeetingService] getMeetingActionController]; if (meetingActionController) { NSString *msgID = @""; if ([meetingActionController isChatMessageCanBeDeleted:msgID]) { [meetingActionController deleteChatMessage:msgID]; } } } ``` ## Parse text format The SDK supports receiving various styles of chat messages such as bold, italic, quote, font color and size, and many more. The styles are included as a list of `ZoomSDKChatMsgSegmentDetails` objects under each of the `ZoomSDKChatInfo` object. ```swift if let chatInfoSegmentDetails = chatInfo.getSegmentDetails() { for segment in chatInfoSegmentDetails { segment.strContent segment.boldAttrs segment.italicAttrs segment.underlineAttrs // and more } } ``` ```objectivec NSArray *chatInfoSegmentDetails = [chatInfo getSegmentDetails]; if (chatInfoSegmentDetails) { for (ZoomSDKChatMsgSegmentDetails *segment in chatInfoSegmentDetails) { [segment strContent]; [segment boldAttrs]; [segment italicAttrs]; [segment underlineAttrs]; // and more } } ``` ## Understanding all the chat callbacks For chat related callbacks, there are 2 delegates to subscribe to. Under `ZoomSDKMeetingActionControllerDelegate`, the callbacks are `onChatStatusChangedNotification` and `onChatMsgDeleteNotification`. Under `ZoomSDKMeetingChatControllerDelegate`, the callbacks are `onChatMessageNotification` and `onChatMessageEditNotification`. ---