Can Realm paginating the objects be possible?

I have a local data of a few thousands stored in realm.
I tried using realm.objects(Object.self).where() to filter the objects.
But this is fetching whole data and filter on the total data.
Is there a where to fetch data in batches with limit like pagination without using realm.objects?

Hi @Krishna_Vivekananda_Vutti ,

If the data is local, it will obviously filter over the total data: please note, however, that Realm only lazily loads the results of a query (see here for Swift, other SDKs behave similarly), so the objects themselves will only be brought into memory when needed, avoiding the need for pagination.

On the other hand, if you were using Flexible Sync, i.e. having data on the backend, you could subscribe to only a part of it, and have only that locally.

I am trying to do pagination using following code snippet.

func getParticipantWithPagination(index: Int, type: String, completion: ((_ userModels: [UserModel]?) -> ())? = nil) {
        DispatchQueue(label: Constants.DispatchThreads.realmThread, qos: .background).async { [weak self] in
            guard let self = self else { return }
            do {
                let realm = try Realm(configuration: self.realmConfig)
                
                let objects = realm.objects(UserModel.self).where({ $0.type == type }).sorted ({ $0.date > $1.date }).dropFirst(index).prefix(20)
                let users = Array(objects).compactMap({ ThreadSafeReference(to: $0) })
                DispatchQueue.main.async { [weak self] in
                    guard let self = self else { return }
                    guard let mainRealm = try? Realm(configuration: self.realmConfig) else { return }
                    let array = users.compactMap({ mainRealm.resolve($0) })
                    completion?(array)
                }
            } catch {
#if DEBUG
                print("unable to load realm error:", error.localizedDescription)
#endif
            }
        }
    }

Calling the above method from the following method:

func tableView(_ tableView: UITableView, prefetchRowsAt indexPaths: [IndexPath]) {
if indexPaths.contains(IndexPath(row: self.usersArray.count - 1, section: .zero)) {
                    self.getParticipantWithPagination(index: self.usersArray.count, type: self.type) { userModels in
self.usersArray.append(contentsOf: userModels ?? [])
tableView.reloadData()
                }
}
}

As I have a lot of data stored in local, It is taking time to load and prefix the data to reload the tableview.

Is there any way to do the fast loading of the limited data?

Hi @Krishna_Vivekananda_Vutti ,

Again, there should be no need to use pagination, given the lazy loading nature of objects in Realm, you’re opening the realm twice in your code, and the compactMap() is likely forcing a read of all objects, even before you use them to visualise the rows in the table view, defeating the purpose of a lazy load in the first place.

We have several examples you could look at, have you tried to see if there’s anything that would fit your requirements?

Is there a way to sort the data on query or add a variable to Object for sorting?

Hi @Krishna_Vivekananda_Vutti,

Yes, of course there is

1 Like

Here’s the likely issue: As @Paolo_Manna mentioned, Realm objects are lazily loaded. That means large datasets take up only a small fraction of memory and Realm stays very responsive.

However, as soon as high level Swift functions are applied (map, filter etc), that lazy-loadingness goes away and ALL of the objects are loaded.

Additionally as soon as those objects are cast to Swift structures, like an array (as in the above code snippet) all of the objects are also loaded.

Lastly, the code appears to be jumping around threads and that can lead to instability and quite frankly is probably not needed (exploring Async functions and/or Actors would be a better approach if that is needed).

So: Best Practice is to stick with provided Realm functions for working with Realm objects.

Realm Results and List objects behave very much like an array and make a perfectly suitable DataSource for a tableview. In fact, one of our projects has a 2GB dataset and millions of objects. Realm flys through that with no issue and we only send large writes to a background thread. Everything else if fluid and no pagination is needed.

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.