Sendbird SyncManager channel pagination issue

Moving my question from StackOverflow from here (as I didn’t get much response there).

I am using Sendbird for chat messages in an native iOS app. They have an add-on SyncManager. Which caches the channel list and messages locally on the phone for offline support.

I am trying to paginate the channel list using SyncManager’s collection. Here is my code snippet:

func fetchCollection() {
    self.query = SBDGroupChannel.createMyGroupChannelListQuery()
    self.query?.order = .latestLastMessage
    self.query?.limit = 20
    self.collection = SBSMChannelCollection(query: query)
    self.collection?.delegate = self

func fetchNextPage() {
    // Problem: The `query.hasNext` is never set to `false`!
    guard let query = query, query.hasNext else { return }
    collection?.fetch { error in
        if let error = error {
            self.log("Error: \(error)", level: .debug)

        // Do nothing, as the collection delegate would be notified to the delegate.
func collection(_ collection: SBSMChannelCollection, didReceiveEvent action: SBSMChannelEventAction, channels: [SBDGroupChannel]) {
    switch action {
    case .insert:
    case .update:
    case .remove:
    case .move:
    case .clear:
    case .none:
        DispatchQueue.main.async { [weak self] in

        assertionFailure("Undefine action")
        DispatchQueue.main.async { [weak self] in

The problem is the query.hasNext is never set to false. I have tried checking collection.query.hasNext as well, but that too has true always.

Note that Sendbird’s basic SDK does set the query.hasNext to false and hence I can determine whether or not the query has next page and I should make another call. I want to paginate using the SyncManager.

Their sample app for SyncManager sends the next page request without checking if there is a next page available, so every time the user scrolls to bottom, they are calling the API. Am I missing anything here?

Is there any reason why you used SBGroupChannelListQuery by yourself instead just using collection? SBSMChannelCollection object already has query property. The query object you used is not related to a query object in collection, therefore your own query will never get to be false

Thank you for responding @Woo.

I am following the Sendbird guide to create a channel collection.

I think I am doing exactly what the guide mentions:

guard let listQuery = SBDGroupChannel.createMyGroupChannelListQuery() else { return }
let collection = SBSMChannelCollection(query: listQuery)
collection?.delegate = self
collection?.fetch(completionHandler: { (error) in })

What do you suggest different? To create an instance of the SBSMChannelCollection, we have to provide instance of the SBDGroupChannelListQuery right?

I am passing the query object to create the SBSMChannelCollection.

Thanks for the information! I missed that part and you are correct. Let me investigate the issue and will get back to you :slight_smile:

1 Like

I found that you cannot rely on query property’s hasNext to check if next is available (this is kinda bug but still you can’t rely on this). A workaround solution (bit hacky) for this is you set the limit on query and if you don’t receive the same amount of channels from the callback didReceiveEvent, then you can assume its end of page.

@Woo Thank you for the answer.

Okay. I won’t rely on query.hasNext(). Thats clear.

I have some doubts about the workaround solution. How do I know that a message I have received from the callback didReceiveEvent is part of the previous page I have requested or it’s a live message some other user has sent just?