开发者

How can I sort my UITableView alphabetically with NSFetchedResultsController?

When the user presses "sort alphabetically", I call the following method for my table:

- (void) sortByName
{
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];

    NSMutableArray *items = [[fetchedResultsController fetchedObjects] mutableCopy];
    [items sortUsingDescriptors:sortDescriptors];

    int newDisplayOrder = 0;

    for (NSManagedObject *managedObject in items)
    {
    开发者_开发知识库    [managedObject setValue:[NSNumber numberWithInt:newDisplayOrder++ ] forKey:@"displayOrder"];
    }

    [sortDescriptor release];
    [sortDescriptors release];

    // Save the context.
    NSError *error = nil;
    if (![self.managedObjectContext save:&error])
    {
       // Need code to handle error properly
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }        
}

But for some reason, instead of sorting alphabetically, it seems to put each item in the order it was created. What am I doing wrong?


Looks good.

Have you set up the fetch results controller to sort according to the displayOrder?

In addition, you should release the items in your code...


It seems you don't refresh the tableview with the sorted array. I use the following method in one of my projects to sort an array of contacts based on status and name:

- (void)refresh {
    if ([NSThread isMainThread]) {
        NSSortDescriptor *descriptorStatus = [[[NSSortDescriptor alloc] initWithKey:@"status" ascending:NO selector:@selector(statusCompare:)] autorelease];
        NSSortDescriptor *descriptorName = [[[NSSortDescriptor alloc] initWithKey:@"displayName" ascending:YES] autorelease]; 
        [contactArray sortUsingDescriptors:[NSArray arrayWithObjects:descriptorStatus, descriptorName, nil]];

        [tableView reloadData];
    } else {
        [self performSelectorOnMainThread:@selector(refresh) withObject:nil waitUntilDone:NO];
    }
}

For your project you probably don't have to check if the refresh is performed on the mainthread, unless the data is retrieved from any thread other then the mainthread.


Try this:

NSMutableArray *items = [NSMutableArray arrayWithArray:fetchedResultsController.fetchedObjects];

or do it in one step (doesn't need to be mutable):

NSArray *items = [fetchedResultsController.fetchedObjects sortedArrayUsingDescriptors:sortDescriptors];

As an aside, this seems like a convoluted way of sorting a table. You are modifying displayIndex in the db to reflect the new sort order. Presumably the NSFetchRequest driving fetchedResultsController is sorting based on displayIndex.

It would be simpler and not require DB changes to simply change the fetchRequest and reconfigure the fetchedResultsController.

From NSFetchedResultsController docs:

Modifying the Fetch Request

You cannot simply change the fetch request to modify the results. If you want to change the fetch request, you must:

If you are using a cache, delete it (using deleteCacheWithName:). Typically you should not use a cache if you are changing the fetch request.

Change the fetch request. Invoke performFetch:.


Why don't you set sort descriptor while fetching the objects.

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