Search code examples
objective-ccocoacore-datanstableviewcocoa-bindings

Core Data & NSTableView Bindings


I am trying to bind my core data to a NSTableView. I am getting information from an API then wanting to add it to NSTableView. It looks like it is setup correctly because each time I have it call the API and get information back, a blank line is added to the NSTableView data.

Why is it adding a blank line instead of the data I have it binded too?

AppController.h

@property (nonatomic, strong) NSManagedObjectContext *managedObjectContext;

I then am using the new Xcode where it auto synth's.

Items.h

@class TimeLog;

@interface Items : NSManagedObject

@property (nonatomic, retain) NSNumber * itemId;
@property (nonatomic, retain) NSString * title;
@property (nonatomic, retain) NSString * itemType;
@property (nonatomic, retain) TimeLog *relationship;

@end

Items.m

@implementation Items

@dynamic itemId;
@dynamic title;
@dynamic itemType;
@dynamic relationship;

@end

ItemObject.h

@interface ItemObject : NSObject

@property (nonatomic, retain) NSString * itemId;
@property (nonatomic, retain) NSString * title;
@property (nonatomic, retain) NSString * itemType;

@end

ItemObject.m

@implementation ItemObject

@end

Method making API Call

This method makes the API call and adds it to a temp object. It then adds that temp object to core data.

+ (void)searchForItemByType:(NSString *)itemType andId:(NSString *)searchId
{
    NSLog(@"Search Feature By ID: %@", searchId);
    RKObjectMapping *itemMapping = [RKObjectMapping mappingForClass:[ItemObject class]];

    [itemMapping addAttributeMappingsFromDictionary:@{
        @"id": @"itemId",
        @"name": @"title",
        @"item_type": @"itemType"
     }];


    RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:itemMapping pathPattern:nil keyPath:@"data" statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];

    RKObjectMapping *errorMapping = [RKObjectMapping mappingForClass:[RKErrorMessage class]];
    // The entire value at the source key path containing the errors maps to the message
    [errorMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:nil toKeyPath:@"errorMessage"]];
    NSIndexSet *statusCodes = RKStatusCodeIndexSetForClass(RKStatusCodeClassClientError);
    // Any response in the 4xx status code range with an "errors" key path uses this mapping
    RKResponseDescriptor *errorDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:errorMapping pathPattern:nil keyPath:@"error_description" statusCodes:statusCodes];
    RKObjectManager *manager = [RKObjectManager sharedManager];
    NSLog(@"HTTP Client: %@", manager.HTTPClient);

    [manager addResponseDescriptorsFromArray:@[ responseDescriptor, errorDescriptor ]];
//    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:
                            @"false", @"with_lock"
                            , nil];
    NSString *path = [NSString stringWithFormat:@"/api/v1/%@/%@", [itemType lowercaseString], searchId];
    NSLog(@"Manager: %@", manager);
    [manager getObjectsAtPath:path parameters:params success:^(RKObjectRequestOperation *operation, RKMappingResult *result) {

        NSLog(@"Results: %@", [result firstObject]);
        Items *insertItem = [NSEntityDescription insertNewObjectForEntityForName:@"Items" inManagedObjectContext:[[CoreDataHelper sharedInstance] managedObjectContext]];
        insertItem = [result firstObject];
        NSLog(@"Name: %@", [insertItem title]);

        // Handled with articleDescriptor
    } failure:^(RKObjectRequestOperation *operation, NSError *error) {
        // Transport error or server error handled by errorDescriptor
        NSLog(@"Error: %@", [error localizedDescription]);
        NSAlert *alert = [NSAlert alertWithMessageText:@"Error" defaultButton:@"OK" alternateButton:nil otherButton:nil informativeTextWithFormat:@"%@", [error localizedDescription]];
        [alert runModal];

    }];
}

Log from above code

2013-03-15 10:15:21.817 Project[59074:403] Results: <ItemObject: 0x1034ab360>
2013-03-15 10:15:21.818 Project[59074:403] ManagedObjectContext
2013-03-15 10:15:21.818 Project[59074:403] Name: Custom Mod is missing from Face Lift

IB

enter image description here

enter image description here

enter image description here

enter image description here

enter image description here

enter image description here


Solution

  • I think the problem may be in this code:

    NSLog(@"Results: %@", [result firstObject]);
    Items *insertItem = [NSEntityDescription insertNewObjectForEntityForName:@"Items" inManagedObjectContext:[[CoreDataHelper sharedInstance] managedObjectContext]];
    insertItem = [result firstObject];
    NSLog(@"Name: %@", [insertItem title]);
    

    In your log it looks like [result firstObject] is part of the 'ItemObject' class not the 'Items' class. Even though they share the same structure, 'ItemObject' does not inherit from NSManagedObject, but is being assigned to one. The system doesn't know how to translate an 'ItemObject' object into an 'Items' object so it simply keeps all the values in insertItem blank, which translates into a blank line showing up in your table. Try this instead:

    Items *insertItem = [NSEntityDescription insertNewObjectForEntityForName:@"Items" inManagedObjectContext:[[CoreDataHelper sharedInstance] managedObjectContext]];
    ItemObject *tempObject = [result firstObject];
    insertItem.itemID = tempObject.itemID;
    insertItem.title = tempObject.title;
    insertItem.itemType = tempObject.itemType;