Being Efficient with iOS Tables

Anyone who has built an app in Xojo has used the Listbox method AddRow to create new rows. The iOSTable control in Xojo also has an AddRow method. However, unlike building a desktop app, AddRow is not always appropriate for iOS apps.

Desktop and laptop computers generally have plenty of RAM so loading a lot of data into memory is not a problem. Call AddRow all you want and it won’t likely matter. iOS devices however don’t have nearly as much RAM. iOS does quite a bit of gymnastics to manage memory efficiently, but it can only do so much and sometimes it needs your help.

When your iOS app has a table that will only display a small number of rows, less than 50 for example, then AddRow is fine. You are likely duplicating your entire data set (one set being the original and the other being the rows in the iOSTable) but an extra 50 rows isn’t going to be a problem.

Once you get into hundreds of rows, it starts to really make a difference. For example, in an iOS app I built one particular table has over 1000 rows. However, at any given moment, there are only 11 rows displayed because that’s as much as my iPhone screen will show. I can swipe up and down of course, but only 11 rows are displayed at a time.

In cases like this, you need something that only duplicates the rows that the user can actually see at any given moment. The more rows of data, the more important this becomes. That’s where the iOSTable’s DataSource property comes in. With this property you can dynamically load data from your data set into the table allowing iOS to be more efficient with memory by unloading rows that are no longer visible. With large data sets, this not only saves memory but makes your app more responsive as well.

So what’s involved with using iOSTable’s DataSource property? Basically, you’ll add a class to your project that will, on demand, take data from your original source and provide it to the table. As the user scrolls the table, the table will request rows from your class which will get them from the original data source:

Create a new class and name it after the type of data it will work with. For example, if it’s providing Customer data, call it Customers. In the Inspector, click the Choose button next to Interfaces. When the dialog appears, click the checkbox for iOSTableDataSource to add this interface then click OK. This will add a few methods to the class. Since this class will need to have access to the original data source, I suggest you add a constructor method to it that takes the original source of the data as a parameter. For example, if you have the data in an Array or Dictionary, pass that in as a parameter to the constructor method you add. Then store that reference in a property in the class so the rest methods you are about to implement will have access to it. If you’ve never created a constructor method, just add a new method to the class and name it Constructor. Next take a look at the four methods that were added by choosing the iOSTableDataSource interface. They are RowCount, RowData, SectionCount and SectionTitle. When we are done, your iOSTable will call these methods when it needs their information. In each case, you will simply add the code that returns the requested data. For example, for RowCount, you’ll return how many rows there are. If the original data is in an array, just return Ubound + 1 (assuming the array starts at zero of course). For RowData, the row number requested will be passed in. You simply return an iOSTableCellData object with the data from that row inserted. The same goes for the sections. If you aren’t using sections, return 1 in SectionCount and “” in SectionTitle. Last but not least, at whatever point you were calling AddRow to populate the table, remove that code and the loop as well. Instead, you’ll create a new instance of your Customers class, pass to it the original data, then assign that instance as the table’s data source. For example, say our data is coming from an array called CustomerList. You’ll need to add a property to the view that contains the table in order to store an instance of your Customers class. In the example code below, that property is called CustomerData. The code to set up the table to use the data source would look like this: CustomerData = new Customers(CustomerList) Table1.DataSource = CustomerData

That’s it. You’re done. Now instead of your app duplicating every row of data from the original source (CustomerList in the example above), it will dynamically fetch rows as it needs them. Your app will be more responsive and will use less memory as well. This will be overkill if the table never shows more than a few dozen rows. However, if it’s showing hundreds or even thousands of rows, it’s a necessity.

If you’d like to see an example project, there’s one included with the Xojo download (Example Projects/iOS/Controls/Table/TableDataSource.)



