使用核心数据和排序的iOS索引表视图 - 索引是可以的,但数据不是

时间:2014-09-06 06:05:35

标签: ios objective-c uitableview collation

我需要帮助索引UITableView,将数据划分为字母部分。数据模型来自核心数据图。

我有索引(A-Z),加载好,部分标题正确。问题是数据没有正确排序(即按字母顺序排列)。

模型中有一个实体属性是字母索引。我查看了sqlite文件,没关系。

以下是相关代码。请帮助我理解我遗漏或弄乱的东西:)

- (void)viewDidLoad {
    [super viewDidLoad];

    sectionArray = [[NSArray alloc] init];
    self.collation = [UILocalizedIndexedCollation currentCollation];

    if (languageKey == 0) { 
        sectionArray = [NSArray arrayWithArray:[@"|α,ά|β|γ|δ|ε,έ|ζ|η,ή|θ|ι,ί|κ|λ|μ|ν|Ξ|ο,ό|π|ρ|σ|τ|υ,υ|φ|χ|ψ|ω,ώ|#"
                                                componentsSeparatedByString:@"|"]];

    } else {
        sectionArray = [NSArray arrayWithArray:
                        [@"A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|#"
                         componentsSeparatedByString:@"|"]];
    }

    NSManagedObjectContext *context = [self managedObjectContext];
    NSEntityDescription *entityDescription = [NSEntityDescription
                                              entityForName:@"WordEntity" inManagedObjectContext:context];
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    [request setEntity:entityDescription];
    [request setPredicate:[self predicate]];
    [request setIncludesSubentities:NO];

    filteredWordsArray = [[NSMutableArray alloc] init];
    self.searchResults = [NSMutableArray arrayWithCapacity:[[self.fetchedResultsController fetchedObjects] count]];

    self.searchDisplayController.searchResultsTableView.rowHeight = wordTable.rowHeight;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    if (tableView == self.searchDisplayController.searchResultsTableView)
    {
        return [self.searchResults count];
    }
    else
    {
        return [[[self.fetchedResultsController sections] objectAtIndex:section] numberOfObjects];
    }
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *CellIdentifier = @"WordCell";
    UITableViewCell *cell = (UITableViewCell *)[self.wordTable dequeueReusableCellWithIdentifier:CellIdentifier];

    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
    }

    WordEntity *word = nil;
    if (tableView == self.searchDisplayController.searchResultsTableView) {
        word = [self.searchResults objectAtIndex:indexPath.row];
        count = self.searchResults.count;
        self.numberWordsLabel.text = [NSString stringWithFormat:@"%lu", (unsigned long)count];

    } else {

        word = [self.fetchedResultsController objectAtIndexPath:indexPath];
        self.numberWordsLabel.text = [NSString stringWithFormat:@"%lu", (unsigned long)fullCount];
    }


    if (languageKey == 0) {
        cell.textLabel.text =  word.greekText;
        cell.detailTextLabel.text = word.englishText;
    } else {
        cell.textLabel.text =  word.englishText;
        cell.detailTextLabel.text = word.greekText;
    }

    return cell;
}

/*
 Section-related methods: Retrieve the section titles and section index titles from the collation.
 */


- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    long languageKey = [defaults integerForKey:DEFAULT_KEY_LANGUAGE_NUMBER];
    long count = 0;
    if (languageKey == 0) {
        count = 24;
    } else {
        count = 26;
    }
    return count;
}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    return [sectionArray objectAtIndex:section];
}
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
    return sectionArray;
}
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
    return [collation sectionForSectionIndexTitleAtIndex:index];
}

- (NSFetchedResultsController *)fetchedResultsController {

    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] init];

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    long languageKey = [defaults integerForKey:DEFAULT_KEY_LANGUAGE_NUMBER ];
    if (languageKey == 0) {
        sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"greekKey" ascending:YES selector:@selector(localizedCaseInsensitiveCompare:)];
       // sectionTitleString = @"greekKey";
    } else {
        sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"englishKey" ascending:YES selector:@selector(localizedCaseInsensitiveCompare:)];
       // sectionTitleString = @"englishKey";
    }

    NSArray *sortDescriptors = @[sortDescriptor];
    [fetchRequest setSortDescriptors:sortDescriptors];

      _fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"greekKey" cacheName:nil];
    _fetchedResultsController.delegate = self; 
    return _fetchedResultsController;
}

/*
-(NSArray *)partitionObjects:(NSArray *)array collationStringSelector:(SEL)selector

{
    collation = [UILocalizedIndexedCollation currentCollation];

    NSInteger sectionCount = [[collation sectionTitles] count];   //section count is  from sectionTitles and not sectionIndexTitles
    NSMutableArray *unsortedSections = [NSMutableArray arrayWithCapacity:sectionCount];

    //create an array to hold the data for each section
    for(int i = 0; i < sectionCount; i++)
    {
        [unsortedSections addObject:[NSMutableArray array]];
    }

    //put each object into a section
    for (id object in array)
    {
        NSInteger index = [collation sectionForObject:object collationStringSelector:selector];
        [[unsortedSections objectAtIndex:index] addObject:object];
    }

    sections = [NSMutableArray arrayWithCapacity:sectionCount];

    //sort each section
    for (NSMutableArray *section in unsortedSections)
    {
        [sections addObject:[collation sortedArrayFromArray:section collationStringSelector:selector]];
    }

    return sections;
}
*/

这就是我所看到的:

enter image description here

1 个答案:

答案 0 :(得分:2)

尝试将排序描述符添加到NSFetchRequest ...

NSSortDescriptor *sortDescriptorSecondary = [[NSSortDescriptor alloc]
    initWithKey:@"word" ascending:YES];
