如何将NSOutlineview与Coredata一起使用,按实体对属性进行分组?

时间:2013-08-25 15:58:08

标签: objective-c core-data nsoutlineview

我很生气。我已经坚持了两天,谷歌搜索,阅读,谷歌搜索和阅读。

我有一个名为Session的实体,其名称为sessionYear(NSNumber)。

我想创建一个NSOutlineView,它将按年分组,然后按月分类sessionMonth(NSString)。像这样:

  

1984

     
    

十月
       十一月
       腊

  
     

1989

     
    

一月
       二月

  
     

2002

     
    

三月
        七月
        十月

  

我发现了很多关于在其他实体下分组实体的信息,以及使用数组控制器和字典的各种方法。不幸的是,我发现的大部分内容已经过时或者表面上看不适用于我的情况。我是一般的开发和coredata的新手,并希望得到任何指导。

同样,岁月是实体的属性。

最终,我希望能够点击这些实体并填充tableview。如果可能的话,我有兴趣用绑定来做这件事,但我一直无法找到可靠的信息。任何帮助或资源链接都表示赞赏。

编辑:

我使用了NSOutlineViewDelegate方法和附加的四种方法。但是,现在似乎sessionMonths在年份扩展后出现在视图中,然后立即消失。如果扩展了另一个(不同的)年份,则所有sessionMonths出现在应该的位置,并且会立即消失。我到目前为止......只是为了一瞥。关于从哪里开始的任何建议?

- (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;
}

2 个答案:

答案 0 :(得分:0)

在NSOutline视图的属性检查器中,将突出显示设置为源列表。

答案 1 :(得分:0)

最好的方法可能是为顶级组和每组子组创建单独的数组。因此,请列出您要显示的所有独特年份。您可以使用集合运算符@distinctUnionOfObjects.sessionYear从现有的Session数组中获取一组NSNumbers。

下面的一些示例代码 - 我没有运行此代码,但从现有应用程序中获取了一些代码并重命名以适合您的模型。可能会有一些错误。

    @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