PubNub Logo Docs
Support Contact Sales Login Try Our APIs

›IOS

Collapse all
Dark mode

Back to Home

Overview

  • In-App Chat

Chat Components

  • Overview
  • REACT

    • React Components

    ANDROID

    • Getting Started
    • UI Components
    • Data Components
    • Chat Provider

    IOS

    • Getting Started
    • UI Components
    • Data Components
    • Chat Provider

SDKs

  • Overview
  • USERS

    • Setup
    • Metadata
    • Permissions
    • Presence
    • Mentions

    CHANNELS

    • Types and Names
    • Metadata
    • Subscriptions
    • Memberships

    MESSAGES

    • Sending Messages
    • Message Storage
    • Unread Counts
    • File Upload
    • Typing Indicators
    • Read Receipts
    • Emoji Reactions
    • Update Messages
    • Delete Messages
    • Message Webhooks

    PUSH NOTIFICATIONS

    • Overview

    MODERATION

    • Profanity Filters
    • Flag Messages
    • Ban Users
    • Mute Users
    • Spam Prevention

    INTEGRATIONS

    • Overview
    • Content Moderation
    • Image Moderation
    • Language Translation
    • Chatbots
    • GIFs
    • Stickers

Moderation Dashboard

  • Overview
  • Getting Started
  • FEATURES

    • Automatic Text Moderation
    • Automatic Image Moderation
    • Manual Message Moderation
    • Manual User Moderation
    • User Management
    • Channel Management
  • Required Configuration

Debug Console
Network Status

UI components

PubNub Chat Components for iOS provide easy-to-use building blocks to create chat applications for various use cases with different functionalities and customizable looks.

Available components include:

  • ChannelList
  • MemberList
  • MessageList
  • MessageInput

Component theming

Default ThemeTemplate provides structural and appearance configurations for each component and its sub-components. Light and dark modes for each theme are supported automatically through adaptive elements based on the current system-wide appearance settings.

Most appearance properties use Combine to asynchronously update the corresponding bound View elements. You can access the shared ThemeTemplate through the themeProvider property of any ChatProvider instance.

ChannelList

UIViewController that displays a list of stored Channel objects. It can represent all channels of the application, only channels joined by the current user, all channels available to be joined, or any other type of NSFetchedResultsController made against stored channel data.

Parameters

You can initialize the ChannelList view model using the following parameters.

NameTypeDefault valueDescription
providerChatProvidern/aThe ChatProvider instance to be used inside this component.
fetchedEntitiesNSFetchedResultsControllern/aThe data type and query options used to populate the component.
componentThemeChannelListComponentTheme?The ChannelList theme sourced from ChatProvider.The configurable theme used for the component. If you provide a custom object, you must maintain it outside of ChatProvider.

View model

The view model is used to configure both the main UIViewController for the component, the channel data, and lay out any sub-components.

To override core functionality, you can either subclass the view model or implement override blocks to replace specific key functionalities.

The default ChannelListComponentViewModel is configured to display the default channel memberships of the current user, sorted by the type and name of the channel.

Component population

ChatProvider can be extended to return a configured NSFetchedResultsController, and this object ensures the component always displays the most recent data. NSFetchedResultsController can contain any type of stored data related to a channel, and can be sorted and sectioned based on any channel property.

Default example

By default, the list is populated by any channel of which the current user is a member. The list is divided into multiple sections based on the channel type, and each section is sorted by the name of the channel.

open func channelMembershipsFrom(
  userId: String, sectionedByType: Bool
) -> NSFetchedResultsController<ManagedEntities.Member> {

  let request = ManagedEntities.Member.membershipsBy(userId: userId)

  request.sortDescriptors = [
    NSSortDescriptor(key: "channel.type", ascending: false),
    NSSortDescriptor(key: "channel.name", ascending: true)
  ]
  request.relationshipKeyPathsForPrefetching = ["channel"]

  return fetchedResultsControllerProvider(
    fetchRequest: request,
    sectionKeyPath: sectionedByType ? "channel.type": nil,
    cacheName: nil
  )
}

You can create a view model composed of the above default NSFetchedResultsController and ChannelListComponentTheme using this ChatProvider extension method:

open func senderMembershipsChannelListComponentViewModel(
  sectionedByType: Bool = true,
  customTheme: ChannelListComponentTheme? = nil
) -> ChannelListComponentViewModel<ModelData, ManagedEntities> {
  return ChannelListComponentViewModel(
    provider: self,
    fetchedEntities: channelMembershipsFrom(userId: senderID, sectionedByType: sectionedByType),
    customTheme: customTheme ?? self.themeProvider.template.channelListComponent
  )
}

Properties

The ChannelList view model provides outlets for the following properties after initialization:

NameTypeDefault valueDescription
providerChatProvidern/aA ChatProvider instance to be used inside this component.
fetchedEntitiesNSFetchedResultsControllern/aThe data type and query options used to populate the component.
componentThemeChannelListComponentThemeThe ChannelList theme sourced from ChatProvider.The configurable theme used for the component.
leftBarButtonNavigationItems(UIViewController, ChannelListComponentViewModel) -> [UIBarButtonItem]nilViews that appear on the left side of the navigation bar.
rightBarButtonNavigationItems(UIViewController, ChannelListComponentViewModel) -> [UIBarButtonItem]nilViews that appear on the right side of the navigation bar.
customNavigationTitleView(ChannelListComponentViewModel) -> UIView?nilThe custom view that's used inside the navigation bar title.
customNavigationTitleString(ChannelListComponentViewModel) -> AnyPublisher<String?, Never>nilThe custom String publisher that's used inside the navigation bar title if a view isn't provided.
customChannelCellViewModel(ChannelListComponentViewModel, Channel) -> ChannelCellComponentViewModelnilThe cell view model that's be used instead of the default model found inside the theme.
configureFetchedResultsController(NSFetchedResultsController) -> VoidnilAn outlet to customize the channel data query before the data is fetched.

