2014-01-10 3 views
0

У меня есть tableView с расширяемыми/сжимаемыми разделами и заголовками фиксированного раздела, которые я хочу поддерживать. Это код, чтобы сделать это:Основные объекты данных в разных разделах таблицыView

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 
{ 
    return 6; 
} 


+ (NSString*) titleForHeaderForSection:(int) section 
{ 
    switch (section) 
    { 
     case 0 : return @"Overdue"; 
     case 1 : return @"Today"; 
     case 2 : return @"Tomorrow"; 
     case 3 : return @"Upcoming"; 
     case 4 : return @"Someday"; 
     case 5 : return @"Completed"; 
     // default : return [NSString stringWithFormat:@"Section no. %i",section + 1]; 
    } 
} 

На данный момент, я заполнение строки с помощью следующего кода:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{ 
    switch (section) 
    { 
     case 2 : return 1; 
     case 3 : return 30; 
     default : return 8; 
    } 
} 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    static NSString *CellIdentifier = @"Cell"; 

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
    if (cell == nil) 
    { 
     cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease]; 
    } 

    // Configure the cell. 

    switch (indexPath.row) 
    { 
     case 0 : cell.textLabel.text = @"First Cell"; break; 
     case 1 : cell.textLabel.text = @"Second Cell"; break; 
     case 2 : cell.textLabel.text = @"Third Cell"; break; 
     case 3 : cell.textLabel.text = @"Fourth Cell"; break; 
     case 4 : cell.textLabel.text = @"Fifth Cell"; break; 
     case 5 : cell.textLabel.text = @"Sixth Cell"; break; 
     case 6 : cell.textLabel.text = @"Seventh Cell"; break; 
     case 7 : cell.textLabel.text = @"Eighth Cell"; break; 
     default : cell.textLabel.text = [NSString stringWithFormat:@"Cell %i",indexPath.row + 1]; 
    } 

    //cell.detailTextLabel.text = ...; 

    return cell; 
} 

Но я хочу, чтобы заполнить строки из объекта основных данных, это мой NSFetchedResultsController: сущность данных

- (NSFetchedResultsController *)fetchedResultsController { 

    if (_fetchedResultsController != nil) { 
     return _fetchedResultsController; 
    } 

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
    NSEntityDescription *entity = [NSEntityDescription 
            entityForName:@"ToDoItem" inManagedObjectContext:self.managedObjectContext]; 
    [fetchRequest setEntity:entity]; 

    NSSortDescriptor *sort = [[NSSortDescriptor alloc] 
           initWithKey:@"tdText" ascending:NO]; 
    [fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]]; 

    [fetchRequest setFetchBatchSize:20]; 

    NSFetchedResultsController *theFetchedResultsController = 
    [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest 
             managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil 
                cacheName:@"Root"]; 
    self.fetchedResultsController = theFetchedResultsController; 
    _fetchedResultsController.delegate = self; 

    return _fetchedResultsController; 

} 

ядро ​​является «ToDoItem», и то, что я наконец-то хочу, чтобы каждый объект отображается в правой части на Tableview. Мне нужна ваша помощь и совет.


Для того, чтобы мой вопрос немного яснее, я бы создать атрибут tdDate, и этот атрибут должен быть ключом фильтрации, чтобы решить, в соответствии с которым раздел должен быть объект показан. Принимая во внимание, что сегодня в разделе СЕГОДНЯ будет отображаться объект с текущей датой, завтра он должен появиться в разделе OVERDUE ...

ответ

1

Хороший способ добиться того, чтобы добавить новый атрибут в вашем ToDoItem (например state), которые вы можете использовать в качестве sectionNameKeyPath для NSFetchedResultsController.

Постараюсь объяснить на простом примере.

Подумайте об объекте Food, в котором перечислены продукты. У этого лица есть name и category. например

Apple, Fruit 
Banana, Fruit 
Potato, Vegetable 
Salad, Vegetable 

Если вы используете category как sectionNameKeyPath вы найдете две секции. Один будет содержать продукты, принадлежащие к категории Fruit, а другой будет содержать Vegetable.

