Следующие работы отображают список «Pins» на таблице, и я могу с легкостью изменить _category, используя таблицу действий.Применение фильтра к NSFetchedResultsController
Я хочу показывать только результаты, соответствующие данной категории (т. Е. Путешествие), но при этом можно добавлять булавки, которые не имеют одинаковой категории (то есть дома), в managedObjectContext.
Я попытался использовать предикат для фильтрации выбранных данных (путем сопоставления _category со свойством «категория» Pin) безрезультатно - тем более, что я все еще показывал все свои записи независимо от категории но допускаются только добавленные контакты выбранной категории.
Основная часть этого кода относится к шаблону CoreData/TableView, снабженному Xcode.
Любая помощь будет невероятно полезна - это мой первый опыт использования CoreData.
- (void)setFilter {
//load
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
NSString *title = [prefs stringForKey:@"Filter"];
_category = title;
if ([title isEqualToString:@"None"] || title.length < 1) {
title = [NSString stringWithFormat:@"All Pins"];
}else{
title = [NSString stringWithFormat:@"%@ Pins", title];
}
self.navigationItem.title = title;
[self.tableView reloadData];
}
///////////////////////////////////////////////////////////////////////////
//
// Action Sheet
//
///////////////////////////////////////////////////////////////////////////
- (IBAction)showCategorySheet:(id)sender {
UIActionSheet *popupQuery;
popupQuery = [[UIActionSheet alloc] initWithTitle:@"Category" delegate:self cancelButtonTitle:@"All" destructiveButtonTitle:nil
otherButtonTitles:@"Family", @"Friends", @"Home", @"Work", @"Travel", nil];
popupQuery.actionSheetStyle = UIActionSheetStyleDefault;
[popupQuery showInView:self.view];
}
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
NSString *filter;
if (buttonIndex == 0) {
//Family
filter = @"Family";
}else if (buttonIndex == 1) {
//Friends
filter = @"Friends";
}else if (buttonIndex == 2) {
//Home
filter = @"Home";
}else if (buttonIndex == 3) {
//Work
filter = @"Work";
}else if (buttonIndex == 4) {
//Travel
filter = @"Travel";
}else if (buttonIndex == 5) {
//None
filter = @"None";
}
//save
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
[prefs setObject:filter forKey:@"Filter"];
[self setFilter];
}
///////////////////////////////////////////////////////////////////////////
//
// Table
//
///////////////////////////////////////////////////////////////////////////
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 60.0;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [[self.fetchedResultsController sections] count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
id <NSFetchedResultsSectionInfo> sectionInfo = [self.fetchedResultsController sections][section];
return [sectionInfo numberOfObjects];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return YES;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
[context deleteObject:[self.fetchedResultsController objectAtIndexPath:indexPath]];
NSError *error = nil;
if (![context save:&error]) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate.
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
}
}
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
// The table view should not be re-orderable.
return NO;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
NSManagedObject *object = [[self fetchedResultsController] objectAtIndexPath:indexPath];
self.detailViewController.detailItem = object;
}
}
///////////////////////////////////////////////////////////////////////////
//
// Data Handling
//
///////////////////////////////////////////////////////////////////////////
- (NSFetchedResultsController *)fetchedResultsController
{
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// Edit the entity name as appropriate.
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Pin" 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:@"creationDate" ascending:NO];
NSArray *sortDescriptors = @[sortDescriptor];
[fetchRequest setSortDescriptors:sortDescriptors];
// Edit the section name key path and cache name if appropriate.
// nil for section name key path means "no sections".
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:@"Master"];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
NSError *error = nil;
if (![self.fetchedResultsController 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 _fetchedResultsController;
}
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
[self.tableView beginUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type
{
switch(type) {
case NSFetchedResultsChangeInsert:
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath
{
UITableView *tableView = self.tableView;
switch(type) {
case NSFetchedResultsChangeInsert:
[tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:
[self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
break;
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
[self.tableView endUpdates];
}
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
NSManagedObject *object = [self.fetchedResultsController objectAtIndexPath:indexPath];
NSLog(@"object: %@", [object valueForKey:@"category"]);
NSLog(@"filter: %@", _category);
//time
NSDate *now = [object valueForKey:@"creationDate"];
NSString *formattedTime = [NSString stringWithFormat:@"%@", [self formattedDate:now type:@"date"]];
cell.textLabel.text = [[object valueForKey:@"pinName"] description];
cell.detailTextLabel.text = formattedTime;
if ([[object valueForKey:@"pinPictureThumb"] description].length > 0) {
NSData *data = [object valueForKey:@"pinPictureThumb"];
UIImage *img = [[UIImage alloc] initWithData:data];
cell.imageView.image = img;
}else{
cell.imageView.image = nil;
}
}
Вот что я делал раньше. Это позволяет только добавлять в список столбцы указанной категории. Однако, если у меня есть категория, установленная в «Главная», и я добавляю объект с категорией «Работа», объект никогда не добавляется. Кроме того, при смене категорий мне нужен новый список объектов, которые соответствуют новой категории, и этот код по какой-то причине не делает этого. –
Во-первых, я предполагаю, что «pin» настроен как ваш объект, а категория - это атрибут этого объекта. Это верно? Во-вторых, если предикат не изменяется, вам необходимо NSLog для объекта categoryToFind и убедиться, что он устанавливается правильно всякий раз, когда создается объект предиката. – JiuJitsuCoder
Да, «Pin» - это объект с атрибутом «категория». После добавления NSLog для отслеживания категории в предикате, я обнаружил, что он работает только в том случае, если я покину стол и вернусь. Есть ли способ заставить его работать снова, не делая этого? –