[request setSortDescriptors:@[sectionArray, sortDescriptorSecondary]]; 

请注意,在表视图中使用节时,必须始终先按部分排序,然后再按其他条件排序。


<强>更新

更详细一点......

要包含的私人资产:

@property (nonatomic, strong) NSArray *sectionArray;

获取请求包括:

    //  Declare sort descriptors
    NSArray *requestSortDescriptors = nil;
    NSSortDescriptor *sortDescriptorPrimary = nil;
    NSSortDescriptor *sortDescriptorSecondary = nil;

    //  Set sort descriptors...
    //  Primary sort descriptor is your section array - sort by sections first.
    sortDescriptorPrimary = [NSSortDescriptor sortDescriptorWithKey:self.sectionArray ascending:YES];
    //  Secondary sort descriptor is your entity attribute `word` - sort by fetched data second.
    sortDescriptorSecondary = [NSSortDescriptor sortDescriptorWithKey:@"word" ascending:YES];

    //  Set sort descriptor array
    requestSortDescriptors = @[sortDescriptorPrimary, sortDescriptorSecondary];

    //  Apply sort descriptors to fetch request
    [request setSortDescriptors:requestSortDescriptors]; 

希望这有助于,如果您需要进一步解释,请与我联系。


第二次更新

我忽略了如何传播节数据。

就个人而言,对于要在带有节标题的TVC中显示的数据,我为每个实体定义了一个实体属性,我总是为了简单而调用sectionIdentifier

然后作为我保留数据的方法的一部分,我确保&#34;部分&#34;数据已分配给此属性sectionIdentifier(例如,在您的示例中为A,B,C等)。

但是,在您的情况下,对于此特定示例,您已在sectionArray TVC生命周期方法中建立了一个名为viewDidLoad的局部变量。

考虑到您的代码,我建议如下(根据上述内容)......

要包含的私有属性:

@property (nonatomic, strong) NSArray *sectionArray;

同时考虑到您的代码,我建议以下(新)......

更改您的TVC生命周期方法viewDidLoad

- (void)viewDidLoad {
    [super viewDidLoad];

    self.sectionArray = nil;
    self.collation = [UILocalizedIndexedCollation currentCollation];

    if (languageKey == 0) { 
        self.sectionArray = [NSArray arrayWithArray:[@"|α,ά|β|γ|δ|ε,έ|ζ|η,ή|θ|ι,ί|κ|λ|μ|ν|Ξ|ο,ό|π|ρ|σ|τ|υ,υ|φ|χ|ψ|ω,ώ|#" 
                        componentsSeparatedByString:@"|"]];

    } else {
        self.sectionArray = [NSArray arrayWithArray:[@"A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|#"
                        componentsSeparatedByString:@"|"]];
    }

    //  I have commented out code following because I cannot see where you are using it.
    //  Does the compiler not throw up warnings for this fetch request?
    //  
    //  NSManagedObjectContext *context = [self managedObjectContext];
    //  NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"WordEntity" inManagedObjectContext:context];
    //  NSFetchRequest *request = [[NSFetchRequest alloc] init];
    //  [request setEntity:entityDescription];
    //  [request setPredicate:[self predicate]];
    //  [request setIncludesSubentities:NO];

    filteredWordsArray = [[NSMutableArray alloc] init];
    self.searchResults = [NSMutableArray arrayWithCapacity:[[self.fetchedResultsController fetchedObjects] count]];

    self.searchDisplayController.searchResultsTableView.rowHeight = wordTable.rowHeight;
}

同时考虑到您的代码,我建议以下(新)......

更改NSFetchedResultsController getter方法:

- (NSFetchedResultsController *)fetchedResultsController {
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    long languageKey = [defaults integerForKey:DEFAULT_KEY_LANGUAGE_NUMBER ];

    //  Set up fetch request
    NSFetchRequest *fetchRequest = [[NSFetchRequest fetchRequestWithEntityName:@"WordEntity"];
    [fetchRequest setPredicate:[self predicate]];
    [fetchRequest setIncludesSubentities:NO];

    //  Declare sort descriptor variables
    NSArray *requestSortDescriptors = nil;
    NSSortDescriptor *sortDescriptorPrimary = nil;
    NSSortDescriptor *sortDescriptorSecondary = nil;

    //  Set sort descriptors...
    //  Primary sort descriptor is your section array - sort by sections first.
    sortDescriptorPrimary = [NSSortDescriptor sortDescriptorWithKey:self.sectionArray 
                                                          ascending:YES];

    //  Secondary sort descriptor is your entity attribute - sort by fetched data second.
    if (languageKey == 0) {
        sortDescriptorSecondary = [NSSortDescriptor sortDescriptorWithKey:@"greekKey" 
                                                                ascending:YES
                                                                 selector:@selector(localizedCaseInsensitiveCompare:)];     
        // sectionTitleString = @"greekKey";

    } else {
        sortDescriptorSecondary = [NSSortDescriptor sortDescriptorWithKey:@"englishKey" 
                                                                ascending:YES
                                                                 selector:@selector(localizedCaseInsensitiveCompare:)];     
        // sectionTitleString = @"englishKey";

    }

    //  Set sort descriptor array - section first, then table view data
    requestSortDescriptors = @[sortDescriptorPrimary, sortDescriptorSecondary];

    //  Apply sort descriptors to fetch request
    [fetchRequest setSortDescriptors:requestSortDescriptors]; 

    //  Your sectionNameKeyPath in your FRC is self.sectionArray (this may be incorrect - try)
    _fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest 
                                                                    managedObjectContext:self.managedObjectContext 
                                                                      sectionNameKeyPath:self.sectionArray 
                                                                               cacheName:nil];

    _fetchedResultsController.delegate = self; 

    return _fetchedResultsController;
}