核心数据:索引x处的获取对象具有乱序部分名称'xxxxxx。对象必须按节名称排序

时间:2012-08-27 21:50:45

标签: iphone objective-c ios core-data nsfetchedresultscontroller

我知道我不是第一个提出这个问题的人,但我真的很难过......

基本上我有一个带两个按钮的屏幕。每个按钮根据日期将数据加载到下面的桌面视图中。在第一个tableview的第一次加载时(默认选中左键),一切正常。如果我点击右键,我得到一个空白的tableview,我收到错误

  

索引x处的获取对象具有无序部分名称   “XXXXXX。对象必须按部分名称排序。

切换回左表视图,数据消失了。两个tableviews都是空的。

每个tableview有2个部分,具体取决于项目的开始时间。如果我删除部分数据显示正常。不幸的是我需要它们..数据分为两部分,如:

@interface NSString(agendaSessionKeyPath)
@property (nonatomic, readonly) NSString *sessionSection;
@end

@implementation NSString(agendaSessionKeyPath)

- (NSString *)sessionSection
{
    int timeValue = [[self stringByReplacingOccurrencesOfString:@":" withString:@""] intValue]; //turns 11:00 to 1100
    if (timeValue < 1200)
        return @"Morning";
     else
        return @"Afternoon";
}

获取请求

- (void)viewDidLoad
{
     //other viewDidLoad stuff
    [self fetchSessions];
}

根据日期从左右按钮对数据进行排序的方法:

- (void)fetchSessions
{
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
    [dateFormatter setDateFormat:@"yyyy-MM-dd"];

    NSDate* date = nil;
    if (selected == 0) //left button is selected
    {
        date = [dateFormatter dateFromString:@"2012-09-26"];
    }
    else if (selected == 1) //right button is selected
    {
        date = [dateFormatter dateFromString:@"2012-09-27"];
    }

    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"date == %@", date];
    [self.fetchedResultsController.fetchRequest setPredicate:predicate];

    NSError *error;
    if (![[self fetchedResultsController] performFetch:&error]) {
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
    }
}

获取结果控制器

- (NSFetchedResultsController *)fetchedResultsController {
    self.managedObjectContext = [[MATCDatabaseController sharedDatabaseController] managedObjectContext];
    if (_fetchedResultsController != nil) {
        return _fetchedResultsController;
    }

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"Session"];

    NSSortDescriptor *sort = [[NSSortDescriptor alloc]
                              initWithKey:@"title" ascending:YES];
    NSSortDescriptor *timeSort = [NSSortDescriptor sortDescriptorWithKey:@"timeValue" ascending:YES];
    [fetchRequest setSortDescriptors:@[timeSort, sort]];
    [fetchRequest setFetchBatchSize:20];

    NSFetchedResultsController *theFetchedResultsController =
    [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
                                        managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"startTime.sessionSection"
                                                   cacheName:nil];

    self.fetchedResultsController = theFetchedResultsController;
    [self.fetchedResultsController setDelegate:self];

    return _fetchedResultsController;

}

任何帮助表示赞赏!

2 个答案:

答案 0 :(得分:22)

好的,我确实快速看了一眼。

使用以下命令初始化FRC:

[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
                                    managedObjectContext:self.managedObjectContext
                                      sectionNameKeyPath:@"startTime.sessionSection"
                                               cacheName:nil];

告诉它你的章节标题是通过关键路径startTime.sessionSection获得的。

现在,给予FRC的获取请求的第一个排序描述符将用于对这些部分进行排序。您首先提供的排序描述符适用于timeValue,这似乎不正确。

您的第一个排序描述符应指定节标题的排序。改变这一点,你可能会很高兴。

修改

  

谢谢大家的信息。我虽然还有点失落。你的意思是   我应该在startTime.sessionSection之前添加一个排序描述符   将它分配给sectionNameKeyPath?我试过了,但还是没有运气。   timeValue和startTime.sessionSection是相关的。可能是吗?    - 发牢骚

您必须确保第一个排序描述符将根据该部分正确排序数据。在你的情况下,时间被转换成单词。您的初始排序描述符是有时间的,当数据按时间排序时,这些部分没有正确排序,这会导致您的错误。

第一个排序描述符必须满足节数据。所以,最初,我会尝试......

[fetchRequest setSortDescriptors:@[
    [NSSortDescriptor sortDescriptorWithKey:@"startTime.sessionSection"
                                  ascending:NO],
    [NSSortDescriptor sortDescriptorWithKey:@"timeValue"
                                  ascending:YES],
    [NSSortDescriptor sortDescriptorWithKey:@"title"
                                  ascending:YES] ];

注意,如果您有大量的数据,您可能会发现您的部分机制变慢。如果发生这种情况,您可能希望将此部分数据添加到数据库中。

答案 1 :(得分:0)

我也有类似的问题,也许有人觉得它很有用。

我从数据库中获取了财务交易,并按月划分了它们。

DB具有属性trDate - 这是一个交易日期。但是trMonth是一个短暂的属性,如:

- (NSString*)trMonth {
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"LLLL"];
[dateFormatter setLocale:[NSLocale currentLocale]];

return [dateFormatter stringFromDate:trDate];
}

它在FetchResultsController中使用如下:

...
NSSortDescriptor *sortDate = [[NSSortDescriptor alloc] initWithKey:@"trDate" ascending:YES];

[fetchRequest setSortDescriptors:@[sortDate]];

NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"trMonth" cacheName:nil];
...

哪个在生产中运作良好,但是一旦应用程序开始崩溃,并且在发现根问题之后我发现在7月:2014年7月和2015年7月有两个交易(例如)。那就是崩溃点为trDate 2014年7月排序好&lt; 2015年7月,但我的方法将它们视为同月。该解决方案不仅用作月份名称,还用作年份:

- (NSString*)trMonthYear {
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"LLLL yyyy"]; // added year also
[dateFormatter setLocale:[NSLocale currentLocale]];

return [dateFormatter stringFromDate:trDate];
}