Objective c 如何将NSOutlineview与Coredata一起使用,根据实体的属性对其进行分组?

Objective c 如何将NSOutlineview与Coredata一起使用,根据实体的属性对其进行分组?,objective-c,core-data,nsoutlineview,Objective C,Core Data,Nsoutlineview,我累了。我已经在这上面呆了两天了,谷歌,阅读,谷歌,阅读 我有一个名为Session的实体,还有一个名为sessionYear(NSNumber)的属性 我想创建一个NSOutlineView,它将按年份对它们进行分组,然后按月份对它们进行排序,sessionMonth(NSString)。像这样: 1984年 十月 十一月 十二月 1989年 一月 二月 2002年 三月 七月 十月 我发现了很多关于在其他实体下分组实体的信息,以及使用数组控制器和字典的各种方法。不幸的是,我发现的很多东西都过

我累了。我已经在这上面呆了两天了,谷歌,阅读,谷歌,阅读

我有一个名为
Session
的实体,还有一个名为
sessionYear
(NSNumber)的属性

我想创建一个NSOutlineView,它将按年份对它们进行分组,然后按月份对它们进行排序,
sessionMonth
(NSString)。像这样:

1984年

十月
十一月
十二月

1989年

一月
二月

2002年

三月
七月
十月

我发现了很多关于在其他实体下分组实体的信息,以及使用数组控制器和字典的各种方法。不幸的是,我发现的很多东西都过时了,或者表面上不适合我的情况。一般来说,我对开发和使用coredata还不熟悉,希望您能给予指导

同样,年份是实体的属性

最后,我希望能够单击这些实体并填充tableview。如果可能的话,我会对绑定感兴趣,但我一直无法找到可靠的信息。感谢您的帮助或资源链接

编辑:

我使用了NSOutlineViewDelegate方法和附加的四种方法。然而,现在看来,当一年被扩展,然后立即消失时,SessionMonth出现在视图中。如果另一个(不同的)年份被扩展,所有的会期都会出现在它们应该出现的地方,然后立即消失。我已经走了这么远。。。只看一眼。关于从哪里开始有什么建议吗

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

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

最佳方法可能是为顶级组和每组子级创建单独的数组。因此,获得一份您想要显示的所有独特年份的列表。您可以使用collection操作符
@distinctUnionOfObjects.sessionYear
从现有会话数组中获取NSNumber数组

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

    @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
@实现会话OutlineViewController{
NSArray*分拣机阵列;
NSMutableDictionary*childrenDictionary;//对于每个键(年份),我们在此字典中放置一个会话数组
}
@结束
@实现SessionOutlineViewController
-(无效)草签{
NSArray*sessions=[self-getData:@“Session”sortKey:@“date”谓词:nil];
//获得不同年份的数组
NSArray*yearray=[sessions valueForKeyPath:@“@distinctUnionOfObjects.sessionYear]”;
NSSortDescriptor*排序=[[NSSortDescriptor alloc]initWithKey:@“description”升序:是];
NSArray*SortedeArray=[yearsArray SortedDarray UsingDescriptor:[NSArray arrayWithObject:sort]];
用于(NSNumber阵列中的年份){
NSPredicate*谓词=[NSPredicate谓词格式:@“sessionYear==%@”,年份];
NSArray*sessionForYear=[self-getData:@“Session”排序键:@“date”谓词:谓词];
[childrenDictionary setObject:sessionsForYear-forKey:year];
}
}
-(NSArray*)getData:(NSString*)entityName sortKey:(NSString*)sortKey谓词:(NSPredicate*)谓词
{
NSFetchRequest*req=[[NSFetchRequest alloc]init];
NSEntityDescription*实体=[NSEntityDescription entityForName:entityName inManagedObjectContext:_managedObjectContext];
如果(实体==nil){
NSLog(@“错误实体%@未找到!”,entityName);
返回零;
}
[req setEntity:实体];
[req SETINCLUDEPROPERTYVALUES:是];
if(谓词!=nil)
[req setPredicate:谓词];
如果(排序键!=nil){
NSSortDescriptor*indexSort=[[NSSortDescriptor alloc]initWithKey:sortKey升序:YES];
NSArray*排序器=[NSArray arrayWithObject:indexSort];indexSort=nil;
[请求设置分拣描述符:分拣机];
}
n错误*错误;
NSArray*结果=[managedObjectContext executeFetchRequest:req错误:&错误];
如果(结果==nil)
返回零;
返回结果;
}
@结束
@实现SessionOutlineViewController(NSOutlineViewDataSource)
-(NSArray*)子项:(id)项{
NSArray*儿童;
如果(项目==零){
children=sorted数组;
}否则{
children=[childrenDictionary objectForKey:item];
}
返回儿童;
}
-(id)大纲视图:(NSOutlineView*)大纲视图子项:(NSInteger)项的索引:(id)项{
return[[self childrenForItem:item]objectAtIndex:index];
}
-(BOOL)大纲视图:(NSOutlineView*)大纲视图可扩展:(id)项{
if([outlineView parentForItem:item]==nil){
返回YES;
}否则{
返回否;
}
}
-(NSInteger)大纲视图:(NSOutlineView*)大纲视图儿童雷诺数项目:(id)项目{
返回[[self childrenForItem:item]计数];
}
@结束