开发者

Core Data, UITableView, and UISegmentedControl

开发者 https://www.devze.com 2023-01-09 22:48 出处:网络
I am new to working with Core Data, and am working with a UITableView.I have a toolbar with a UISegmentedController, and I want to filter the items in the UITableView based on the selected index.In ot

I am new to working with Core Data, and am working with a UITableView. I have a toolbar with a UISegmentedController, and I want to filter the items in the UITableView based on the selected index. In other words, suppose I have a UITableView that displays Books (stored in Core Data) and a UISegmentedController with segments to display books in "English", "Spanish", and "French".

What is the approach here to get everything hooked up? When one of the segments is clicked, what do I do in t开发者_StackOverflow中文版he UISegmentedControl's target to change things around?

Sorry if it's a stupid question!


I would use a separate NSFetchedResultsController for each segment. This will allow you to take advantage of the built in cache for each segment and improve performance.

In addition to Apple's documentation (and my book), you can also read up on them from my article Touching The Core in the PragPub magazine.


Its a good idea to use three different Arrays for each of your filters. Cache them somewhere so their is no delay when the user selects a filter. To find the information you are looking for from your CoreData store use NSPredicate.


You can use NSFetchedResultsController, when you clicked on segment just set the different perdicate and perform fetch again.


I have implemented this as follows using the guidelines from Marcus above(I'm new to this so it may not be the best approach). I have a segment controller with three options for 'open', 'in progress' and 'closed'.

In the ViewController.h, create an iVar for each one of your segment options, and one iVar for the main controller that will store the current controller.

@property (nonatomic, retain) NSFetchedResultsController *fetchedResultsController;

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

In the ViewController.m you need to create methods for lazy loading of these controllers, so I have three in total. They are basically the same except for the predicate and the cacheName, I have only shown one below.

- (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;
}

Create an IBAction for your segment so that when it is changed it changes the fetched results controller and reloads the table.

- (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];
}

That's it!

N.B. I also added this line to my ViewDidLoad method so that it would load the correct option into the fetchedResultsController initially.

self.fetchedResultsController = self.inprogressFetchedResultsController;
0

精彩评论

暂无评论...
验证码 换一张
取 消