22

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

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

}

任何帮助表示赞赏!

4

2 回答 2

26

好的,我确实快速浏览了一下。

您使用以下命令初始化 FRC:

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

这告诉它您的部分标题将通过 key path 获得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] ];

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

于 2012-08-27T23:39:20.573 回答
0

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

我从 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 7 月排序良好2014 < 2015 年 7 月,但我的方法认为它们是同一个月。该解决方案不仅将月份名称用作部分名称,而且将年份用作部分名称:

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

return [dateFormatter stringFromDate:trDate];
}
于 2015-09-15T07:44:25.673 回答