You can configure the message items inside the list with the data found inside ManagedChannelViewModel:

public protocol ManagedChannelViewModel {
  associatedtype Entity: ManagedChatChannel
  associatedtype MemberViewModel: ManagedMemberViewModel & Hashable
  associatedtype MessageViewModel: ManagedMessageViewModel & Hashable

  var pubnubId: String { get }
  var managedObjectId: NSManagedObjectID { get }

  var channelNamePublisher: AnyPublisher<String, Never> { get }
  var channelDetailsPublisher: AnyPublisher<String?, Never> { get }
  var channelAvatarUrlPublisher: AnyPublisher<URL?, Never> { get }
  var channelTypePublisher: AnyPublisher<String, Never> { get }
  var channelCustomPublisher: AnyPublisher<Data, Never> { get }

  var membershipPublisher: AnyPublisher<Set<MemberViewModel>, Never> { get }
  var memberCountPublisher: AnyPublisher<Int, Never> { get }
  var presentMemberCountPublisher: AnyPublisher<Int, Never> { get }

  var messagesPublisher: AnyPublisher<Set<MessageViewModel>, Never> { get }
  var oldestMessagePublisher: AnyPublisher<MessageViewModel?, Never> { get }
}

Theming

You can configure the ChannelListComponentTheme theme using the following parameters.

NameTypeAuto update on changeDescription
controllerTypeComponentViewControllerNoDefault class type that is used when creating new UIViewController instances.
backgroundColorUIColorYesView Controller’s background color.
navigationTitleViewBasicComponentTheme?YesTheming for UIView found on the UINavigationItem component.
collectionViewThemeCollectionViewComponentThemeYesTheming for UICollectionView found on the UIViewController component.
sectionHeaderLabelLabelComponentThemeYesTheming for UILabel you can attach to the UICollectionReusableView section Header-type.
cellThemeMemberListCellComponentThemeYesTheming for UICollectionViewCell found on the UIViewController component.

You can configure the CollectionViewComponentTheme theme using the following parameters.

NameTypeAuto update on changeDescription
viewTypeUICollectionView.TypeNoDefault class type that is used when creating new UICollectionView instances.
layoutTypeCollectionViewLayoutComponent.TypeNoDefault class type that is used when creating new UICollectionViewLayout instances.
headerTypeUICollectionReusableView.TypeNoDefault class type that is used when creating new UICollectionView section headers.
footerTypeUICollectionReusableView.TypeNoDefault class type that is used when creating new UICollectionView section footers.
backgroundColorUIColorYesView background color.
scrollViewThemeScrollViewComponentThemeYesTheming for the UIScrollView properties of UICollectionView.
refreshControlThemeRefreshControlTheme?YesTheming for the UIRefreshControl properties of UICollectionView.
prefetchIndexThresholdInt?YesList index that when scrolled past triggers a remote sync request to fetch additional data to be stored into the local database.
isPrefetchingEnabledBoolNoA Boolean value that indicates whether cell and data pre-fetching are enabled. This allows for more efficient pre-fetching, but isn't required.

You can configure the ChannelListCellComponentTheme theme using the following parameters.

NameTypeAuto update on changeDescription
cellTypeCollectionViewCellComponent.TypeNoDefault class type that is used when creating new UICollectionViewCell instances.
backgroundColorUIColor?YesView's background color.
highlightColorUIColor?YesView's background color during highlighted state.
selectedColorUIColor?YesView's background color during selected state.
itemThemeBasicComponentThemeYesTheming for the sub-views of the channel list cell.

You can configure the BasicComponentTheme theme using the following parameters.

NameTypeAuto update on changeDescription
imageViewImageComponentThemeYesTheming for the User avatar UIImageView
primaryLabelLabelComponentThemeYesTheming for the primary UILabelView that can be displayed on the channel list cell.
secondaryLabelLabelComponentThemeYesTheming for the secondary UILabelView that can be displayed on the channel list cell.
tertiaryLabelLabelComponentThemeYesTheming for the tertiary UILabelView that can be displayed on the channel list cell.
quaternaryLabelLabelComponentThemeYesTheming for the quaternary UILabelView that can be displayed on the channel list cell.

You can configure the ImageComponentTheme theme using the following parameters.

NameTypeAuto update on changeDescription
customTypeImageComponentView.TypeNoDefault class type that is used when creating new UIImageView instances.
localImageUIImage?YesLocally sourced UIImage you can use as a placeholder while fetching remote images.
cornerRadiusCGFloatYesThe radius to use when drawing rounded corners for the layer’s background.
marginUIEdgeInsetsYesThe default spacing to use when laying out content in the view.

You can configure the LabelComponentTheme theme using the following parameters.

NameTypeAuto update on changeDescription
textFontUIFontYesFont of the text.
textColorUIColorYesColor of the text.
textAlignmentNSTextAlignmentYesTechnique for aligning the text.
adjustsFontForContentSizeCategoryBoolYesBoolean that determines whether the text's font size is reduced to fit inside the bounds of the UILabelView.

Default

The default implementation is available through ChannelListComponentTheme.pubnubDefaultGroupChannelList which is composed of the following values:

ChannelListComponentTheme(
  controllerType: CollectionViewComponent.self,
  backgroundColor: .clear,
  navigationTitleView: BasicComponentTheme(
    imageView: ImageComponentTheme(
      customType: PubNubAvatarComponentView.self,
      localImage: AppearanceTemplate.Image.avatar,
      diameterSize: 42,
      margin: .init(top: .zero, left: .zero, bottom: .zero, right: 5.0)
    ),
    primaryLabel: LabelComponentTheme(
      customType: PubNubLabelComponentView.self,
      textFont: AppearanceTemplate.Font.title2.bold,
      textColor: AppearanceTemplate.Color.label,
      adjustsFontForContentSizeCategory: true,
      textAlignment: .natural,
      textMargin: .zero
    )
  ),
  collectionViewTheme: CollectionViewComponentTheme(
    viewType: UICollectionView.self,
    layoutType: TableCollectionViewLayout.self,
    headerType: ReusableLabelViewComponent.self,
    footerType: ReusableLabelViewComponent.self,
    backgroundColor: .systemBackground,
    isPrefetchingEnabled: true,
    scrollingBounces: false,
    alwaysBounceVertical: false,
    showsHorizontalScrollIndicator: false,
    keyboardDismissMode: .interactive,
    automaticallyAdjustsScrollIndicatorInsets: true,
    contentInsetAdjustmentBehavior: .always
  ),
  headerLabel: LabelComponentTheme(
    customType: PubNubLabelComponentView.self,
    textFont: AppearanceTemplate.Font.title1.bold,
    textColor: AppearanceTemplate.Color.label,
    adjustsFontForContentSizeCategory: true,
    textAlignment: .natural,
    textMargin: .zero
  ),
  itemTheme: ChannelListCellComponentTheme(
    customType: CollectionViewContainerCellComponent.self,
    viewModelType: ChannelCellViewModel.self,
    backgroundColor: .clear,
    highlightColor: .clear,
    selectedColor: .systemGray4,
    itemTheme: BasicComponentTheme(
      imageView: ImageComponentTheme(
        customType: PubNubAvatarComponentView.self,
        localImage: AppearanceTemplate.Image.avatar,
        diameterSize: 30,
        margin: .init(top: .zero, left: 10.0, bottom: .zero, right: 5.0)
      ),
      primaryLabel: LabelComponentTheme(
        customType: PubNubLabelComponentView.self,
        textFont: AppearanceTemplate.Font.caption1,
        textColor: AppearanceTemplate.Color.label,
        adjustsFontForContentSizeCategory: true,
        textAlignment: .natural,
        textMargin: .zero
      ),
      secondaryLabel: LabelComponentTheme(
        customType: PubNubLabelComponentView.self,
        textFont: AppearanceTemplate.Font.caption2,
        textColor: AppearanceTemplate.Color.secondaryLabel,
        adjustsFontForContentSizeCategory: true,
        textAlignment: .natural,
        textMargin: .zero
      )
    )
  )
)

Actions

This component supports the following UI interactions:

NameTypeDefault valueDescription
componentDidLoad(UIViewController, ChannelListComponentViewModel) -> VoidnilAn action called when the component view is loaded.
componentWillAppear(UIViewController, ChannelListComponentViewModel) -> VoidnilAn action called when the component view appears on the screen.
componentWillDisappear(UIViewController, ChannelListComponentViewModel) -> VoidnilAn action called when the component view disappears from the screen.
didSelectChannel(UIViewController, ChannelListComponentViewModel, ChatChannel) -> VoidDefault MessageList componentAn action called when a user taps a list item.

Example

The following example shows how an action can be configured after creating a view model. didSelectChannel creates a default MessageList component from the selected channel and displays it from the current ChannelList component.

let channelViewModel = chatProvider
  .senderMembershipsChannelListComponentViewModel()

channelViewModel.didSelectChannel = { (controller, viewModel, channel) in

  // Prepare Message List View
  guard let component = try? viewModel.provider
          .messageListComponentViewModel(for: channel.id)
          .configuredComponentView() else { return }

  // Display it from the current controller in the primary content view
  controller.show(component, sender: nil)
}

MemberList

UIViewController that displays a list of stored Member and User objects. It can represent all members of a specific channel, only other users that are currently present in the application, a sectioned list of present and non-present members, or any other type of NSFetchedResultsController made against stored member data.

Parameters

You can initialize the MemberList view model using the following parameters.

NameTypeDefault valueDescription
providerChatProvidern/aA ChatProvider instance to be used inside this component.
selectedChannelIdStringn/aThe channel identifier used during a member query.
fetchedEntitiesNSFetchedResultsControllern/aThe data type and query options used to populate the component.
componentThemeMemberListComponentTheme?The MemberList theme sourced from ChatProvider.The configurable theme used for the component. If you provide a custom object, you must maintain it outside of ChatProvider.

View model

The view model is used to configure both the main UIViewController for the component, the member data, and lay out any sub-components.

To override core functionality, you can either subclass the view model or implement override blocks to replace specific key functionalities.

The default MemberListComponentViewModel is configured to display the users that are members of a specific channel, sorted by their presence status and name.

Component population

ChatProvider can be extended to return a configured NSFetchedResultsController, and this object ensures the component always displays the most recent data. NSFetchedResultsController can contain any type of stored data related to a member, and can be sorted and sectioned based on any member property.

Default example

By default, the list is populated by any user that's a member of the provided channel. The list is sorted based on the presence status and the name of the user.

open func userMembersFrom(
  channelId: String,
  excludingSender: Bool = false
) -> NSFetchedResultsController<ManagedEntities.Member> {

  let request = ManagedEntities.Member.membersBy(
    channelID: channelId,
    excludingUserId: excludingSender ? senderID : nil,
    onlyPresent: true
  )

  request.sortDescriptors = [
    NSSortDescriptor(key: "user.name", ascending: true)
  ]

  request.relationshipKeyPathsForPrefetching = ["user"]

  return fetchedResultsControllerProvider(
    fetchRequest: request,
    sectionKeyPath: nil,
    cacheName: nil
  )
}

