views:

423

answers:

2

Let's say, for illustration, I was writing an iTunes clone app in Cocoa, that was backed by CoreData. For simplification's sake, let's say there are two "sections", "Library" with things like Music, Movies, Radio, etc. And a second section called "Playlists" which holds user-generated playlists (just dumb lists, not smart playlists).

So the SourceList itself would typically be implemented with NSOutlineView, that's generally straightforward.

The Library section of the source list doesn't really house anything generated by the user, only "features" of the app (in essence) where the Playlists section only holds custom lists as created by the user. How would one do this with Bindings and CoreData? Is it possible just to bind the Playlists section to the user's data and have a custom way of displaying the Library features?

I'm still getting my feet wet with Bindings and AppKit in general, so please bear with me. I appreciate the help. I should add, I'm targeting 10.6 and above.

+1  A: 

Since the source list in this case is really a "scope" and not a flat list of nothing but instances of some "LibraryItem" entity, I think it's easier to implement this the "old fashioned" way (ie, table data source protocol).

This gives you precise control over grouping, how/when to mix "static" items (like "Library" and "Music", and "Movies", "Playlists") with items from your store (like the individual Playlist items under the "Playlists" section).

It's also a little easier to deal with drag and drop, in my opinion, which is key when preventing a Playlist item from being dropped upon your "Movies" group.

Joshua Nozzi
+6  A: 

I haven't had a lot of experience with core data, but I have made extensive use of Cocoa's bindings. In my experience, something like this works best with an intermediate NSArray of objects which is "manually" adjusted.

As an example, I imagine you would have a custom NSArray of playlists that are user-generated, and you would also have a separate NSArray containing your standard Library items. With this setup, I would create a property in one of your controllers called combinedArray, which would be the property that gets bound to your NSOutlineView. I would then bind your user-generated playlist array to the controller, and have some code in the controller automatically update the combined array whenever the playlist array is modified.

Here is a quick mock-up:

TheController.h

@interface TheController : NSObject
{
    NSArray * combinedArray;
    NSArray * userPlaylists;
}
@property (retain) NSArray * combinedArray;
@property (copy) NSArray * userPlaylists;
@end

TheController.m

@implementation TheController

@synthesize combinedArray;
@synthesize userPlaylists;
- (void)setUserPlaylists:(NSArray *)newLists
{
    // standard property setting code:
    if (newLists != userPlaylists)
    {
        [userPlaylists release];
        userPlaylists = [newLists copy];
    }

    // modify the combined array:
    NSMutableArray * allItems = [NSMutableArray arrayWithCapacity:0];
    [allItems addObjectsFromArray:standardLibrary];
    [allItems addObjectsFromArray:userPlaylists];
    [self setCombinedArray:allItems];
}

@end
e.James
This is sort of what I was thinking would needed to be done. So `setUserPlaylists` would be a method called by Bindings? I am incredibly foggy when it comes to how bindings work (I know their relation to KVC but how they are actually configured with Array/Tree Controllers still baffles me).
jbrennan
Yep. Cocoa takes care of all the binding magic behind the scenes. All you have to do is define a property that satisfies KVO/KVC. Any property that you @synthesize will satisfy that requirement, and any time you use [self setSomePropertyName:someValue], the appropriate KVC messages will be sent. Intercepting the property setter (as I show above) is perfectly legal. I'm not sure what your data source is for the user playlists (something from CoreData, I presume), but if you bind it to your controller, the controller will receive a `setUserPlaylists:` message whenever that list is modified.
e.James