ioscore-datawatchkitwatchos-2wkinterfacetable

WatchKit, Core Data and tables


I have a published app and now I want to build in a watch extension that will just present a table on the watch populated with data from my core data store. Very simple for now. So I basically tried to use the code I have in my app tableviewcontroller modified for the watch extension. I have the app group in place, and created a core data class that both the app and the watch extension can access. And although that seems to be working fine in the watch extension based on the debug logs, I am not getting any data in the watch table when I run the app on the watch. The code and debug logs are below:

InterfaceController.h

#import <WatchKit/WatchKit.h>
#import <Foundation/Foundation.h>
#import "CoreDataHelper.h"

@interface InterfaceController : WKInterfaceController

@property (strong, nonatomic) IBOutlet WKInterfaceTable *table;
@property (strong, nonatomic) NSArray *objects;

@end

InterfaceController.m:

#import "InterfaceController.h"
#import "ScheduleTableRow.h"

@interface InterfaceController()

@end

@implementation InterfaceController

@synthesize objects; 

- (void)awakeWithContext:(id)context {
[super awakeWithContext:context];

// Configure interface objects here.

NSManagedObjectContext * managedContext = [[CoreDataHelper sharedHelper] context];

NSEntityDescription *entity = [NSEntityDescription entityForName:@"Cschedule" inManagedObjectContext:managedContext];

NSManagedObject *object = [[NSManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:managedContext];

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];

[fetchRequest setEntity:entity];

NSArray *myResults = [managedContext executeFetchRequest:fetchRequest error:nil];

self.objects = myResults;

NSLog(@"Results count: %lu", (unsigned long)myResults.count);

[self.table setNumberOfRows:myResults.count withRowType:@"ScheduleTableRow"];

for (object in myResults) {

    ScheduleTableRow *scheduleRow = [self.table rowControllerAtIndex:[myResults indexOfObject:object]];
    [scheduleRow.name setText:[NSString stringWithFormat:@"%@",[object valueForKey:@"day"]]];
    [scheduleRow.date setText:[NSString stringWithFormat:@"%@",[object valueForKey:@"date"]]];
}

}

- (void)willActivate {
// This method is called when watch view controller is about to be visible to user
[super willActivate];
}

- (void)didDeactivate {
// This method is called when watch view controller is no longer visible
[super didDeactivate];
}

@end

DEBUG LOG:

2015-11-17 15:07:12.143 canada2016Watch Extension[89456:1406057] Running CoreDataHelper 'init'
2015-11-17 15:07:12.148 canada2016Watch Extension[89456:1406057] Running CoreDataHelper 'setupCoreData'
2015-11-17 15:07:12.148 canada2016Watch Extension[89456:1406057] Running CoreDataHelper 'loadStore'
2015-11-17 15:07:12.148 canada2016Watch Extension[89456:1406057] Running CoreDataHelper 'storeURL'
2015-11-17 15:07:12.148 canada2016Watch Extension[89456:1406057] Running CoreDataHelper 'applicationStoresDirectory'
2015-11-17 15:07:12.148 canada2016Watch Extension[89456:1406057] Running CoreDataHelper 'applicationDocumentsDirectory'
2015-11-17 15:07:12.159 canada2016Watch Extension[89456:1406057]    Successfully added store: <NSSQLCore: 0x7b8692b0> (URL:   file:///Users/barry/Library/Developer/CoreSimulator/Devices/E7C26A87-B22C-45C5-9AE3-18CB24393EA9/data/Containers/Data/PluginKitPlugin/6717F002-7F1B-44EB-8C9F-861B6CF01E08/Documents/Stores/group.org.bicsi.canada2016app)
2015-11-17 15:07:12.160 canada2016Watch Extension[89456:1406057] Results count: 1

Solution

  • Maybe you misunderstood the rowControllerAtIndex method. This method is the actual place where you add rows to your table. Instead, you reference the index as indexOfObject although the table does not have any objects yet.

    Instead, you should loop through your indexes, create an item for each row and populate it with the appropriate object.

    for (int i = 0; i < self.objects.count; i++) {
       ScheduleTableRow *scheduleRow = [self.table rowControllerAtIndex:i];
       NSManagedObject *item = self.objects[i];
       scheduleRow.name.text = [item valueForKey:@"day"];
       scheduleRow.date.text = [item valueForKey:@"date"];
    }
    

    Much more elegant in Swift

    for (idx, object) in self.objects.enumerate() {
       let scheduleRow = self.table.rowControllerAtIndex(idx)
       scheduleRow.name.text = object.valueForKey("day")
       scheduleRow.date.text = object.valueForKey("date")
    }