You can create a view model composed of the above default NSFetchedResultsController and MemberListComponentTheme using this ChatProvider extension method:

open func memberListComponentViewModel(
  channelId: String,
  customTheme: MemberListComponentTheme? = nil
) -> MemberListComponentViewModel<ModelData, ManagedEntities> {
  return MemberListComponentViewModel(
    provider: self,
    fetchedEntities: userMembersFrom(channelId: channelId),
    customTheme: customTheme ?? self.themeProvider.template.memberListComponent
  )
}

Properties

The MemberList view model provides outlets for the following properties after initialization:

NameTypeDefault valueDescription
providerChatProvidern/aA ChatProvider instance to be used inside this component.
fetchedEntitiesNSFetchedResultsControllern/aThe data type and query options used to populate the component.
componentThemeChannelListComponentThemeThe ChannelList theme sourced from ChatProvider.The configurable theme used for the component.
selectedChannelIdStringn/aThe channel identifier used during the member query.
leftBarButtonNavigationItems(UIViewController, MemberListComponentViewModel) -> [UIBarButtonItem]nilViews that appear on the left side of the navigation bar.
rightBarButtonNavigationItems(UIViewController, MemberListComponentViewModel) -> [UIBarButtonItem]nilViews that appear on the right side of the navigation bar.
customNavigationTitleView(MemberListComponentViewModel) -> UIView?nilThe custom view that's used inside the navigation bar title.
customNavigationTitleString(MemberListComponentViewModel) -> AnyPublisher<String?, Never>nilThe custom String publisher that's used inside the navigation bar title if a view isn't provided.
customMemberCellViewModel(MemberListComponentViewModel, Member) -> MemberCellComponentViewModelnilThe cell view model that's used instead of the default model found inside the theme.
configureFetchedResultsController(NSFetchedResultsController) -> VoidnilThe outlet to customize the member data query before the data is fetched.

You can configure the message items inside the list with the data found inside ManagedMemberViewModel:

public protocol ManagedMemberViewModel {
  associatedtype Entity: ManagedChatMember
  associatedtype ChannelViewModel: ManagedChannelViewModel
  associatedtype UserViewModel: ManagedUserViewModel

  var managedObjectId: NSManagedObjectID { get }

  var isPresentPublisher: AnyPublisher<Bool, Never> { get }

  var channelViewModel: ChannelViewModel { get }
  var userViewModel: UserViewModel { get }
}

Theming

You can configure the MemberListComponentTheme theme using the following parameters.

NameTypeAuto update on changeDescription
controllerTypeComponentViewControllerNoDefault class type that is used when creating new UIViewController instances.
backgroundColorUIColorYesView Controller’s background color.
navigationTitleViewBasicComponentTheme?YesTheming for UIView found on the UINavigationItem component.
collectionViewThemeCollectionViewComponentThemeYesTheming for UICollectionView found on the UIViewController component.
sectionHeaderLabelLabelComponentThemeYesTheming for UILabel you can attach to the UICollectionReusableView section Header-type.
cellThemeMemberListCellComponentThemeYesTheming for UICollectionViewCell found on the UIViewController component.

You can configure the CollectionViewComponentTheme theme using the following parameters.

NameTypeAuto update on changeDescription
viewTypeUICollectionView.TypeNoDefault class type that is used when creating new UICollectionView instances.
layoutTypeCollectionViewLayoutComponent.TypeNoDefault class type that is used when creating new UICollectionViewLayout instances.
headerTypeUICollectionReusableView.TypeNoDefault class type that is used when creating new UICollectionView section headers.
footerTypeUICollectionReusableView.TypeNoDefault class type that is used when creating new UICollectionView section footers.
backgroundColorUIColorYesView background color.
scrollViewThemeScrollViewComponentThemeYesTheming for UIScrollView properties of UICollectionView.
refreshControlThemeRefreshControlTheme?YesTheming for UIRefreshControl properties of UICollectionView.
prefetchIndexThresholdInt?YesList index that when scrolled past triggers a remote sync request to fetch additional data to be stored into the local database.
isPrefetchingEnabledBoolNoA Boolean value that indicates whether cell and data pre-fetching are enabled. This allows for more efficient pre-fetching, but isn't required.

You can configure the MemberListCellComponentTheme theme using the following parameters.

NameTypeAuto update on changeDescription
cellTypeCollectionViewCellComponent.TypeNoDefault class type that is used when creating new UICollectionViewCell instances.
backgroundColorUIColor?YesView's background color.
highlightColorUIColor?YesView's background color during highlighted state.
selectedColorUIColor?YesView's background color during selected state.
itemThemeBasicComponentThemeYesTheming for the sub-views of the member list cell..

You can configure the BasicComponentTheme theme using the following parameters.

NameTypeAuto update on changeDescription
imageViewImageComponentThemeYesTheming for the User avatar UIImageView
primaryLabelLabelComponentThemeYesTheming for the primary UILabelView you can display on the member list cell.
secondaryLabelLabelComponentThemeYesTheming for the secondary UILabelView you can display on the member list cell.
tertiaryLabelLabelComponentThemeYesTheming for the tertiary UILabelView you can display on the member list cell.
quaternaryLabelLabelComponentThemeYesTheming for the quaternary UILabelView you can display on the member list cell.

You can configure the ImageComponentTheme theme using the following parameters.

NameTypeAuto update on changeDescription
customTypeImageComponentView.TypeNoDefault class type that is used when creating new UIImageView instances.
localImageUIImage?YesLocally sourced UIImage you can use as a placeholder while fetching remote images.
cornerRadiusCGFloatYesThe radius to use when drawing rounded corners for the layer’s background.
marginUIEdgeInsetsYesThe default spacing to use when laying out content in the view.

