Pergunta

O que eu quero fazer é bem simples. No meu uitableViewController, quero carregar dados de vários nsfetchedResultControllers (tenho várias entidades no meu modelo de dados) e colocar dados de cada um em uma seção diferente na visualização da tabela. Por exemplo, todos os itens buscados do primeiro NSFetchedResultController entrariam na seção 0 no UitableView, os itens buscados do outro entram na Seção 1, etc.

O projeto principal do modelo de dados não demonstra como fazer isso. Tudo (principalmente os caminhos do índice) é codificado sem levar em consideração as seções (não há seções no modelo padrão) e tudo é retirado de um único nsfetchedResultController. Existem algum exemplo de projetos ou documentação que demonstra fazer isso?

Obrigado

Foi útil?

Solução

Suponha por um momento o seguinte no seu cabeçalho (o código abaixo será um pouco desleixado, minhas desculpas):

NSFetchedResultsController *fetchedResultsController1; // first section data
NSFetchedResultsController *fetchedResultsController2; // second section data

Informe a tabela que deseja ter 2 seções:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 2; // you wanted 2 sections
}

Dê os títulos da seção:

- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
    return [NSArray arrayWithObjects:@"First section title", @"Second section title", nil];
}

Informe a tabela quantas linhas existem por seções:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    if (section == 0) {
        return [[fetchedResultsController1 fetchedObjects] count];
    } else if (section == 1) {
        return [[fetchedResultsController2 fetchedObjects] count];
    }

    return 0;
}

Construa a célula:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    ... // table cell dequeue or creation, boilerplate stuff

    // customize the cell
    if (indexPath.section == 0) {
        // get the managed object from fetchedResultsController1
        // customize the cell based on the data
    } else if (indexPath.section == 1) {
        // get the managed object from fetchedResultsController2
        // customize the cell based on the data
    }

    return cell;
}

Outras dicas

Estendendo a solução da Giao com dois nsfetchedResultScontrollers - precisamos lembrar que o nosso NSFetchedResultScontroller não conhece nossas duas seções e os NSindexpathes retornados serão sempre para a primeira seção.

Então, quando estamos obtendo um objeto na configuração de células:

- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
    if (!cell) {
        [tableView registerNib:[UINib nibWithNibName:@"cell" bundle:nil] forCellReuseIdentifier:@"cell"];
        cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
    }
    [self configureCell:cell atIndexPath:indexPath];
    return cell;
}

-(void)configureCell:(UITableViewCell*)cell atIndexPath:(NSIndexPath *)indexPath {
    if (indexPath.section == 0) {
        NSManagedObject *object = [self.fetchedResults1 objectAtIndexPath:[NSIndexPath indexPathForRow:indexPath.row inSection:0]];
        //use object to configure cell
    } else {
        NSManagedObject *object = [self.fetchedResults2 objectAtIndexPath:[NSIndexPath indexPathForRow:indexPath.row inSection:0]];
        //use object to configure cell
    }
}

Atualizando células enquanto o NSFetchedResultScontroller notou algumas alterações:

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
    NSIndexPath *customIndexPath = [NSIndexPath indexPathForRow:indexPath.row inSection:(controller == self.fetchedResultsController1)?0:1];
    NSIndexPath *customNewIndexPath = [NSIndexPath indexPathForRow:newIndexPath.row inSection:(controller == self.fetchedResultsController2)?0:1];
    switch(type) {
        case NSFetchedResultsChangeInsert:
            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:customNewIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;
        case NSFetchedResultsChangeDelete:
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:customIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;
        case NSFetchedResultsChangeUpdate:
            [self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
            break;
        case NSFetchedResultsChangeMove:
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:customIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:customNewIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;
    }
}

Vários controladores de busca (e possivelmente várias entidades) são a abordagem errada. A solução correta é usar o sectionNameKeyPath param para o NSFetchedResultController Para agrupar os resultados em várias seções. Se você pensar em suas entidades de maneira diferente, talvez elas sejam realmente a mesma entidade e, em vez disso, você pode usar um imóvel ItemType no qual você pode seções (e também deve classificá -la também). Por exemplo, diga que eu tinha lúpulos e grãos de entidades, então eu poderia alterá -los para ingredientes e ter um ingrediente da propriedade INT_16 que eu tenho uma enumeração no código para armazenar os valores hopType = 0, grainType = 1. Afinal, todo o ingrediente é apenas um nome e um peso, que ambos compartilham.

Se, no entanto, suas entidades realmente tiverem um conjunto distinto de propriedades, a solução correta é criar uma entidade abstrata pai que possua uma propriedade que você pode usar na seção, por exemplo, Sortorder, Seção ou tipo. Quando você cria um controlador de busca e busca a entidade pai abstrata, na verdade você obtém resultados contendo todas as sub-entidades. Por exemplo, no aplicativo Notes, eles têm uma entidade abstrata noteContainer que possui uma conta e pasta de sub-entrada. Dessa forma, eles podem usar um único controlador de busca para exibir a conta na primeira célula da seção e depois ter todas as pastas nas células a seguir. Por exemplo, todas as notas do iCloud (na verdade é a conta), depois as notas (é a pasta padrão), seguida por todas as pastas personalizadas e depois a pasta de lixo. Eles usam uma propriedade Sortorder e a pasta padrão é 1, as pastas personalizadas são todas 2 e o lixo é 3. Ao adicionar isso como um descritor de classificação que eles podem exibir as células na ordem que desejam. É um pouco diferente do seu requisito, porque eles têm as duas entidades misturadas em seções diferentes, mas você ainda pode usá -lo apenas com diferentes propriedades de classificação.

A moral da história é não lutar contra a estrutura, abraçá-la :-)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top