从NSFetchedResultsController索引结果 [英] Indexing results from an NSFetchedResultsController

查看:120
本文介绍了从NSFetchedResultsController索引结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我从NSFetchedResults控制器中得到了一个混合的,索引的,可搜索的结果集的一些问题。我设置为实体存储索引的A-Z第一个初始值,然后希望它显示数字第一个初始值(即UILocalizedIndexCollat​​ion将做的#)。

I'm having some issues with a mixed, indexed, searchable results set from an NSFetchedResults controller. I have it set up to store an indexed A-Z first initial for an entity, and then want it to display numeric first initials (i.e. # as the UILocalizedIndexCollation would do).

我已经写了一个代码,将Artist对象的firstInitial属性保存为NSString @#,如果全名以一个数字开头,我似乎得到代码一半工作在我的UITableViewController与自定义的排序描述符。问题是,它只有工作,直到我退出/重新启动应用程序。

I have already written the code that saves a "firstInitial" attribute of an Artist object as NSString @"#" if the full name started with a number, and I seem to have gotten the code half working in my UITableViewController with a customised sort descriptor. The problem is that it only works until I quit/relaunch the app.

此时,获取结果的#部分显示在顶部。它将保持在那里,直到我强制数据更改(添加/删除托管对象),然后搜索条目,并清除搜索(使用searchDisplayController)。此时,部分重新排序将进入,#部分将移动到底部...

At this point, the # section from the fetched results appears at the top. It will stay there until I force a data change (add/remove a managed object) and then search for an entry, and clear the search (using a searchDisplayController). At this point the section re-ordering will kick in and the # section will be moved to the bottom...

我显然缺少某些东西/一直盯着相同的代码太长。或者,有一个更简单的方法,我不知道/不能在谷歌找到!

I'm obviously missing something/have been staring at the same code for too long. Alternatively, there's a much easier way of doing it which I'm not aware of/can't find on Google!

任何帮助将不胜感激!

感谢

Sean

我的UITableViewController的相关代码

The relevant code from my UITableViewController is below.

- (void)viewDidLoad
{
    // ----------------------------------
    // Various other view set up things in here....
    // ...
    // ...
    // ----------------------------------

    NSError *error;
    if (![[self artistResultsController] performFetch:&error]) {
        // Update to handle the error appropriately.
        NSLog(@"Failed to fetch artists: %@, %@", error, [error userInfo]);
        exit(-1);  // Fail
    }

}
- (NSFetchedResultsController *)artistResultsController {

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

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription 
                               entityForName:@"Artist" inManagedObjectContext:_context];
[fetchRequest setEntity:entity];

NSSortDescriptor *initialSort = [[NSSortDescriptor alloc] 
                          initWithKey:@"firstInitial" 
                          ascending:YES 
                          comparator:^(id obj1, id obj2) {
                              // Various number conditions for comparison - if it's a # initial, then it's a number
                              if (![obj1 isEqualToString:@"#"] && [obj2 isEqualToString:@"#"]) return NSOrderedAscending;
                              else if ([obj1 isEqualToString:@"#"] && ![obj2 isEqualToString:@"#"]) return NSOrderedDescending;
                              if ([obj1 isEqualToString:@"#"] && [obj2 isEqualToString:@"#"]) return NSOrderedSame;
                              // Else it's a string - compare it by localized region
                              return [obj1 localizedCaseInsensitiveCompare:obj2];
                          }];

NSSortDescriptor *nameSort = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];

[fetchRequest setSortDescriptors:[NSArray arrayWithObjects:initialSort, nameSort, nil]];

[fetchRequest setFetchBatchSize:20];

NSFetchedResultsController *theFetchedResultsController = 
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest 
                                    managedObjectContext:_context 
                                      sectionNameKeyPath:@"firstInitial" 
                                               cacheName:nil];
self.artistResultsController = theFetchedResultsController;
_artistResultsController.delegate = self;