You can configure the LabelComponentTheme theme using the following parameters.

NameTypeAuto update on changeDescription
textFontUIFontYesFont of the text.
textColorUIColorYesColor of the text.
textAlignmentNSTextAlignmentYesTechnique for aligning the text.
adjustsFontForContentSizeCategoryBoolYesBoolean that determines whether the text's font size is reduced to fit inside the bounds of UILabelView.

Default

The default implementation is available through MemberListComponentTheme.pubnubDefaultGroupMemberList which is composed of the following values:

MemberListComponentTheme(
  controllerType: CollectionViewComponent.self,
  backgroundColor: .clear,
  navigationTitleView: BasicComponentTheme(
    imageView: ImageComponentTheme(
      customType: PubNubAvatarComponentView.self,
      localImage: AppearanceTemplate.Image.avatar,
      diameterSize: 42,
      margin: .init(top: .zero, left: .zero, bottom: .zero, right: 5.0)
    ),
    primaryLabel: LabelComponentTheme(
      customType: PubNubLabelComponentView.self,
      textFont: AppearanceTemplate.Font.title2.bold,
      textColor: AppearanceTemplate.Color.label,
      adjustsFontForContentSizeCategory: true,
      textAlignment: .natural,
      textMargin: .zero
    )
  ),
  collectionViewTheme: CollectionViewComponentTheme(
    viewType: UICollectionView.self,
    layoutType: TableCollectionViewLayout.self,
    headerType: ReusableLabelViewComponent.self,
    footerType: ReusableLabelViewComponent.self,
    backgroundColor: .systemBackground,
    isPrefetchingEnabled: true,
    scrollingBounces: false,
    alwaysBounceVertical: false,
    showsHorizontalScrollIndicator: false,
    keyboardDismissMode: .interactive,
    automaticallyAdjustsScrollIndicatorInsets: true,
    contentInsetAdjustmentBehavior: .always
  ),
  headerLabel: LabelComponentTheme(
    customType: PubNubLabelComponentView.self,
    textFont: AppearanceTemplate.Font.title1.bold,
    textColor: AppearanceTemplate.Color.label,
    adjustsFontForContentSizeCategory: true,
    textAlignment: .natural,
    textMargin: .zero
  ),
  itemTheme: MemberListCellComponentTheme(
    customType: CollectionViewContainerCellComponent.self,
    viewModelType: MemberCellViewModel.self,
    backgroundColor: .clear,
    highlightColor: .clear,
    selectedColor: .clear,
    itemTheme: BasicComponentTheme(
      imageView: ImageComponentTheme(
        customType: PubNubAvatarComponentView.self,
        localImage: AppearanceTemplate.Image.avatar,
        diameterSize: 30,
        margin: .init(top: .zero, left: 10.0, bottom: .zero, right: 5.0)
      ),
      primaryLabel: LabelComponentTheme(
        customType: PubNubLabelComponentView.self,
        textFont: AppearanceTemplate.Font.caption1,
        textColor: AppearanceTemplate.Color.label,
        adjustsFontForContentSizeCategory: true,
        textAlignment: .natural,
        textMargin: .zero
      ),
      secondaryLabel: LabelComponentTheme(
        customType: PubNubLabelComponentView.self,
        textFont: AppearanceTemplate.Font.caption2,
        textColor: AppearanceTemplate.Color.secondaryLabel,
        adjustsFontForContentSizeCategory: true,
        textAlignment: .natural,
        textMargin: .zero
      )
    )
  )
)

Actions

This component supports the following UI interactions:

NameTypeDefault valueDescription
componentDidLoad(UIViewController, MemberListComponentViewModel) -> VoidnilAn action called when the component view is loaded.
componentWillAppear(UIViewController, MemberListComponentViewModel) -> VoidnilAn action called when the component view appears on the screen.
componentWillDisappear(UIViewController, MemberListComponentViewModel) -> VoidnilAn action called when the component view disappears from the screen.
didSelectMember(UIViewController, MemberListComponentViewModel, ChatMember) -> VoidnilAn action called when a user taps a list item.

Example

The following example shows how an action can be configured after creating a view model.

componentDidLoad is called when the component view first loads. The following example shows how to call PubNub HereNow presence and automatically store the response in the local database.

let memberViewModel = provider
  .memberListComponentViewModel(channelId: "stored-channel-id")

memberViewModel.componentDidLoad = { controller, viewModel in
  viewModel.provider.dataProvider.syncHereNow(
    .init(channels: [viewModel.selectedChannel.pubnubId]),
    completion: nil
  )
}

MessageList

UIViewController that displays a list of stored message objects. It's primarily used to fetch historical messages for a channel, including user names, avatars, times of sending, and rich message types (links, images).

Parameters

You can initialize the MemberList view model using the following parameters.

NameTypeDefault valueDescription
providerChatProvidern/aA ChatProvider instance to be used inside this component.
authorUsern/aThe User that represents the current application user.
selectedChannelChanneln/aThe channel of the displayed messages.
fetchedEntitiesNSFetchedResultsControllern/aThe data type and query options used to populate the component.
componentThemeMessageListComponentTheme?The MessageList theme sourced from ChatProvider.The configurable theme used for the component. If you provide a custom object, you must maintain it outside of ChatProvider.

View model

The view model is used to configure both the main UIViewController for the component, the member data, and lay out any sub-components.

To override core functionality, you can either subclass the view model or implement override blocks to replace specific key functionalities.

The default MessageListComponentViewModel is configured to display the messages of a particular channel sorted by the time a given message was sent.

Component population

