Подтвердить что ты не робот

Основные данные: извлеченный объект с индексом x имеет имя раздела без порядка "xxxxxx". Объекты должны сортироваться по названию раздела

Я знаю, что я не первый, кто задал этот вопрос, но я действительно в тупике.

В основном у меня есть экран с двумя кнопками. Каждая кнопка загружает данные в таблицу ниже по дате. При первом загрузке первого представления таблицы (по умолчанию выбрана левая кнопка), все отображается нормально. Если я нажму на правую кнопку, и я получу пустой стол, и я получу ошибку

Приобретенный объект с индексом x имеет имя раздела вне порядка "XXXXXX. Объекты должны быть отсортированы по имени раздела.

Возвращаясь к левому экрану таблицы, данные исчезли. Оба табличных поля пусты.

В каждом представлении таблицы есть 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;

}

любая помощь приветствуется!

4b9b3361

Ответ 1

Хорошо, я быстро заглянул.

Вы инициализируете FRC:

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

который сообщает, что ваши заголовки разделов должны быть получены с помощью пути ключа startTime.sessionSection.

Теперь для сортировки разделов будет использоваться первый дескриптор сортировки запроса на выборку, который присваивается FRC. Сначала дескриптор сортировки, который вы предоставляете, - это timeValue, который кажется неправильным.

Ваш первый дескриптор сортировки должен указать сортировку для заголовков разделов. Измените это, и вам может быть хорошо.

ИЗМЕНИТЬ

Спасибо, ребята, за информацию. Я все еще немного потерял. Ты имел ввиду что я должен добавить дескриптор сортировки в startTime.sessionSection раньше присвоив его разделуNameKeyPath? Я пробовал, но все равно не повезло. timeValue и startTime.sessionSection связаны между собой. Может ли это так? - pigeonfactory

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

Самый первый дескриптор сортировки должен удовлетворять данным раздела. Итак, изначально, я бы попытался...

[fetchRequest setSortDescriptors:@[
    [NSSortDescriptor sortDescriptorWithKey:@"startTime.sessionSection"
                                  ascending:NO],
    [NSSortDescriptor sortDescriptorWithKey:@"timeValue"
                                  ascending:YES],
    [NSSortDescriptor sortDescriptorWithKey:@"title"
                                  ascending:YES] ];

Примечание. Если у вас много и много данных, вы можете обнаружить, что ваш секционный механизм замедляется. Если это произойдет, вы можете захотеть добавить данные этого раздела в свою базу данных.

Ответ 2

У меня тоже есть аналогичная проблема, возможно, кто-то найдет ее полезной.

Я взял финансовые транзакции из БД и разделил их на месяц.

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];
...

Что хорошо сработало в производстве, но как только приложение начало рушиться, и после обнаружения корневой проблемы я выяснил, что две транзакции для (например) в июле: июль 2014 года и июль 2015 года. Это была краш-точка как trDate сортированная скважина Июль 2014 г. < Июль 2015 года, но мой метод рассматривал их как один месяц. В качестве имен разделов использовалось не только название месяца, но и год:

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

return [dateFormatter stringFromDate:trDate];
}