一个NSFetchedResultsController,日期为sectionNameKeyPath

时间:2010-12-11 20:12:07

标签: iphone sorting core-data nsfetchedresultscontroller

我开发了一个使用Core Data的应用程序。在一个UITableView中,我想显示我的实体列表,按照对象的保存日期排序。当我这样做时:

fetchedResultsController = [[NSFetchedResultsController alloc]
                            initWithFetchRequest:fetchRequest
                            managedObjectContext:managedObjectContext
                              sectionNameKeyPath:@"date"
                                       cacheName:nil];

我为每个对象获取一个新部分,因为此代码也会根据秒数对日期进行分组。但我想要一个按日期分组的对象列表,但只根据日,月和年。有可能吗?怎么样?

非常感谢你的帮助!! ;)

5 个答案:

答案 0 :(得分:41)

这应该适合你:

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
  NSString *rawDateStr = [[[self.fetchedResultsController sections] objectAtIndex:section] name];
  // Convert rawDateStr string to NSDate...
  NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease];
  [formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss ZZ"];
  NSDate *date = [formatter dateFromString:rawDateStr];

  // Convert NSDate to format we want...
  [formatter setDateFormat:@"d MMMM yyyy"];
  NSString *formattedDateStr = [formatter stringFromDate:date];
  return formattedDateStr;  
}

<强> [编辑]

Jus看到了你的评论以及你想要实现的目标,你可以创建一个瞬态NSDate属性(非持久性),其格式与上面的代码类似(即没有H:mm:ss ZZZZ)并将该属性用作sectionNameKeyPath值。

简而言之,对于具有foofooDate属性的fooDateTransient对象,您会:

  1. 获取foo.fooDate属性

  2. 使用上面的代码(或类似代码)对其进行转换,并将NSDate结果分配给foo.fooDateTransient

  3. 创建fooDateTransient对象时,使用sectionNameKeyPath作为fetchedResultsController

  4. PS:我自己没有测试过,但值得一试!

    祝你好运, ROG

答案 1 :(得分:23)

退房:http://developer.apple.com/library/ios/#samplecode/DateSectionTitles/Introduction/Intro.html#//apple_ref/doc/uid/DTS40009939

它适用于月份和年份,但它很容易使它适用于日,月和年。

答案 2 :(得分:2)

以下是Swift 3解决方案,按日期排序,但部分标题与个别日期相对应。

  1. 向Core Data中的实体添加名为daySectionIdentifier的瞬态属性。
  2. 重新生成NSManagedObject子类。删除可能在daySectionIdentifier生成的Entity+CoreDataProperties.swift的属性。
  3. Entity+CoreDataClass.swift文件,为daySectionIdentifier添加以下getter:

    // Transient property for grouping a table into sections based
    // on day of entity's date. Allows an NSFetchedResultsController
    // to sort by date, but also display the day as the section title.
    //   - Constructs a string of format "YYYYMMDD", where YYYY is the year,
    //     MM is the month, and DD is the day (all integers).
    
    public var daySectionIdentifier: String? {
        let currentCalendar = Calendar.current
        self.willAccessValue(forKey: "daySectionIdentifier")
        var sectionIdentifier = ""
        if let date = self.date as? Date {
            let day = currentCalendar.component(.day, from: date)
            let month = currentCalendar.component(.month, from: date)
            let year = currentCalendar.component(.year, from: date)
    
            // Construct integer from year, month, day. Convert to string.
            sectionIdentifier = "\(year * 10000 + month * 100 + day)"
        }
        self.didAccessValue(forKey: "daySectionIdentifier")
    
        return sectionIdentfier
    }
    
  4. UITableViewController实施中,添加以下方法:

    override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        var sectionTitle: String?
        if let sectionIdentifier = fetchedResultsController.sections?[section].name {
            if let numericSection = Int(sectionIdentifier) {
                // Parse the numericSection into its year/month/day components.
                let year = numericSection / 10000
                let month = (numericSection / 100) % 100
                let day = numericSection % 100
    
                // Reconstruct the date from these components.
                var components = DateComponents()
                components.calendar = Calendar.current
                components.day = day
                components.month = month
                components.year = year
    
                // Set the section title with this date
                if let date = components.date {
                    sectionTitle = DateFormatter.localizedString(from: date, dateStyle: .medium, timeStyle: .none)
                }
            }
        }
    
        return sectionTitle
    }
    
  5. 构建NSFetchedResultsController时,请使用"daySectionIdentifier"作为sectionNameKeyPath参数调用初始值设定项。
  6. 将您的NSFetchedResultsController排序描述符设置为您实体的普通旧"date"属性。重要的是,基于"date"的排序顺序将与基于我们刚刚构建的部分标识符的排序顺序一致。
  7. 现在,您应该将表格视图按日分组(例如,&#34; 2017年2月6日和#34;),并按细粒度日期排序。

答案 3 :(得分:-1)

我认为这会更好。

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {

    // Replace DataClassObject with whatever object your using
    DataClassObject *tempObject = [[sectionInfo objects] objectAtIndex:0];

    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    [formatter setDateFormat:@"d MMMM yyyy"];
    NSString *formattedDateStr = [formatter stringFromDate:tempObject.date];
    [dateFormatter release]

    return formattedDateStr;
}

答案 4 :(得分:-1)

当遇到同样的问题时,我使用了@ BoltClock的Unicorn和@Rog的anwser。 只需将一个瞬态NSString * sectionTitle添加到我的托管对象,使用@“sectionTitle”作为sectionNameKeyPath并创建一个自定义getter,如下所示:

-(NSString *)sectionTitle
{
    NSDate *_now = [NSDate date];
    NSDate *_today = [_now dateByAddingTimeInterval: -86400.0];
    NSDate *_yesterday = [_now dateByAddingTimeInterval: -172800.0];
    NSDate *_thisWeek  = [_now dateByAddingTimeInterval: -604800.0];
    NSDate *_lastWeek  = [_now dateByAddingTimeInterval: -1209600.0];
    NSDate *_thisMonth = [_now dateByAddingTimeInterval: -2629743.0]; 
   // if better precision required use something more sophisticated for month...

   double today = [_today timeIntervalSince1970];
   double yesterday = [_yesterday timeIntervalSince1970]; 
   double thisWeek = [_thisWeek timeIntervalSince1970];
   double lastWeek = [_lastWeek timeIntervalSince1970]; 
   double thisMonth = [_thisMonth timeIntervalSince1970];

   [self willAccessValueForKey:@"timestamp"];
       double ts = [self.timestamp timeIntervalSince1970];
   [self didAccessValueForKey:@"timestamp"];

   NSString *title = @"";
   if(ts >= today) title = NSLocalizedString(@"TODAY",nil);
   else if (ts >= yesterday) title = NSLocalizedString(@"YESTERDAY",nil);
   else if (ts >= thisWeek) title = NSLocalizedString(@"THIS WEEK",nil);
   else if (ts >= lastWeek) title = NSLocalizedString(@"LAST WEEK",nil);
   else if (ts >= thisMonth) title = NSLocalizedString(@"THIS MONTH",nil);

   return title;
}