iPhone 按日期排序核心数据 NSFetchedResultsController

Posted

技术标签:

【中文标题】iPhone 按日期排序核心数据 NSFetchedResultsController【英文标题】:iPhone by-date sorting core data NSFetchedResultsController 【发布时间】:2010-12-05 18:11:27 【问题描述】:

我正在开发的程序是“CoreDataBooks”的修改版本,取自 Apple iPhone 示例代码。在“CoreDataBooks”中有一个作者列表,其中一些作者有多本书。设置导航控制器,按作者姓名划分部分。在每个部分中,都有每个作者的书籍列表。

所以我使用了这段代码,并试图制作一个按部分排列的名称列表。我的实体被称为“病人”。每个实体都有属性 myDate 和 myName 以及其他一些属性。我想按 myDate 排列部分,每个部分中都有一个名称列表,所有这些都具有相同的日期。

我在使用 NSFetchedResultsController 方法时遇到了困难。当使用日期选择器创建日期时,它们都有一个时间戳。此时间戳使它们不同,如​​果您在 sectionNameKeyPath 方法中按 myDate 排序,它们将被放置到单独的部分中。

我在网上进行了相当广泛的搜索,并提出了以下解决方案。您创建另一个瞬态属性,一个 NSString,然后使用它对部分进行排序。这是通过创建一个日期格式化程序来完成的,如下所示。我包括了我的 NSString 的 setter,以及 NSFetchedResultsController 方法。

任何帮助将不胜感激。

- (NSFetchedResultsController *)fetchedResultsController 

    if (fetchedResultsController != nil) 
        return fetchedResultsController;
    

 PatientsAppDelegate*appDelegate=[[UIApplication sharedApplication]delegate];
 NSManagedObjectContext*managedObjectContext=appDelegate.managedObjectContext;

 // Create and configure a fetch request with the Book entity.
 NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
 NSEntityDescription *entity = [NSEntityDescription entityForName:@"Patient" inManagedObjectContext:managedObjectContext];
 [fetchRequest setEntity:entity];

 // Create the sort descriptors array.
 NSSortDescriptor *dateDescriptor = [[NSSortDescriptor alloc] initWithKey:@"myDate" ascending:YES];
 NSSortDescriptor *nameDescriptor = [[NSSortDescriptor alloc] initWithKey:@"myName" ascending:YES];
 NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:dateDescriptor, nameDescriptor, nil];
 [fetchRequest setSortDescriptors:sortDescriptors];

// NSLog(@"%@",myFormattedDate);

 // Create and initialize the fetch results controller.
 NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest 
                        managedObjectContext:managedObjectContext 
                          sectionNameKeyPath:@"transactionDay" 
                             cacheName:@"Root"];
 self.fetchedResultsController = aFetchedResultsController;
 fetchedResultsController.delegate = self;

 // Memory management.
 [aFetchedResultsController release];
 [fetchRequest release];
 [dateDescriptor release];
 [nameDescriptor release];
 [sortDescriptors release];

 return fetchedResultsController;
 

- (NSString *)transactionDay
 [self willAccessValueForKey:@"transactionDay"];
 NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setDateFormat:@"MM dd,yyyy"];
 NSString*someString=[dateFormatter stringFromDate:[self valueForKey:@"myDate"]];
 [self didAccessValueForKey:@"transactionDay"];
 return someString;

我得到的当前错误是“实体 Patient 不符合键“transactionDay”的键值编码”

再次感谢。

【问题讨论】:

不要使用“[code]”标签。使用“101010”按钮格式化代码。 【参考方案1】:

在指定sectionNameKeyPath 时,您必须包含要应用瞬态属性的实体属性(即entityAttribute.transientAttribute)。因此,如果您有一个实体Patient,其属性myDate 类型为NSDate

// Create and initialize the fetch results controller.
NSFetchedResultsController *aFetchedResultsController = 
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest 
                                    managedObjectContext:managedObjectContext 
                                      sectionNameKeyPath:@"myDate.transactionDay" 
                                               cacheName:@"Root"];

可以在Patient 实现文件中定义瞬态属性,方法是在顶部添加以下内容:

@implementation NSDate (TransactionDayFormat)

- (NSString *)transactionDay
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setDateFormat:@"MM dd,yyyy"];
    NSString*someString=[dateFormatter stringFromDate:self];
    return someString;


@end

@implementation Patient
...

transactionDay 将进一步处理您的myDate 属性,允许您将部分指定为更严格的格式。请注意,NSDateFormatter 是一个非常庞大的初始化对象,因此为了提高效率,提前声明它并稍后引用它可能是值得的。

【讨论】:

【参考方案2】:

-transactionDay 方法应该是您在 Patient 类上实现的属性,然后这个类(我猜是视图控制器)可以选择基于它进行排序或分区。

【讨论】:

【参考方案3】:

听起来您正在尝试使用尚未在 Patient 的对象模型中声明为属性的 sectionNameKeyPath 来初始化 fetchedResultsController。

您能否确认 transactionDay 在您的 Patient 对象模型中被定义为 NSString 属性?

此外,这听起来有点绕圈子来实现您想要实现的目标。也许您应该尝试从您的 NSDate 属性中删除时间戳?我对 SO 进行了快速搜索,可以找到删除 NSDate 时间戳的可能解决方案

-(NSDate *)dateWithOutTime:(NSDate *)datDate
    if( datDate == nil ) 
        datDate = [NSDate date];
    
    NSDateComponents* comps = [[NSCalendar currentCalendar] components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit fromDate:datDate];
    return [[NSCalendar currentCalendar] dateFromComponents:comps];

问题的链接是Removing time components from an NSDate object using Objective C/Cocoa

【讨论】:

以上是关于iPhone 按日期排序核心数据 NSFetchedResultsController的主要内容,如果未能解决你的问题,请参考以下文章

使用 FetchedResultsController 按日期对核心数据进行排序

从按格式化日期排序的核心数据中获取

按日期和字符对核心数据属性进行排序

从核心数据中按日期对 TableView 进行排序 - Swift4

核心数据按格式化日期排序表格视图

核心数据聊天应用获取一批按日期排序的消息