ChatProvider can be extended to return a configured NSFetchedResultsController, and this object ensures the component always displays the most recent data. NSFetchedResultsController can contain any type of stored data related to a message, and can be sorted and sectioned based on any message property.

Default example

By default, the list is populated by any channel of which the current user is a member. The list will be divided into multiple sections based on the channel type, and each section is sorted by the name of the channel.

open func messagesFrom(
  pubnubChannelId: String
) -> NSFetchedResultsController<ManagedEntities.Message> {

  let request = ManagedEntities.Message.messagesBy(pubnubChannelId: pubnubChannelId)

  request.sortDescriptors = [
    NSSortDescriptor(key: "dateCreated", ascending: true)
  ]

  request.relationshipKeyPathsForPrefetching = ["sender"]

  return fetchedResultsControllerProvider(
    fetchRequest: request,
    sectionKeyPath: nil,
    cacheName: nil
  )
}

You can create a view model composed of the above default NSFetchedResultsController and MessageListComponentTheme using this ChatProvider extension method:

open func messageListComponentViewModel(
  for pubnubChannelId: String,
  customTheme: MessageListComponentTheme? = nil
) throws -> MessageListComponentViewModel<ModelData, ManagedEntities> {
  let sender = try fetchSender()

  guard let channel = try fetchChannel(byPubNubId: pubnubChannelId) else {
    throw ChatError.missingRequiredData
  }

  return MessageListComponentViewModel(
    provider: self,
    sender: sender,
    selectedChannel: channel,
    fetchedMessages: messagesFrom(pubnubChannelId: pubnubChannelId),
    componentTheme: customTheme ?? themeProvider.template.messageListComponent
  )
}
Channel ID storage

You must store the channel matching pubnubChannelId locally before calling the messageListComponentViewModel() method.

Properties

You can configure the MessageList view model using the following parameters.

NameTypeDefaultDescription
providerChatProvidern/aA ChatProvider instance to be used inside this component.
authorUserThe User that represents the current application user.
selectedChannelChanneln/aThe channel of the displayed message.
fetchedEntitiesNSFetchedResultsControllern/aThe data type and query options used to populate the component.
componentThemeMessageListComponentThemeThe MessageList theme sourced from ChatProvider.The configurable theme used for the component.
leftBarButtonNavigationItems(UIViewController, MessageListComponentViewModel) -> [UIBarButtonItem]nilViews that appear on the left side of the navigation bar.
rightBarButtonNavigationItems(UIViewController, MessageListComponentViewModel) -> [UIBarButtonItem]nilViews that appear on the right side of the navigation bar.
customNavigationTitleView(MessageListComponentViewModel) -> UIView?nilThe custom view that's used inside the navigation bar title.
customNavigationTitleString(MessageListComponentViewModel) -> AnyPublisher<String?, Never>nilThe custom String publisher that's used inside the navigation bar title if a view isn't provided.
configureFetchedResultsController(NSFetchedResultsController) -> VoidnilThe outlet to customize the message data query before the data is fetched.

You can configure the message items inside the list with the data found inside ManagedChannelViewModel:

public protocol ManagedMessageViewModel {
  associatedtype Entity: ManagedChatMessage
  associatedtype ChannelViewModel: ManagedChannelViewModel
  associatedtype UserViewModel: ManagedUserViewModel

  var pubnubId: Timetoken { get }
  var managedObjectId: NSManagedObjectID { get }

  var messageContentPublisher: AnyPublisher<MessageContent, Error> { get }
  var messageCustomPublisher: AnyPublisher<Data, Never> { get }

  var messageTextContentPublisher: AnyPublisher<String?, Never>? { get }
  var messageLinkContentPublisher: AnyPublisher<URL?, Never>? { get }
  var messageImageContentPublisher: AnyPublisher<URL?, Never>? { get }
  var messageJSONContentPublisher: AnyPublisher<AnyJSON?, Never>? { get }

  var messageCustomPublisher: AnyPublisher<Data, Never> { get }

  var messageDateCreatedPublisher: AnyPublisher<Date, Never> { get }

  var userViewModel: UserViewModel { get }
  var channelViewModel: ChannelViewModel { get }
}

Theming

You can configure the MessageListComponentTheme theme using the following parameters.

NameTypeAuto update on changeDescription
controllerTypeComponentViewController.TypeNoDefault class type that is used when creating new UIViewController instances.
backgroundColorUIColor?YesView Controller’s background color.
collectionViewThemeCollectionViewComponentThemeYesTheming for UICollectionView found on the UIViewController component.
incomingItemThemeMessageListCellComponentThemeYesTheming for messages that are sent from users other than the current user.
authorItemThemeMessageListCellComponentTheme?YesTheming for messages that are sent from the current user.
typingIndicatorCellThemeTypingIndicatorCellThemeYesTheming for UICollectionViewCell that's displayed when another member is typing.

You can configure the MessageListCellComponentTheme theme using the following parameters.

NameTypeAuto update on changeDescription
textMessageContentCellTypeCollectionViewCellComponent.TypeNoDefault class for the UICollectionViewCell specific to text based messages.
richMessageContentCellTypes[MessageContentType: CollectionViewCellComponent.Type]NoDictionary that maps UICollectionViewCell class types to known rich message content types.
backgroundColorUIColor?YesView's background color.
highlightColorUIColor?YesView's background color during highlighted state.
selectedColorUIColor?YesView's background color during selected state.
alignmentUICollectionViewCell.AlignmentYesVertical list edge the message is anchored to.
maxWidthPercentageCGFloatYesMaximum width a Cell spans inside the message list frame.
bubbleContainerThemeBubbleComponentThemeYesTheming for the bubble view container you can wrap around message content.
contentTextThemeTextViewComponentThemeYesTheming for UITextView that displays message text content.
contentLinkThemeLinkViewComponentThemeYesTheming for LPLinkView that displays message URL content.
itemThemeBasicComponentThemeYesTheming for the accessory views around the message content.
dateFormatterDateFormatterYesDataFormatter used when displaying message dates.

