ListView: Load-on-demand

There are certain scenarios typically with remote data over the wire where data needs to be loaded continuously on small portions. TKListView can load data on demand.

Enabling the load-on-demand

To enable the load on demand feature, you shoud set the loadOnDemandMode property to one of the two supported modes TKListViewLoadOnDemandModeAuto or TKListViewLoadOnDemandModeManual.

_listView.loadOnDemandMode = TKListViewLoadOnDemandModeManual;
listView.loadOnDemandMode = TKListViewLoadOnDemandMode.manual
listView.LoadOnDemandMode = TKListViewLoadOnDemandMode.Manual;

When using the auto mode the loadOnDemandBufferSize property defines the number of cells from the bottom of the list view up at which to start requesting data.

_listView.loadOnDemandBufferSize = 5;
listView.loadOnDemandBufferSize = 5
listView.LoadOnDemandBufferSize = 5;

After setting the desired loadOnDemandMode you should implement the TKListViewDelgate method listView:shouldLoadMoreDataAtIndexPath: to determine if more data should be loaded. After the data is loaded you should notify the ListView by calling its didLoadDataOnDemand method:

- (BOOL)listView:(TKListView *)listView shouldLoadMoreDataAtIndexPath:(NSIndexPath *)indexPath
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{

        _lastRetrievedDataIndex = MIN(_names.items.count, _lastRetrievedDataIndex + 10);

        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2* NSEC_PER_SEC), dispatch_get_main_queue(), ^{
            //Notifying the ListView that we have fresh data so it can hide the activity indicator and be ready for next load-on-demand request.

            if (_lastRetrievedDataIndex == _names.items.count) {
                listView.loadOnDemandMode = TKListViewLoadOnDemandModeNone;
            }

            [listView didLoadDataOnDemand];
        });
    });

    return YES;
}
func listView(_ listView: TKListView, shouldLoadMoreDataAt indexPath: IndexPath) -> Bool {
    DispatchQueue.global(qos:DispatchQoS.QoSClass.userInitiated).async(execute: { () -> Void in
    self.lastRetrievedDataIndex = min(self.names.items.count, self.lastRetrievedDataIndex + 10)

    DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + Double(Int64(2 * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC), execute: {
        //Notifying the ListView that we have fresh data so it can hide the activity indicator and be ready for next load-on-demand request.

        if self.lastRetrievedDataIndex == self.names.items.count {
            listView.loadOnDemandMode = TKListViewLoadOnDemandMode.none
        }

        listView.didLoadDataOnDemand()
    })
   })

    return true
}
class ListViewDelegate: TKListViewDelegate
{
    ListViewLoadOnDemand owner;

    public ListViewDelegate(ListViewLoadOnDemand owner)
    {
        this.owner = owner;
    }

    public override bool ShouldLoadMoreDataAtIndexPath (TKListView listView, NSIndexPath indexPath)
    {
        DispatchQueue.DefaultGlobalQueue.DispatchAsync (() => {
            this.owner.lastRetrievedDataIndex = Math.Min(this.owner.names.Items.Length, this.owner.lastRetrievedDataIndex + 10);
            DispatchQueue.MainQueue.DispatchAfter(new DispatchTime(DispatchTime.Now, 2 * 400000000), new Action(delegate {
                if (this.owner.names.Items.Length == this.owner.lastRetrievedDataIndex) {
                    listView.LoadOnDemandMode = TKListViewLoadOnDemandMode.None;
                }
                listView.DidLoadDataOnDemand();                
            }));
        });

        return true;
    }
}

When using manual mode, TKListView appends a special cell at the end of the list. Touching this cell starts the process of loading more data. In this scenario you should process listView:cellForItemAtIndexPath: method of TKListViewDataSource and check whether this is a "load on demand cell":

- (TKListViewCell*)listView:(TKListView *)listView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    TKListViewCell *cell = [listView dequeueLoadOnDemandCellForIndexPath:indexPath];
    if (cell == nil) {
        cell = [listView dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath];
        cell.imageView.image = [UIImage imageNamed:_photos.items[indexPath.row]];
        cell.textLabel.text = _names.items[indexPath.row];
        cell.detailTextLabel.text = [_loremIpsum randomString:10 + (arc4random()%16) forIndexPath:indexPath];
        cell.detailTextLabel.textColor = [UIColor whiteColor];
    }
    cell.backgroundView.backgroundColor = [UIColor colorWithWhite:0.3 alpha:0.5];
    ((TKView*)cell.backgroundView).stroke = nil;

    return cell;
}
func listView(_ listView: TKListView, cellForItemAt indexPath: IndexPath) -> TKListViewCell? {

    var cell = listView.dequeueLoadOnDemandCell(for: indexPath)

    if (cell == nil) {
        cell = listView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as? TKListViewCell
        cell!.imageView.image = UIImage(named: self.photos.items[(indexPath as NSIndexPath).row] as! String)
        cell!.textLabel.text = names.items[(indexPath as NSIndexPath).row] as? String
        cell!.detailTextLabel.text = loremIpsumGenerator.randomString(10 + Int(arc4random_uniform(16)), indexPath: indexPath) as String
        cell!.detailTextLabel.textColor = UIColor.white
    }

    cell!.backgroundView?.backgroundColor = UIColor(white: 0.3, alpha: 0.5)
    let backgroundView = cell!.backgroundView as! TKView
    backgroundView.stroke = nil

    return cell
}
public override TKListViewCell CellForItem (TKListView listView, NSIndexPath indexPath)
{
    TKListViewCell cell = listView.DequeueLoadOnDemandCell (indexPath);

    if (cell == null) {
        cell = listView.DequeueReusableCell ("cell", indexPath) as TKListViewCell;
        cell.ImageView.Image = UIImage.FromBundle (this.owner.photos.Items [indexPath.Row] as NSString);
        cell.TextLabel.Text = this.owner.names.Items [indexPath.Row] as NSString;
        Random r = new Random ();
        cell.DetailTextLabel.Text = this.owner.loremIpsum.RandomString (10 + r.Next (0, 16), indexPath);
        cell.DetailTextLabel.TextColor = UIColor.White;
    }

    cell.BackgroundView.BackgroundColor = UIColor.FromWhiteAlpha (0.3f, 0.5f);
    ((TKView)cell.BackgroundView).Stroke = null;

    return cell;
}