[nameSort release];
[initialSort release];
[fetchRequest release];
[_artistResultsController release];

return _artistResultsController;}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
    if (tableView == self.searchDisplayController.searchResultsTableView) {
        return nil;
    } else {
        return [[[_artistResultsController sections] objectAtIndex:section] name];
    }
}

- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
{
    if (tableView == self.searchDisplayController.searchResultsTableView) {
        return nil;
    } else {
        return [[NSArray arrayWithObject:UITableViewIndexSearch] arrayByAddingObjectsFromArray:
                [[UILocalizedIndexedCollation currentCollation] sectionIndexTitles]];

    }
}

- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index
{
    if (tableView == self.searchDisplayController.searchResultsTableView) {
        return 0;
    } else {
        if (title == UITableViewIndexSearch) {
            [tableView scrollRectToVisible:self.searchDisplayController.searchBar.frame animated:NO];
            return -1;
        } 
        else {
            for (int i = [[_artistResultsController sections] count] -1; i >=0; i--) {
                NSComparisonResult cr = 
                [title localizedCaseInsensitiveCompare:
                 [[[_artistResultsController sections] objectAtIndex:i] indexTitle]];
                if (cr == NSOrderedSame || cr == NSOrderedDescending) {
                    return i;
                }
            }
            return 0;
        }
    }
}

编辑:我的搜索过滤器在fetchedResults控制器上使用一个谓词,所以这会导致一个新的获取请求,像这样

Forgot to mention - my search filter is using a predicate on the fetchedResults controller, so this causes a new fetch request, like so

- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope {
    NSFetchRequest *aRequest = [_artistResultsController fetchRequest];

    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name BEGINSWITH[cd] %@", searchText];
    // set predicate to the request 
    [aRequest setPredicate:predicate];
    // save changes
    NSError *error = nil;
    if (![_artistResultsController performFetch:&error]) {
        NSLog(@"Failed to filter artists: %@, %@", error, [error userInfo]);
        abort();
    }  
} 


推荐答案

I

SortDescriptors似乎在运行自定义排序时遇到问题,当您同时使用CoreData和SQLite作为后端存储时。我试了几件事情; NSString类别与新的比较方法,比较块如上所列,并刷新表多次尝试和强制更新与排序标准。

SortDescriptors seem to have issues with running a custom sort when you are also using CoreData with SQLite for your backend storage. I tried a few things; NSString categories with a new comparison method, the compare block as listed above, and refreshing the table multiple times to try and force an update with the sort criterion.

最后,我不能强迫排序描述符做一个初始排序,所以我改变了实现。我将名称以numerics开头的艺术家的firstInitial属性设置为zzzz。这意味着CoreData将正确地排序(数字最后)从棒。

In the end, I couldn't force the sort descriptor to do an initial sort, so I changed the implementation. I set the firstInitial attribute for artists whose names began with numerics to 'zzzz'. This means that CoreData will sort this correctly (numerics last) off the bat.

这样做后,我然后硬编码我的titleForHeaderInSection方法返回#的标题,如果适当,如下:

After doing this, I then hardcoded my titleForHeaderInSection method to return # for the title if appropriate, as below:

if ([[[[_artistResultsController sections] objectAtIndex:section] indexTitle] isEqualToString:@"zzzz"]) return [NSString stringWithString:@"#"];
return [[[_artistResultsController sections] objectAtIndex:section] indexTitle];

本质上,这意味着它将数字排序为zzzz

Essentially this means it's sorting numbers into a 'zzzz' grouping, which should be last, and I'm just ignoring that title and saying the title is # instead.

不知道是否有更好的方法来做到这一点,但它保留CoreData中的所有排序从长远来看可能更有效/可扩展。

Not sure if there's a better way to do this, but it keeps all of the sorting inside CoreData, which is probably more efficient/scalable in the long run.

这篇关于从NSFetchedResultsController索引结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