Использование пользовательских разделов с NSFetchedResultsController?

Я делаю секционированную таблицу с извлеченными результатами, но мне сложно сработать настраиваемые разделы.

Как правило, просто нужно иметь атрибут для сортировки и использовать sectionNameKeyPath: для генерации разделов. Но мой атрибут сортировки вычисляется "на лету", и я не могу заставить fetchedResultsController использовать его правильно...

Обновление: Используя jbrennan ниже, я действительно близок к предполагаемой функциональности. Я добавил категорию в NSDate, которая возвращает число "дней назад"; введя здесь здесь, вы получите разделы, основанные на этих числах:

NSFetchedResultsController *aFetchedResultsController =
    [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
    managedObjectContext:managedObjectContext
    sectionNameKeyPath:@"myDateAttribute.daysAgo"
    cacheName:@"Root"];

Здесь, где я застрял: мне не нужны они отсортированы "днями назад", они мне нужны, они отсортированы с помощью некоторых вычислений на основе других атрибутов в сущности. Поэтому я не могу просто вызвать этот настраиваемый метод Category, мне нужно вызвать метод с аргументами, например:

[myDateAttribute sortingRoutine:thisObject.value]

Или что-то в этом роде. Надеюсь, это имеет определенный смысл. Спасибо, если вы можете помочь:)

Ответы

Ответ 1

Вы можете попробовать следующее.

Добавить переходный атрибут в вашу основную модель данных в объекте Task. Затем выполните

- (void)awakeFromFetch

в классе Task NSManagedObject. См. Его документацию. В рамках метода вы можете установить значение для свойства переходного процесса, используя значения других свойств. Обратите внимание, что есть некоторые ограничения на то, что вы можете сделать, но это хорошо объяснено в документации (в частности, вы не можете изменять отношения или передавать аргументы, однако, если вы можете вычислить свойство переходного процесса, используя только значения других свойств/отношения это должно быть прекрасно).

Как только вы это сделаете, вы просто используете свойство переходного процесса как атрибут, который вы передаете, чтобы вернуть разделы.

Ответ 2

Я сделал что-то подобное этому в (скоро появляющемся) доставке iPhone-приложения. Мои разделы были разделены по датам следующим образом: вчера, сегодня, завтра, в будущем...

В любом случае, трюк для меня заключался в добавлении категории в NSDate для определения того, в каком разделе принадлежал мой импортированный объект.

У моего управляемого объекта было свойство, называемое dueDate, которое было NSDate. При настройке контроллера получаемых результатов я использовал @"dueDate.relativeDate" как путь к разделу раздела.

В категории -relativeDate было объявлено как возвращающее NSString, а также как свойство readonly (одного из которых может быть достаточно, я не пробовал, не имея обоих, но это не мешает иметь как метод, так и объявление свойств). Затем я просто реализовал метод, при котором он работал красиво.

Ответ 3

Вот куча кода для этого (спасибо jbrennan):

@implementation NSDate (MyExtensions)


// Return today.
+ (NSDate *)today {

    return [NSDate date];
}


// Return yesterday (today minus 24 hours).
+ (NSDate *)yesterday {

    return [NSDate dateWithTimeIntervalSinceNow:-60*60*24];
}


// Return tomorrow (today plus 24 hours).
+ (NSDate *)tomorrow {

    return [NSDate dateWithTimeIntervalSinceNow:60*60*24];
}


// Convert a date comporting a time into a rounded date (just the day, no time).
- (NSDate *)dayDate {

    unsigned unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit |  NSDayCalendarUnit;
    NSDateComponents *comps = [[NSCalendar currentCalendar] components:unitFlags fromDate:self];
    return [[NSCalendar currentCalendar] dateFromComponents:comps]; 
}


// Return a string representing the date relatively (today, tomorrow, yesterday, etc.)
// If no relative sentence is found, return the NSDateFormatterLongStyle formatted date.
- (NSString *)relativeDate {

    if ([self.dayDate isEqualToDate:[[NSDate today] dayDate]]) {

        return NSLocalizedString(@"Today", @"NSDate extensions");
    }
    if ([self.dayDate isEqualToDate:[[NSDate yesterday] dayDate]]) {

        return NSLocalizedString(@"Yesterday", @"NSDate extensions");
    }
    if ([self.dayDate isEqualToDate:[[NSDate tomorrow] dayDate]]) {

        return NSLocalizedString(@"Tomorrow", @"NSDate extensions");
    }

    return [NSDateFormatter localizedStringFromDate:self
                                          dateStyle:NSDateFormatterLongStyle
                                          timeStyle:NSDateFormatterNoStyle];    
}


@end