Swift 3-4 Retrieving large set with page size and offset.

Has anyone an example how this is done?

I get the setPageSize and setOffset part. Not quite clear on when/how to call queryBuilder?.prepareNextPage() part.
If anyone has something so I can see how to loop things, I would be most appreciative.
As an example, say I have 250 objects in a custom class that I need to get into an array in iOS/macOS.

Hi Jorgen,

Here you go, this section in the docs explains this with examples: https://backendless.com/docs/ios/doc.html#data_data_paging

Thank you, but it doesn’t really explain it.

There is two calls, by the look of things, but not really how to string them together.
I was hoping someone had done it and could show the link between them.

What .prepareNextPage() call does is merely setting offset = offset + pageSize. It doesn’t perform any network calls. Thus, you call it before calling .find() to retrieve the next page of data.

For example, of you have 250 data objects, here’s the sequence of actions you need to retrieve them all:

queryBuilder.setPageSize(100); // set to max initially
Backendless.Data.find( queryBuilder ); // retrieves first 100 objects (0-99)
queryBuilder.prepareNextPage();
Backendless.Data.find( queryBuilder ); // retrieves second 100 objects (100-199)
queryBuilder.prepareNextPage();
Backendless.Data.find( queryBuilder ); // retrieves remaining objects, since there are less than 100 left (200-250)

(note that this is just a pseudocode, not an actual code to run)

OK, I will give that a go.

Is there any call/signal to say that I have reached the end?

E.g. if I have your line 3 & 4 running in a loop, I need something to finish the loop.

You can check whether the resulting collection is empty, it will indicate that there’s no data left.

Continuing my example:

...
queryBuilder.prepareNextPage();
Backendless.Data.find( queryBuilder ); // retrieves remaining objects, since there are less than 100 left (200-250)
queryBuilder.prepareNextPage();
Backendless.Data.find( queryBuilder ); // returns empty collection

or you can count by query https://backendless.com/docs/ios/doc.html#data_get_object_count


// get number of objects for a query
dataStore.getObjectCount(queryBuilder: DataQueryBuilder!,
                         response:((NSNumber?) -> Void)!, 
                         error:((Fault?) -> Void)!)

then if page size is 10 and there is 253 records, you will have 26 pages

Solved it.

The loop of the secondary finds needed to be blocking and within the first fin block.
You can close this now.
Thank you.

Whats the best way to do this without blocking the UI?
https://backendless.com/feature-17-data-paging-or-how-to-efficiently-load-large-data-sets-in-a-mobile-app/
This seems to be missing some code, at least for the swift side.

there is sample with paging

func advancedPagingAsync() {

        var startTime = NSDate()

        var offset = 0
        var query = BackendlessDataQuery()
        query.queryOptions.pageSize = PAGESIZE // set page size
        backendless.persistenceService.of(Restaurant.ofClass()).find(
            query,
            response: { (var restaurants : BackendlessCollection!) -> () in
                println("Total restaurants in the Backendless starage - \(restaurants.totalObjects)")
                self.getPageAsync(restaurants, offset:offset, startTime:startTime)
            },
            error: { (var fault : Fault!) -> () in
                println("Server reported an error: \(fault)")
            }
        )
    }

}

This part is missing. Where is it calling?

ok, now I understand your question, we will add this part to the doc and notice you

Thanks for the quick reply and fix!

Hello!

Are you using Backendless v3 or Backendless v5? These methods are different in different versions of Backendless.

Regards, Olga

Backendless v5

Robert

I’ll provide a simpler example:

// Setup pageSize and offset

let pageSize: Int32 = 5
var offset: Int32 = 0

// Create queryBuilder with this params

var queryBuilder = DataQueryBuilder()!
queryBuilder.setOffset(offset)
queryBuilder.setPageSize(pageSize)

// Call this method to load objects with paging

func loadObjects() {
    let dataStore = Backendless.sharedInstance()?.data.ofTable("Restaurant")

	// Total amount of objects in the table
    let totalObjects: Int32 = dataStore?.getObjectCount()?.int32Value ?? 0	
        
    dataStore?.find(queryBuilder, response: { loadedObjects in
        let loadedObjectsCount: Int32 = Int32(loadedObjects?.count ?? 0)
        print("Loaded \(loadedObjectsCount) objects in this page")
            
        self.offset += loadedObjectsCount

		// Check if we have more objects to load
        if self.offset < totalObjects {
			
			// update queryBuilder offset
            self.queryBuilder.prepareNextPage()

			// loading objects with new offset
            self.loadObjects()
        }
    }, error: { fault in
        print("ERROR: \(fault!)")
    })        
}

As I have 12 objects in my Restaurant table the result is:

Loaded 5 objects in this page
Loaded 5 objects in this page
Loaded 2 objects in this page

Hope it helps you

Regards,
Olga

1 Like