8
votes

Multiple NsfetchedResultController sur un UitaireVoir

J'ai des difficultés à mettre en œuvre 2 NsfetchedResultSluTroller code> dans un TableView code>. Je voulais un fetchedResultSlugroller dans chaque section de la table (2 sections), quelque chose comme ceci:

Liste de souhaits strong> P>

  • Produit Li>
  • Produit2 LI> ul>

    acheté strong> p>

    • Produit3 Li> ul>

      Je sais que pour cet exemple, je n'aurais pas besoin de 2 nsfetchedresultSlugroller, mais j'aurai besoin de cela plus tard. P>

      Lorsque je retire un produit d'un NsfetchedResultSluTroller, il passe à l'autre et je Obtenez cette erreur: p>

      mise à jour non valide: Nombre non valide de lignes à la section 0. Le nombre de rangées contenues dans une section existante après la mise à jour (0) doit être égal au nombre de lignes contenues dans cette section avant la mise à jour (0), plus ou moins le nombre de lignes insérées ou supprimées de cette section (1 insérée, 0 supprimée). avec userinfo (null) " p> blockQuote>

      Je pense que cela se produit parce que lorsque le premier fetchedRController détecte un changement, il met à jour la tableView avant que le second soit appelé, c'est ce droit? Dois-je utiliser Nsmutablarrays et mettre à jour la tableView manuellement?
      P>

      Le code: p>

      - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
      {
      NSInteger numberOfRows = 0;
      
      switch (section)
      {
          case WISHLIST_SECTION:
      
          {
              numberOfRows =[[fetchedResultsControllerwish fetchedObjects]count];
      
      
          };
               break;
      
          case PURCHASED_SECTION:
          {   
              numberOfRows =[[fetchedResultsControllerPurchased fetchedObjects]count];
      
          };
              break;
      
      
          default:
              break;
      }
      return numberOfRows;
      }
      
      - (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
      // The fetch controller is about to start sending change notifications, so prepare the table view for updates.
      [self.tableView beginUpdates];
      }
      
      
      - (void)controllerDidChangeContent:(NSFetchedResultsController *)controller 
      {
      
      // The fetch controller has sent all current change notifications, so tell the table view to process all updates.
      [self.tableView endUpdates];
      }
      
      - (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
         atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
        newIndexPath:(NSIndexPath *)newIndexPath {
      
      UITableView *tableViewT = self.tableView;
      
      switch(type) {
      
          case NSFetchedResultsChangeInsert:
              [tableViewT insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
                               withRowAnimation:UITableViewRowAnimationFade];
              break;
      
          case NSFetchedResultsChangeDelete:
              [tableViewT deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
                               withRowAnimation:UITableViewRowAnimationFade];
              break;
      
          case NSFetchedResultsChangeUpdate:
              [self configureCell:(GiftEventTableViewCell *)[tableViewT cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
              break;
      
          case NSFetchedResultsChangeMove:
              [tableViewT deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
                               withRowAnimation:UITableViewRowAnimationFade];
              [tableViewT insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
                               withRowAnimation:UITableViewRowAnimationFade];
              break;
      }
      }
      
      -(void)configureCell:(GiftEventTableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
      {
      switch (indexPath.section) {
          case WISHLIST_SECTION:
          {
              GiftEvent *giftEv=(GiftEvent *)[fetchedResultsControllerwish objectAtIndexPath:indexPath];
              cell.gift=giftEv;
      
          };
              break;
          case PURCHASED_SECTION:
          {
              GiftEvent *giftEv=(GiftEvent *)[fetchedResultsControllerPurchased objectAtIndexPath:indexPath];
      
              //if i don't use indexpath.row in the second section i get an out of bounds error
              //GiftEvent *giftEv=(GiftEvent *)[[fetchedResultsControllerPurchased fetchedObjects]objectAtIndex: indexPath.row];
              cell.gift=giftEv;
      
          };
              break;
      
      
      
      
          default:
              break;
      }
      
      }
      
      // Override to support editing the table view.
      - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
      if (editingStyle == UITableViewCellEditingStyleDelete) 
      {
          switch (indexPath.section) {
              case WISHLIST_SECTION:
              {
                  // Delete the managed object for the given index path
      
                  [self.managedObjectContext deleteObject:[fetchedResultsControllerwish objectAtIndexPath:indexPath]];
      
                  // Save the context.
                  NSError *error;
                  if (![self.managedObjectContext save:&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. If it is not possible to recover from the error, display an alert panel that instructs the user to quit the application by pressing the Home button.
                       */
                      NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
                      abort();
                  }
                  [self.tableView reloadData];
      
                   };
                  break;
              case PURCHASED_SECTION:
              {
                  // Delete the managed object for the given index path
      
                  [self.managedObjectContext deleteObject:[fetchedResultsControllerPurchased objectAtIndexPath:indexPath]];
      
                  // Save the context.
                  NSError *error;
                  if (![self.managedObjectContext save:&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. If it is not possible to recover from the error, display an alert panel that instructs the user to quit the application by pressing the Home button.
                       */
                      NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
                      abort();
                  }
      
              };
                  break;
      
              default:
                  break;
          }
      }   
      }
      


0 commentaires

4 Réponses :


4
votes

Consultez cette autre question sur le débordement de la pile:


Données de base: Uitailview avec plusieurs NsfetchedResultContrôleurs

Données de base: UitailView avec plusieurs NsfetchedResultControls


0 commentaires

1
votes

Désolé gars, c'était une erreur noob. L'erreur se produisait car l'indexPath.section a renvoyé la section dans la tableView mais je n'avais aucune section dans la FetchedResultSlontroller (toujours index 0).

Edit: En réalité, il y en a une .. p>

NSIndexPath *indexPathTemp = [NSIndexPath indexPathForRow:indexPath.row inSection:0];


0 commentaires

1
votes

Je viens de créer une pod pour résoudre ce problème. https://github.com/imton/gmcoredataMultiPleectionStableVC

Vous pouvez le vérifier et dites-moi ce que vous pensez, rétrodive accueil!

g


0 commentaires

4
votes

Utiliser plusieurs est la mauvaise approche. La solution correcte consiste à utiliser la section SectionNameKeyPath param sur le nsfetchedresulttroller pour regrouper les résultats en plusieurs sections, dans votre cas, ce serait une propriété booléenne achetée sur le produit. Et vous devriez également faire de cela le premier descripteur de tri en ordre croissant depuis que vous souhaitez que l'ONU achète ci-dessus acheté. Utilisez la méthode de déléguée de la table de titres en-tête pour renvoyer la chaîne "wishlist" et "acheté" pour chaque indice de section.

Si vous pensez avoir une troisième liste à l'avenir, vous feriez mieux d'utiliser une propriété de statut numérique et dans le code une ENUM pour chacun des états (ou des listes), le produit peut être dans. C'est généralement comment cela est fait plutôt que de trier sur un bool.


0 commentaires