You can configure the TypingIndicatorCellTheme theme using the following parameters.

NameTypeAuto update on changeDescription
cellTypeCollectionViewCellComponent.TypeNoDefault class for UICollectionViewCell when creating typing indicator cells.
contentViewTypeUIViewNoDefault class for contentView inside the UICollectionViewCell typing indicator.
backgroundColorUIColor?YesView's background color.
highlightColorUIColor?YesView's background color during highlighted state.
selectedColorUIColor?YesView's background color during selected state.
alignmentUICollectionViewCell.AlignmentYesThe vertical list edge contentViewType is anchored to.
primaryContentColorUIColor?YesPrimary color by the contentViewType view.
secondaryContentColorUIColor?YesSecondary color used by the contentViewType view.
animationEnabledBoolNoWhether the typing indicator is animated.
pulsingBoolNoWhether the typing indicator animation pulses.
bouncesBoolNoWhether the typing indicator animation bounces.
bounceDelayTimeIntervalNoDelay between each distinct sub-view's bounce animation.
bounceOffsetCGFloatNoDistance each distinct sub-view bounces during its animation.
fadesBoolNoWhether the typing indicator animation fades as it animates.

Default

The default implementation is available through MessageInputComponentTheme.pubnubGroupChat which is composed of the following values:

MessageListComponentTheme(
  controllerType: CollectionViewComponent.self,
  backgroundColor: .systemBackground,
  messageInputComponent: .pubnubGroupChat,
  collectionViewTheme:  CollectionViewComponentTheme(
    layoutType: ChatLayout.self,
    backgroundColor: .secondarySystemBackground,
    scrollViewTheme: .enabled,
    refreshControlTheme: .init(
      pullToRefreshTitle: .init(string: "Pull to Refresh"),
      pullToRefreshTintColor: nil
    ),
    prefetchIndexThreshold: 35,
    isPrefetchingEnabled: false
  ),
  incomingItemTheme: MessageListCellComponentTheme(
    textMessageContentCellType: MessageListItemCell.self,
    richMessageContentCellTypes: [
      .link: MessageLinkContentCell.self
    ],
    backgroundColor: .clear,
    highlightColor: .clear,
    selectedColor: .clear,
    alignment: .leading,
    maxWidthPercentage: 0.65,
    bubbleContainerTheme: BubbleComponentTheme(
      alignment: .leading,
      containerType: .tailed,
      backgroundColor: .systemBlue,
      tailSize: 5,
      layoutMargin: UIEdgeInsets(top: 8, left: 16, bottom: 8, right: 16)
    ),
    contentTextTheme: TextViewComponentTheme(
      customType: UITextView.self,
      backgroundColor: .clear,
      textColor: .black,
      textFont: AppearanceTemplate.Font.body,
      usesStandardTextScaling: false,
      dataDetectorTypes: .all,
      linkTextAttributes: [:],
      isEditable: false,
      isExclusiveTouch: false,
      scrollView: .disabled,
      textContainerInset: .zero
    ),
    contentLinkTheme: LinkViewComponentTheme(
      cacheProvider: InMemoryLinkMetadataCache.shared,
      layoutMargin: UIEdgeInsets(top: 8, left: 16, bottom: 8, right: 16)
    ),
    itemTheme: .pubnubGroupChannelList,
    dateFormatter: .messageInline
  ),
  authorItemTheme: nil,
  typingIndicatorCellTheme: AnimatedTypingIndicatorCellTheme(
    cellType: IMessageTypingIndicatorCell.self,
    contentViewType: IMessageTypingBubbleView.self,
    backgroundColor: .clear,
    highlightColor: .clear,
    selectedColor: .clear,
    primaryContentColor: .systemGray5,
    secondaryContentColor: .systemGray2,
    animationEnabled: true,
    pulsing: true,
    bounces: true,
    bounceDelay: 0.33,
    bounceOffset: 0.25,
    fades: true
  )
)

Actions

This component supports the following UI interactions:

NameTypeDefault valueDescription
componentDidLoad(UIViewController, MemberListComponentViewModel) -> VoidnilAction called when the component view is loaded into memory. Maps to viewDidLoad() of the component view.
componentWillAppear(UIViewController, MemberListComponentViewModel) -> VoidnilAction called when the component view is about to be added to a view hierarchy. Maps to viewWillAppear(_:) of the component view.
componentWillDisappear(UIViewController, MemberListComponentViewModel) -> VoidnilAction called when the component view is removed from the view hierarchy. Maps to viewWillDisappear(_:) of the component view.

MessageInput

UIView that can be used to display an interactive UITextView with an optional, customizable UIButton used for sending the String input.

Component dependency

Unlike the other components that can be used as standalone view controllers, the message input should be treated as a sub-component. It's added as a sub-view or accessoryInput view of the UIViewController of another component.

Parameters

MessageInputComponent is the base class for the component. It can be sub-classed to add additional functionality or to include a third-party input bar. You can initialize the component through MessageInputComponentViewModel.

NameTypeDefault valueDescription
providerChatProvidern/aChatProvider instance to be used inside this component.
selectedChannelChanneln/aChannel used when sending messages.
componentThemeMessageInputComponentTheme?The MessageInput theme sourced from ChatProvider.The configurable theme used for the component. If you provide a custom object, you must maintain it outside of ChatProvider.

View model

The view model is used to configure both the main UIView for the component, the configuration of any sub-views, and the interaction between the MessageInputComponent and MessageListComponent.

