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.
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;
}