I used NSFetchedResultController
and WKInterfaceTable
for my Apple Watch application. It is true that it is not as convenient as a UITableViewController
, but it is very doable. I don't have any performance issues, even in in loading 20+ rows (didn't try 80-90). Of course this is in the simulator, so I don't know how the devices themselves will behave.
Insert, update and delete you have to implement yourself, but is not that hard.
Below part of my code in the InterfaceController, with insert row as an example, but edit and delete is not more difficult:
Interface
...
@property (weak, nonatomic) IBOutlet WKInterfaceTable *interfaceTable;
@property(strong, nonatomic) NSFetchRequest *fetchRequest;
@property(strong, nonatomic) NSFetchedResultsController *fetchedResultsController;
@property(strong, nonatomic) NSMutableArray *data;
...
Implementation
The fetching is the same as always, except that we don't assign a delegate to the resultscontroller, but save the data directly:
self.fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"YourModel" inManagedObjectContext:self.managedObjectContext];
self.fetchRequest.entity = entityDescription;
[self.fetchRequest setSortDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"createdAt" ascending:YES]]];
self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:self.fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:nil];
[self.fetchedResultsController performFetch:&error];
self.data= self.fetchedResultsController.fetchedObjects;
I then use a function loadTableData
:
- (void)loadTableData {
[self.interfaceTable setNumberOfRows:[[self data] count] withRowType:@"YourCustomCell"];
[self.interfaceTable insertRowsAtIndexes:[NSIndexSet indexSetWithIndex:[[self data] count]] withRowType:@"YourRowType"];
for (int i = 0; i<[[self data] count];i++)
[self configureRowControllerAtIndex:i];
}
Which calls configureRowControllerAtIndex
, a function that populates one row (I have two labels):
- (void)configureRowControllerAtIndex:(NSInteger)index {
WKTableVIewRowController *listItemRowController = [self.interfaceTable rowControllerAtIndex:index];
[listItemRowController setTitle:[[self.data[index] title] integerValue]];
[listItemRowController setDescription:[self.data[index] description]];
}
When you insert a new row, just add it manually in the managedObjectContext
and in the data array:
// Add in managedObjectContext
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"YourModel" inManagedObjectContext:self.managedObjectContext];
YourModel *newRow = [[YourModel alloc] initWithEntity:entityDescription insertIntoManagedObjectContext:nil];
// Add in data array
[self.data addObject:newRow];
and regularly save the managedObjectContext:
if (![self.managedObjectContext save:&error]) {
if (error) {
NSLog(@"Unable to save changes.");
NSLog(@"%@, %@", error, error.localizedDescription);
}
}