Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSFetchResultController for showing records on an Apple Watch?

Can I use NSFetchResultController on an Apple Watch to show 80 to 90 records in table?

I am using WKInterfaceTable+IGInterfaceDataTable to make use of datasource type loading methods because that seems to me simple than using NSArray.

Will NSFetchResultController help in increasing efficiency or it will make it slow?

like image 908
Iqbal Khan Avatar asked Apr 08 '15 07:04

Iqbal Khan


2 Answers

I found that NSFetchResultController is not useful at all in iWatch app because WKInterfaceTable does not support delegate method for edit, changes or delete for a single row that NSFetchResultController support in delegate. so you will have to update all data that you want to show each time so i think we should not use it.

like image 148
Iqbal Khan Avatar answered Oct 09 '22 01:10

Iqbal Khan


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);
    }
}
like image 39
Wouter Avatar answered Oct 09 '22 02:10

Wouter