NSFetchedResultsController с датой в виде sectionNameKeyPath - PullRequest
22 голосов
/ 11 декабря 2010

Я разрабатываю приложение, которое использует Core Data. В одном UITableView я хочу отобразить список моих сущностей, отсортированный по дате сохранения объектов. Когда я делаю это:

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

Я получаю для каждого объекта новый раздел, потому что этот код также группирует даты по секундам. Но я хочу список объектов, сгруппированных по дате, но только по дню, месяцу и году. Возможно ли это и как?

Большое спасибо за вашу помощь !! ;)

Ответы [ 5 ]

41 голосов
/ 12 декабря 2010

Это должно помочь вам:

- (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;  
}

[EDIT]

Jus видел ваш комментарий, и для того, что вы пытаетесь достичь, вы можете создать временный атрибут NSDate (непостоянный), который отформатирован аналогично приведенному выше коду (т. Е. Без H: mm: ss ZZZZ) и используйте этот атрибут в качестве значения sectionNameKeyPath.

Итак, в двух словах для объекта foo, с атрибутами fooDate и fooDateTransient, вы бы:

  1. Получите ваш foo.fooDate атрибут

  2. Преобразуйте его, используя код выше (или аналогичный), и присвойте результат NSDate foo.fooDateTransient

  3. Используйте fooDateTransient в качестве sectionNameKeyPath при создании объекта fetchedResultsController.

PS: Я сам не проверял, но стоит попробовать!

Удачи, Рог

23 голосов
/ 10 апреля 2011

Выезд: http://developer.apple.com/library/ios/#samplecode/DateSectionTitles/Introduction/Intro.html#//apple_ref/doc/uid/DTS40009939

Он работает с месяцем и годом, но его довольно просто заставить работать с днем, месяцем и годом.

3 голосов
/ 07 февраля 2017

Ниже приведено решение Swift 3 для сортировки по дате, но заголовки разделов соответствуют отдельным дням.

  1. Добавьте временное свойство с именем daySectionIdentifier к вашей сущности в Базовых данных.
  2. Восстановите ваш NSManagedObject подкласс. Удалите свойство для daySectionIdentifier, которое может быть сгенерировано в Entity+CoreDataProperties.swift.
  3. К файлу Entity+CoreDataClass.swift добавьте следующий геттер для daySectionIdentifier:

    // 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" будет соответствовать порядку сортировки на основе только что созданного идентификатора раздела.

Теперь вы должны сгруппировать табличное представление по дням (например, «6 февраля 2017 г.») и отсортировать по точной дате.

0 голосов
/ 28 апреля 2012

Я использовал @ BoltClock's Unicorn и @ Rog's anwser, когда возникла та же проблема.Просто добавил временный NSString * sectionTitle в мой управляемый объект, использовал @ "sectionTitle" в качестве sectionNameKeyPath и создал собственный метод получения, например, так:

-(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;
}
0 голосов
/ 09 августа 2011

Думаю, так будет лучше.

- (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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...