2010-08-04 4 views
2

Я новичок в работе с Core Data и работаю с UITableView. У меня есть панель инструментов с UISegmentedController, и я хочу отфильтровать элементы в UITableView на основе выбранного индекса. Другими словами, предположим, что у меня есть UITableView, который отображает книги (хранимые в Core Data) и UISegmentedController с сегментами для отображения книг на «английском», «испанском» и «французском».Основные данные, UITableView и UISegmentedControl

Каков подход здесь, чтобы все подключилось? Когда один из сегментов нажат, что мне делать в цели UISegmentedControl, чтобы изменить ситуацию?

Извините, если это глупый вопрос!

ответ

6

Я бы использовал отдельныйNSFetchedResultsController для каждого сегмента. Это позволит вам использовать встроенный кеш для каждого сегмента и повысить производительность.

В дополнение к документации Apple (и моей книге) вы также можете прочитать о них из моей статьи Touching The Core в журнале PragPub.

+0

Я не могу не сказать, что, как вы, кто-то, кто так много дает сообществу, я совершенно удивлен тем, что вы нашли время, чтобы ответить на такие вопросы, как моя. Миллион спасибо! –

+0

Маркус, какой был бы самый чистый способ реализовать это? Если бы у вас было три сегмента, для этого потребовалось бы три FRC, и было бы не очень красиво иметь все эти операторы 'switch() case:' в коде таблицы. Возможно, создайте «typedef enum» с метками, соответствующими отдельным сегментам, затем добавьте FRC в NSArray в классе по соответствующим индексам? Тогда все, что вам нужно сделать, это ссылаться на что-то вроде '[self.frcArray objectAtIndex: [segControl selectedSegmentIndex]]', где в противном случае был бы случай 'switch(). Или есть более чистый способ сделать это? –

+1

имеют их как iVars и имеют 'currentFRC' iVar. Когда сегментированный элемент управления задействован, вы переключаете то, что указывает «currentFRC», и сообщают, что tableView перезагружается. Все остальное говорит с 'currentFRC' и имеет проверки в ваших методах делегатов, чтобы они игнорировали любые сообщения, которые не относятся к' currentFRC'. –

0

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

+1

Использование массивов с данными ядра - это больше кода, чем нужно писать. Лучше использовать 'NSFetchedResultsController', для чего он предназначен. –

+0

должным образом отметил: мне особенно нравится, что NSFetchedResultsController использует какое-то кэширование. Большинство моих данных динамичны, поэтому я думаю, что в большинстве случаев NSMutableArrays для большинства вещей – PaulWoodIII

+0

Даже с динамическими данными, Core Data с хранилищем In-Memory плюс 'NSFetchedResultsController' будет меньше кода и лучшей производительности практически в каждой ситуации. Пища для размышлений. –

0

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

+0

Где я могу найти пример кода для этого подхода? –

+0

Читайте: http://developer.apple.com/iphone/library/documentation/CoreData/Reference/NSFetchedResultsController_Class/Reference/Reference.html для создания и использования NSFetchedResultsController. – jamapag

+1

Если вы используете только один, вы теряете преимущество своего кеша. Лучше использовать один для каждого сегмента. –

0

Я реализовал это следующим образом, используя рекомендации Marcus выше (я новичок в этом, поэтому это может быть не лучший подход). У меня есть сегментный контроллер с тремя вариантами «open», «in progress» и «closed».

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

@property (nonatomic, retain) NSFetchedResultsController *fetchedResultsController; 

@property (nonatomic, retain) NSFetchedResultsController *inprogressFetchedResultsController; 
@property (nonatomic, retain) NSFetchedResultsController *openFetchedResultsController; 
@property (nonatomic, retain) NSFetchedResultsController *closedFetchedResultsController; 

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

- (NSFetchedResultsController *)closedFetchedResultsController 
{ 
    if (_closedFetchedResultsController != nil) { 
     return _closedFetchedResultsController; 
    } 

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 

    // Edit the entity name as appropriate. 
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Ticket" inManagedObjectContext:self.managedObjectContext]; 
    [fetchRequest setEntity:entity]; 

    // Set the batch size to a suitable number. 
    [fetchRequest setFetchBatchSize:20]; 

    // Edit the sort key as appropriate. 
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"priority.name" ascending:NO]; 
    NSArray *sortDescriptors = @[sortDescriptor]; 

    [fetchRequest setSortDescriptors:sortDescriptors]; 
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"status = 'Closed'"]; 
    [fetchRequest setPredicate:predicate]; 

    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"priority.name" cacheName:@"ClosedTickets"]; 
    aFetchedResultsController.delegate = self; 

    self.closedFetchedResultsController = aFetchedResultsController; 

    NSError *error = nil; 
    if (![self.closedFetchedResultsController performFetch:&error]) { 
     // Replace this implementation with code to handle the error appropriately. 
     // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. 
     NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
     abort(); 
    } 

    return _closedFetchedResultsController; 
} 

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

- (IBAction)statusChanged:(id)sender { 
    switch (self.segmentControl.selectedSegmentIndex) { 
     case 0: 
      self.fetchedResultsController = self.inprogressFetchedResultsController; 
      break; 
     case 1: 
      self.fetchedResultsController = self.openFetchedResultsController; 
      break; 
     case 2: 
      self.fetchedResultsController = self.closedFetchedResultsController; 
      break; 
     default: 
      break; 

    } 
    [self.tableView reloadData]; 
} 

Всё!

N.B. Я также добавил эту строку к моему методу ViewDidLoad, чтобы он сначала загрузил правильный параметр в fetchedResultsController.

self.fetchedResultsController = self.inprogressFetchedResultsController; 
Смежные вопросы