Search code examples
objective-ccocoamacoscore-datansarraycontroller

How do you populate a NSArrayController with CoreData rows programmatically?


After several hours/days of searching and diving into example projects I've concluded that I need to just ask. If I bind the assetsView (IKImageBrowserView) directly to an IB instance of NSArrayController everything works just fine.

- (void) awakeFromNib
{
    library = [[NSArrayController alloc] init];
    [library setManagedObjectContext:[[NSApp delegate] managedObjectContext]];
    [library setEntityName:@"Asset"];       

    NSLog(@"%@", [library arrangedObjects]);
    NSLog(@"%@", [library content]);

    [assetsView setDataSource:library];
    [assetsView reloadData];
}

Both NSLogs are empty. I know I'm missing something... I just don't know what. The goal is to eventually allow multiple instances of this view's "library" filtered programmatically with a predicate. For now I'm just trying to have it display all of the rows for the "Asset" entity.

Addition: If I create the NSArrayController in IB and then try to log [library arrangedObjects] or manually set the data source for assetsView I get the same empty results. Like I said earlier, if I bind library.arrangedObjects to assetsView.content (IKImageBrowserView) in IB - with same managed object context and same entity name set by IB - everything works as expected.

- (void) awakeFromNib
{
//  library = [[NSArrayController alloc] init];
//  [library setManagedObjectContext:[[NSApp delegate] managedObjectContext]];
//  [library setEntityName:@"Asset"];       

    NSLog(@"%@", [library arrangedObjects]);
    NSLog(@"%@", [library content]);

    [assetsView setDataSource:library];
    [assetsView reloadData];
}

Solution

  • It looks like the problem is that you have not actually told the NSArrayController to fetch anything. NSArrayControllers are empty until you add objects either through bindings or manually.

    After setting up library try to call its fetch method:

    [library fetch:self];
    

    Also, you probably know this already but it is possible to set bindings in code with the following method:

    - (void)bind:(NSString *)binding toObject:(id)observableController withKeyPath:(NSString *)keyPath options:(NSDictionary *)options