【问题标题】:Core data: The fetched object at index x has an out of order section name 'xxxxxx. Objects must be sorted by section name核心数据:在索引 x 处获取的对象有一个乱序的部分名称'xxxxxx。对象必须按部分名称排序
【发布时间】:2012-08-22 10:05:23
【问题描述】:

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

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

在索引 x 处获取的对象有一个乱序的部分名称 'xxxxxx。对象必须按部分名称排序。

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

每个 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;

}

感谢任何帮助!

【问题讨论】:

  • 虽然您提供了相当多的代码,但您期望发生什么以及您实际遇到什么问题(以及标题中的错误何时发生)并不明显。请提供更多上下文。如果没有更好地描述问题,没有多少人会通读代码。
  • 感谢您的反馈。我将使用更多信息编辑问题。

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


【解决方案1】:

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

我从 DB 中获取金融交易并按月份划分。

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 月

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

return [dateFormatter stringFromDate:trDate];
}

【讨论】:

  • 这行得通吗? NSFetchedResultsController 最终不会将 trMonthYear 属性排序为字符串吗?那么“2017 年 4 月”
【解决方案2】:

好的,我确实看了一下。

您使用以下命令初始化 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] ];

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

【讨论】:

  • 是的。我以前也遇到过同样的问题,这就是解决方案。首先按与节索引相同的键路径排序,然后按节内的任何行排序。
  • 感谢大家提供的信息。不过我还是有点失落。你的意思是我应该在startTime.sessionSection 上添加一个排序描述符,然后再将它分配给sectionNameKeyPath?我试过了,但仍然没有运气。 timeValue 和 startTime.sessionSection 是相关的。会这样吗?
  • 说“我试过了,但还是没有运气”并不能说明你尝试了什么、你是如何做到的以及你得到了什么结果。
  • 嗨乔迪。你说得对。对不起。我所做的是在我的fetchedResultsController 中创建一个排序描述符,如下所示:NSSortDescriptor *sectionSort = [NSSortDescriptor sortDescriptorWithKey:@"startTime.sessionSection" ascending:YES]; 即使使用额外的排序描述符,我也没有看到任何变化。第二次加载时,表格视图始终为空。我实际上解决了它,它与我的想法完全无关。 This question 帮助了我。无论如何感谢您的帮助。
  • 多哈。我试图猜测您的问题是什么,并将初始排序描述符归零,因为这是一个常见错误。我完全忽略了 sessionSection。再见。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-09
  • 2014-06-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多