To override core functionality, you can either subclass the view model or implement override blocks to replace specific key functionalities.

The default MessageInputComponentViewModel is configured based on the configurations found inside MessageInputComponentTheme.

Properties

The MessageInput view model provides outlets for the following properties after initialization:

NameTypeDefaultDescription
providerChatProvidern/aChatProvider instance to be used inside this component.
selectedChannelChanneln/aChannel used when sending messages.
componentTheme@Published MessageInputComponentThemeThe MessageInput theme sourced from ChatProvider.The configurable theme used for the component.
typingMemberIds@Published Set<String>[]Set of member PubNub identifiers that are currently typing on the channel. An empty Set means no one is currently typing.

Theming

You can configure the MessageInputComponentTheme theme using the following parameters.

NameTypeAuto update on changeDescription
viewTypeMessageInputComponentNoDefault class type that is used when creating new view instances.
backgroundColorUIColor?YesView’s background color.
placeholderTextString?YesText that appears whens the user hasn't entered the text.
placeholderTextColorUIColor?YesPlaceholder text's color.
placeholderTextFontUIFont?YesPlaceholder text's font.
textInputThemeInputTextViewComponentThemeYesTheming for UITextView used as the input view.
sendButtonThemeButtonComponentThemeYesTheming for UIButton responsible for sending message input.
typingIndicatorServiceTypingIndicatorServiceNoService that coordinates typing indicator events across all channels.
publishTypingIndicatorBoolYesWhether typing indicator signals are sent to other chat users.
displayTypingIndicatorBoolYesWhether typing indicator signals are displayed from other chat users.

You can configure the ButtonComponentTheme theme using the following parameters.

NameTypeAuto update on changeDescription
backgroundColorUIColor?YesView’s background color.
tintColorUIColor?YesTint color to apply to the button title and image.
titleButtonTitleStateThemeYesTitle during normal button state.
titleHighlightedButtonTitleStateThemeYesTitle during highlighted button state.
titleFontUIFont?YesFont of the button text.
imageButtonImageStateThemeYesImage during normal button state.
imageHighlightedButtonImageStateThemeYesImage during highlighted button state.

You can configure the ButtonTitleStateTheme theme using the following parameters.

NameTypeAuto update on changeDescription
titleString?YesTitle that the button displays.
attributedTitleNSAttributedString?YesStyled text that the button displays.
titleColorUIColor?YesColor of the text.
titleShadowColorUIColor?YesShadow color of the text.

You can configure the ButtonImageStateTheme theme using the following parameters.

NameTypeAuto update on changeDescription
imageUIImage?YesImage used for a button state.
backgroundImageUIImage?YesBackground image used for a button state.

Default

The default implementation is available through MessageInputComponentTheme.pubnubGroupChat which is composed of the following values:

MessageInputComponentTheme(
  viewType: MessageInputBarComponent.self,
  backgroundColor: .secondarySystemBackground,
  placeholderText: "Type Message",
  placeholderTextColor: .systemGray2,
  placeholderTextFont: AppearanceTemplate.Font.body,
  textInputTheme: InputTextViewComponentTheme(
    customType: UITextView.self,
    backgroundColor: .tertiarySystemBackground,
    textColor: .systemGray2,
    textFont: AppearanceTemplate.Font.body,
    usesStandardTextScaling: true,
    dataDetectorTypes: .all,
    linkTextAttributes: [:],
    isEditable: true,
    isExclusiveTouch: false,
    scrollView: .enabled,
    textContainerInset: .zero,
    typingAttributes: [:],
    autocapitalizationType: .sentences,
    autocorrectionType: .default,
    spellCheckingType: .default,
    smartQuotesType: .default,
    smartDashesType: .default,
    smartInsertDeleteType: .default,
    keyboardType: .default,
    keyboardAppearance: .default,
    textContentType: nil
  ),
  sendButton: ButtonComponentTheme(
    backgroundColor: .clear,
    tintColor: .systemBlue,
    title: .empty,
    titleHighlighted: .empty,
    titleFont: AppearanceTemplate.Font.caption1,
    image: ButtonImageStateTheme(
      image: UIImage(systemName: "paperplane.fill")?.rotate(degree: 45)?.withTintColor(.systemBlue),
      backgroundImage: nil
    ),
    imageHighlighted: .empty
  ),
  typingIndicatorService: .shared,
  publishTypingIndicator: true,
  displayTypingIndicator: true
)

Actions

This component supports the following UI interactions.

NameTypeDefault valueDescription
messageWillSend(MessageInputComponentViewModel, ChatMessage) -> ChatMessagenilClosure that's called before sending a message. Allows you to mutate the message that is sent.
messageDidSend(MessageInputComponentViewModel, ChatMessage, Future<ChatMessage, Error>) -> VoidnilClosure that's called after the message was sent. You can use Future to track the transmission of the message and handle any Error that might be returned.

Example

Let's see how to configure an action after creating a view model.

messageWillSend is called when the user is attempting to send a new message. The following example shows how to store the message before sending so it appears on the MessageList component faster:

let messageInputViewModel = try provider
  .messageInputComponentViewModel(channelId: "stored-channel-id")

messageInputViewModel.messageWillSend = { viewModel, message in

  viewModel.provider.dataProvider.load(messages: [message])

  return message
}
←Getting StartedData Components→
  • Component theming
  • ChannelList
    • Parameters
    • View model
    • Theming
    • Actions
  • MemberList
    • Parameters
    • View model
    • Theming
    • Actions
  • MessageList
    • Parameters
    • View model
    • Theming
    • Actions
  • MessageInput
    • Parameters
    • View model
    • Theming
    • Actions
© PubNub Inc. - Privacy Policy