A MessageCollection instance allows you to swiftly create a chat view that includes all data. This page explains how to make a view using the collection.
import SendbirdChatSDK
class CustomViewController: UIViewController {
// The following properties should be initialized before using them.
var collection: MessageCollection?
var channel: GroupChannel?
var startingPoint: Int64!
func createMessageCollection() {
// You can use a MessageListParams instance for MessageCollection.
let params = MessageListParams()
params.reverse = false
params.isInclusive = false
params.messageTypeFilter = .all
params.includeMetaArray = false
params.includeReactions = false
// You can add other params setters.
// ...
guard let channel = self.channel else {
return
}
self.collection = SendbirdChat.createMessageCollection(channel: channel, startingPoint: self.startingPoint, params: params)
self.collection?.delegate = self
}
// Initialize messages from startingPoint.
func initialize() {
guard let collection = self.collection else {
return
}
collection.startCollection(initPolicy: .cacheAndReplaceByApi, cacheResultHandler: { messages, error in
// Messages are retrieved from the local cache.
// They might be too outdated compared to startingPoint.
}, apiResultHandler: { messages, error in
// Messages are retrieved from the Sendbird server through the API.
// According to MessageCollectionInitPolicy.cacheAndReplaceByApi,
// the existing data source needs to be cleared
// before adding retrieved messages to the local cache.
})
}
// ...
}
The startingPoint parameter is the reference point of message retrieval for a chat view. This should be specified in the form of timestamp.
If you set the value of startingPoint to the current time, messages in the view are retrieved in reverse chronological order, showing messages from most to least recent.
If you set the value of startingPoint to the message last read by the current user, messages in the view are fetched in chronological order, starting from the last message seen by the user to the latest.
The argument of MessageCollectionInitPolicy determines how initialization deals with the message data retrieved from the local cache and API calls. Because we only support cacheAndReplaceByApi as of now, messages in the local cache must be cleared prior to adding the messages from the Sendbird server.
Policy
Description
cacheAndReplaceByApi
Retrieves cached messages from the local cache and then replaces them with the messages pulled from the Sendbird server through API calls.
These methods have to be called during initialization as well.
class CustomViewController: UIViewController {
// ...
// Load the previous messages when the scroll reaches
// the first message in the chat view.
func loadPrevious() {
guard let collection = self.collection else {
return
}
if collection.hasPrevious {
collection.loadPrevious { messages, error in
guard error == nil else {
// Handle error.
return
}
}
}
}
// Load the next set of messages when the scroll reaches
// the last message in the chat view.
func loadNext() {
guard let collection = self.collection else {
return
}
if collection.hasNext {
collection.loadNext { messages, error in
guard error == nil else {
// Handle error.
return
}
}
}
}
// ...
}
- A message is deleted as a real-time event. - Message deletion is detected during changelog sync. - The value of the MessageListParams setter such as custom_type changes.
- The channel information that is included in the user's current chat view is updated as a real-time event. - Channel info update is detected during changelog sync.
- The current channel is deleted as a real-time event. - Channel deletion is detected during changelog sync. * In both cases, the entire view should be disposed of.
didDetectHugeGap(_:)
- A huge gap is detected through background sync. In this case, you need to dispose of the view and create a new MessageCollection instance.
extension CustomViewController: MessageCollectionDelegate {
func messageCollection(_ collection: MessageCollection, context: MessageContext, channel: GroupChannel, addedMessages: [BaseMessage]) {
switch context.sendingStatus {
case .succeeded:
// Add messages to your data source.
case .pending:
// Add pending messages to your data source.
default:
}
}
func messageCollection(_ collection: MessageCollection, context: MessageContext, channel: GroupChannel, updatedMessages: [BaseMessage]) {
switch context.sendingStatus {
case .succeeded:
// Update the send status of sent messages.
case .pending: (failed -> pending)
// Update the send status from failed to pending in your data source.
// Remove the failed message from the data source.
case .failed: (pending -> failed)
// Update the send status from pending to failed in your data source.
// Remove the pending message from the data source.
case .canceled: (pending -> canceled)
// Remove the pending message from the data source.
// Implement codes to process canceled messages on your end.
// The Chat SDK doesn't store canceled messages.
default:
}
}
func messageCollection(_ collection: MessageCollection, context: MessageContext, channel: GroupChannel, deletedMessages: [BaseMessage]) {
switch context.sendingStatus {
case .succeeded:
// Remove the sent message from your data source.
case .failed:
// Remove the failed message from your data source.
default:
}
}
func messageCollection(_ collection: MessageCollection, channelContext: ChannelContext, updatedChannel channel: GroupChannel) {
// Change the chat view with the updated channel information.
}
func messageCollection(_ collection: MessageCollection, channelContext: ChannelContext, deletedChannel channelURL: String) {
// This is called when a channel was deleted.
// So the current chat view should be cleared.
}
func didDetectHugeGap(_ collection: MessageCollection) {
// The Chat SDK detects that more than 300 messages are missing.
// Dispose of the current collection.
collection.dispose()
// Create a new message collection object.
self.createMessageCollection()
// An additional implementation is required for initialization.
}
}
In local caching, a gap refers to a chunk of objects that are created and logged on the Sendbird server but missing from the local cache. Depending on the connection status, the client app could miss message events and new messages stored in the Sendbird server may not reach the Chat SDK in the client app. In such cases, a gap is created.
Small gaps can be filled in through changelog sync. However, if the client app has been disconnected for a while, too big of a gap can be created.
A gap can be created for many reasons, such as when a user has been offline for days. When the client app comes back online, the Chat SDK checks with the Sendbird server to see if there are any new messages. If it detects that more than 300 messages are missing in the local cache compared to the Sendbird server, the SDK determines that there is a huge gap and the didDetectHugeGap(_:) delegate is called.
Note: To adjust the number of missing messages that result in a call for the didDetectHugeGap(_:) delegate, contact our support team.
In this case, the existing MessageCollection instance should be cleared through the dispose() method and a new one must be created for better performance.
The dispose() method should be called when you destroy the chat screen to notify the SDK that this collection is no longer visible.
For example, this should be used when the current user exits from the chat screen or when a new collection has to be created due to a huge gap detected by didDetectHugeGap(_:).