Pregunta

I'm fried. I've been stuck on this for two days, googling, and reading, googling and reading.

I have an entity called Session and with an attribute called sessionYear (NSNumber).

I'd like to create an NSOutlineView that will group them by year and then sort them by month, sessionMonth (NSString). Like this:

1984

October
November
December

1989

January
February

2002

March
July
October

I've found lots of information about grouping entities under other entities, and various methods of using array controllers and dictionaries. Unfortunately, much of what I found was outdated or not ostensibly applicable to my situation. I'm new to developing and coredata in general, and would appreciate any guidance on this.

Again, the years are attributes of the entities.

Eventually, I want to be able to click on these entities and populate a tableview. I'd be interested in doing this with bindings if possible, but I've been unable to find solid information. Any help, or links to resources are appreciated.

EDIT:

I've used the NSOutlineViewDelegate approach with the appending four methods. However, now it seems the sessionMonths appear in the view when the year is expanded and then immediately disappear. If another (different) year is expanded all sessionMonths appear where they should and again immediately disappear. I've come so far... for only a glimpse. Any suggestions about where to start?

- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item {
    if (item == nil) {
        return [savedSessionsOutlineViewData count];
    }

    return [item count];
}

- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item {
    if (item == nil) {
        item = savedSessionsOutlineViewData;
    }

    if ([item isKindOfClass:[NSMutableArray class]]) {
        return [item objectAtIndex:index];
    }
    else if ([item isKindOfClass:[NSDictionary class]]) {
        NSArray *keys = [item allKeys];
        return [item objectForKey:[keys objectAtIndex:index]];
    }
    return nil;
}

- (id)outlineView:(NSOutlineView *)outline objectValueForTableColumn:(NSTableColumn *)column byItem:(id)item {

    // If the item is a "yearArray" holding sessions.
   if ([item isKindOfClass:[NSMutableArray class]]) {
        NSArray *keys = [savedSessionsOutlineViewData allKeysForObject:item];
        return [keys objectAtIndex:0];
   } else if ([item isKindOfClass:[Session class]]) {
       //NSLog (@"Item returned isKindOfClass:Session");
       return [item valueForKey:@"sessionMonth"];
   }

    return nil;
}
- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item {
    if ([item isKindOfClass:[NSMutableArray class]] || [item isKindOfClass:[NSDictionary class]]) {
        if ([item count] > 0) {
            return YES;
        }
    }

    return nil;
}
¿Fue útil?

Solución

In the attributes inspector for the NSOutline view, set the highlight to source list.

Otros consejos

The best approach may be to create separate arrays for the top level groups and for each set of children. So get a list of all the unique years you want to display. You could use the collection operator @distinctUnionOfObjects.sessionYear to get an array of NSNumbers from the existing array of Session(s).

Some sample code below - I have not run this but took some code from an existing app and renamed to fit your model. There may be some mistakes..

    @implementation SessionOutlineViewController <NSOutlineViewDataSource> {

        NSArray *sortedYearsArray;  
        NSMutableDictionary *childrenDictionary;  // for each key (year) we put an array of sessions in this dictionary

    }
    @end

    @implementation SessionOutlineViewController

    - (void)initialise {
        NSArray* sessions = [self getData:@"Session" sortKey:@"date" predicate:nil];

        // Get an array of distinct years
        NSArray *yearsArray = [sessions valueForKeyPath:@"@distinctUnionOfObjects.sessionYear"];

        NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"description" ascending:YES];
        NSArray * sortedYearsArray =[yearsArray sortedArrayUsingDescriptors:[NSArray arrayWithObject:sort]];


        for (NSNumber year in sortedYearsArray) {
            NSPredicate *predicate = [NSPredicate predicateWithFormat:@"sessionYear == %@", year];

            NSArray * sessionForYear = [self getData:@"Session" sortKey:@"date" predicate:predicate];

            [childrenDictionary setObject:sessionsForYear forKey:year];

        }

    }


- (NSArray*)getData:(NSString*)entityName sortKey:(NSString*)sortKey predicate:(NSPredicate*)predicate
{

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

    NSEntityDescription * entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:_managedObjectContext];

    if (entity == nil) {
        NSLog(@" error entity %@ NOT FOUND!", entityName);
        return nil;
    }

    [req setEntity:entity];
    [req setIncludesPropertyValues:YES];
    if (predicate != nil)
        [req setPredicate:predicate];
    if (sortKey != nil) {
        NSSortDescriptor *indexSort = [[NSSortDescriptor alloc] initWithKey:sortKey ascending:YES];
        NSArray *sorters = [NSArray arrayWithObject:indexSort]; indexSort = nil;

        [req setSortDescriptors:sorters];
    }

    NSError *error;

    NSArray *result = [managedObjectContext executeFetchRequest:req error:&error];
    if (result == nil)
        return nil;

    return result;
}
@end

@implementation SessionOutlineViewController (NSOutlineViewDataSource)

- (NSArray *)childrenForItem:(id)item {
    NSArray *children;
    if (item == nil) {
        children = sortedYearsArray;
    } else {
        children = [childrenDictionary objectForKey:item];
    }
    return children;
}

- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item {
    return [[self childrenForItem:item] objectAtIndex:index];
}

- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item {
    if ([outlineView parentForItem:item] == nil) {
        return YES;
    } else {
        return NO;
    }
}

- (NSInteger) outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item {
    return [[self childrenForItem:item] count];
}
@end
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top