То же самое относится к использованию свойства state в вашей сущности (для простоты это строка, но вы можете просто использовать числа и использовать карту для сопоставления каждого номера со строковым значением). Я думаю, это правильно, потому что каждый элемент будет иметь состояние завершения. Кроме того, с помощью этого подхода значения, связанные с каждым state, могут динамически меняться. И это должно быть частью модели, а не контроллера. Следовательно, state может принимать одно из следующих значений: @"Overdue", @"Today", @"Tomorrow", @"Upcoming", @"Someday", @"Completed".

В качестве важных нот (см Apple, док)

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

+0

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

+0

@mvasco Что значит? –

+0

Я имею в виду, что разделы должны включать ToDoItems, которые имеют дату (может быть атрибутом, называемым tdDate), этот атрибут можно использовать в качестве фильтра, чтобы сделать распределение по разделам, но затем я должен найти способ обновить ключ в зависимости от текущую дату. – mvasco

1

Я могу представить себе как минимум две разумные стратегии. Один из них - сделать несколько отдельных наборов, по одному для каждой категории. Каждому запросу выборки будет задан предикат, который выбирает те объекты ToDoItem, срок и статус которых соответствуют каждой категории. Например, запрос на выборку для «Сегодня» будет выбирать элементы, в которых дата выполнения - текущая дата, а статус неполный; запрос «Завершено» будет игнорировать дату и выбрать все те элементы, статус которых завершен.

Другая стратегия - получить все предметы сразу и классифицировать их самостоятельно после извлечения. Это может быть концептуально проще, и вы все равно можете использовать NSPredicate для категоризации объектов. Например, вы можете использовать способ NSSet -objectsPassingTest: или метод -filteredArrayUsingPredicate: NSArray.

Проведите некоторое время, прочитав using predicates и fetching objects.

+0

Не могли бы вы дать мне пример того, как заменить текущий cellForRowAtIndexPath, который использует цикл переключения, с результатами запроса на выборку? – mvasco

+0

Скажите, что у вас есть массив, заполненный всеми предметами, которые должны быть представлены завтра. Используйте индекс indexPath.row как индекс в массиве, например: 'ToDoItem * item = tomorrowItems [indexPath.row]; cell.textLabel.text = item.title; 'Вы можете применить ту же стратегию к разделам - возможно, у вас есть массив, в котором каждый элемент массива есть и массив элементов для определенного раздела. Затем вы можете использовать 'indexPath.section', чтобы получить правильный массив, а затем' indexPath.row', чтобы получить элемент из этого массива: 'ToDoItem * item = (allItems [indexPath.section]) [indexPath.row];' – Caleb

+0

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

1

Вы должны быть в состоянии группы извлечённому найденные по переходным свойства (например, itemState), который вычисляет правильную раздела ToDoItem должен появиться в (т.е. 0 = Просро-, 1 = Сегодня, 2 = Завтра).

[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest 
             managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"itemState" 
                cacheName:@"Root"]; 

В управляемом объекте, осуществить itemState вернуть вычисленное состояние элемента:

- (NSString *)itemState { 
    // logic to return @"Overdue", @"Today", etc.. based on whatever logic makes sense in your app 
    // see this on how to implement transient properties http://davemeehan.com/technology/objective-c/core-data-transient-properties-on-nsmanagedobject 

}

Тогда вы можете пойти дальше и использовать ваш FRC реализовать свои методы UITableViewControllerDataSource:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{ 
    return [[[self.fetchedResultsController sections] objectAtIndex:section] numberOfObjects]; 
} 

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 
{ 
    return [self.fetchedResultsController sections].count; 
} 

... и т.д. ...

+0

Я предполагаю, что это не сработает, так как 'itemState' будет найден в объектах, полученных запросом. –

+0

@flexaddicted не уверен, что вы имеете в виду? –

+0

@flexaddicted О, я думаю, я понимаю, что вы имеете в виду. Поскольку он хочет иметь фиксированный набор разделов, это не будет работать так, как есть (например, не может быть просроченных предметов, поэтому просрочка не появится). –

Смежные вопросы