ROInterfaceTable 0.1

ROInterfaceTable 0.1

TestsTested
LangLanguage Obj-CObjective C
License MIT
ReleasedLast Release Aug 2015

Maintained by George Cox.



  • By
  • Tundaware LLC

Tack on ?ts=2 when viewing our source, it'll make your browser stop misrepresenting tabs.

Credit

This project borrows a lot from IGInterfaceDataTable but is focused from the beginning on supporting NSFetchedResultsController, testability, and support the bits Apple recommends but doesn't help with (batch loading).

ROInterfaceTable

ROInterfaceTable adds support for sections to WKInterfaceTable. It supports the same batch updating you're used to with UITableView, making it compatible with NSFetchedResultsController's change notifications. This was created for and is used in Downcast's Apple Watch app, currently in beta.

Features

  • Section support, including section header and section footer support.
  • Applies changes in batches using beginUpdates and endUpdates
  • NSFetchedResultsControllerDelegate compatible
  • Paging/Loading of rows in batches, either manually or automatically with a per-batch delay.

Section Support

Sadly, WKInterfaceTable only supports flat data sources out of the box, which can be painful to deal with coming from iOS. ROInterfaceTable adds the same familiar indexPath based methods you're used to using with UITableView. As far as adding, moving, and deleting rows and sections, it's just like UITableView.

Batch Updates

Rows can only be added to WKInterfaceTable incrementally. ROInterfaceTable adds familiar beginUpdates and endUpdates methods that allow changes to be grouped together and applied in the correct order regardless of the order they come in.

NSFetchedResultsController Compatibility

The order in which NSFetchedResultsController reports move operations prevents us from immediately applying changes to a table. Batch update support makes it possible to use this class with ROInterfaceTable just as you would with UITableView.

Paging/Batch Loading Rows

Loading too many rows into a WKInterfaceTable can cause memory consumption issues, load time delays, and crashes. Apple recommends only loading a pre-determined number of rows at a time and then providing the user with a way to request additional rows. ROInterfaceTable makes this easy by allowing you to specify a batch size.

Automatic Batch Loading

ROInterfaceTable will also load all batches by itself should you specify a per-batch delay. This will cause it to load the first batch of rows, wait a bit, load the next batch, wait a bit, and repeat until all rows have been added to the table.

Installation

CocoaPods:

pod 'ROInterfaceTable'

#import <ROInterfaceTable/ROInterfaceTable.h>

or, copy the following files into your project:

WKInterfaceTable+ROInterfaceTable.h|m
ROInterfaceTableBackingStore.h|m
ROInterfaceTableProtocol.h
ROInterfaceTableDataStore.h
ROInterfaceTableDelegate.h
ROInterfaceTable.h (umbrella header)
// Importing
#import "ROInterfaceTable.h"

Usage

First, conform to the ROInterfaceTableDataSource protocol. Only two of the methods are required to get started:

-(NSInteger)numberOfRowsInTable:(id)table section:(NSInteger)section {
  return self.fetchedResultsController.fetchedObjects.count;
}
-(NSString *)table:(id)table identifierForRowAtIndexPath:(NSIndexPath *)indexPath {
  return @"RowIdentifier"; // Make sure this is set in your storyboard!
}

Section headers & footers

-(NSInteger)numberOfSectionsInTable {
  return self.fetchedResultsController.sections.count;
}
-(NSInteger)numberOfRowsInTable:(id)table section:(NSInteger)section {
  return [][self.fetchedResultsController.sections[section] objects] count];
}
-(NSString *)table:(id)table identifierForSectionHeader:(NSInteger)section {
  return @"SectionHeaderRowController";
}
-(NSString *)table:(id)table identifierForRowAtIndexPath:(NSIndexPath *)indexPath {
  return @"RowIdentifier";
}
-(NSString *)table:(id)table identifierForSectionFooter:(NSInteger)section {
  return @"SectionFooterRowController";
}

Batch Loading You need to conform to ROInterfaceTableDelegate and set self.table.ro_delegate for the -[WKInterfaceTable table:loadedRowBatch:rowsShown:hasMoreRows:] to be called.

-(NSUInteger)numberOfRowsPerBatchInTable:(id)table {
  return 5; // Load 5 'normal' rows per batch. Headers & footers don't count
}

-(void)table:(id)table loadedRowBatch:(NSUInteger)batch rowsShown:(NSUInteger)rowsShown hasMoreRows:(BOOL)hasMoreRows {
  // Assuming loadNextBatchButton is a button you've added below the
  // WKInterfaceTable in your storyboard.
  //
  // Hide the button if no more rows are available to load
  [self.loadNextBatchButton setHidden:!hasMoreRows];

  if (hasMoreRows) {
    // Update the button's title to read 'Show Next X'
    [self.loadNextBatchButton setTitle:[NSString stringWithFormat:@"Show Next %@",
                                        @(MIN(self.fetchedResultsController.fetchedObjects.count - rowsShown,
                                        [self numberOfRowsPerBatchInTable:table]))]];
    }
}

Auto Batch Loading

-(NSUInteger)numberOfRowsPerBatchInTable:(id)table {
  return 5; // Load 5 'normal' rows per batch. Headers & footers don't count
}
-(NSTimeInterval)autoBatchLoadingDelayInTable:(id)table {
  return 3.0; // Load a batch every 3 seconds
}