Supprimer une ligne d'une tableView a partir d'une autre viewController

Bonjour, 


 


un ViewControllerA qui possède une tableView et un ViewControllerB qui contient le detail de la ligne sélectionné avec un bouton supprimé.


 


Je ne trouve pas comment supprimé la ligne sélectionner sur l'action de ce bouton. 


Je voudrai un peut d'aide !!!! 


 


merci 


Mots clés:

Réponses

  • iLandesiLandes Membre
    juillet 2014 modifié #2

    Salut,


     


    Si tu ne supprime pas ton item depuis le tableView il suffit de mettre à  jour ta dataSource. Dans la plus par des cas supprimer un élément du NSArray qui te sert à  alimenter la tableView. Si tu ne connais pas l'index de l'élément mais que tu connais ton objet (puisque tu l'affiche) il y a dans NSArray la méthode removeObject:(id)anObject  plus simplement si tu connais l'index removeObjectAtIndex:(NSUInteger)index


     


     

    --

    Attention de publier tes post dans le bon forum.

    --

     

    Il est d'usage de se présenter avant d'interroger. Cela permet d'offrir une réponse adaptée : où es tu en stage ? Quel est ton expérience ? Quels études as tu fait ?

     

    En plus c'est plus sympa que de parler à  un avatar vide.

  • AVIS AUX MODO


     


    Ce sujet n'est pas dans la bonne section. Il faudrait le déplacer


  • Désoler je n'arrive pas a trouver la solution j'utilise des donnée en core data dans ma tableView


     


    Dans mon ViewControllerA j'ai un bouton delete qui marche niquel



    // Delete button Aactioonn
    NSIndexPath *cellIndexPath = [self.tableView indexPathForCell:cell];

    [_tableView beginUpdates];
    [self.tableView deleteRowsAtIndexPaths:@[;cellIndexPath] withRowAnimation:UITableViewRowAnimationLeft];

    // 3
    [self.managedObjectContext deleteObject:[self.fetchedScanArray objectAtIndex:cellIndexPath.row]];
    NSError *error;
    if (![self.managedObjectContext save:&error]) {
    NSLog(@Whoops, couldn't save: %@", [error localizedDescription]);
    }
    // 4
    AppDelegate* appDelegate = [UIApplication sharedApplication].delegate;
    self.fetchedScanArray = [appDelegate getAllScan];
    // 5
    [_tableView endUpdates];

    mais pour faire la meme chose dans mon ControllerB ... meme si j'ai très bien compris votre conseille !!!!


  • AliGatorAliGator Membre, Modérateur

    AVIS AUX MODO
     
    Ce sujet n'est pas dans la bonne section. Il faudrait le déplacer

    Merci iLandes! C'est corrigé.

    DarkKnight, tu commences fort, entre tes grossièretés et poster n'importe où... merci de faire attention.
  • DarknightDarknight Membre
    juillet 2014 modifié #6

    désolé !!!!


    J'ai vraiment raté mon entrée !!!  :'(


  • Il faudrait en voir plus sur ton projet pour savoir comment tu gère la source de données.


     


    Qu'est-ce que tu affiches ? Où sont les données de ta datasource ? Dans un NSArray ou ailleurs ?


  • Oui dans l'absolue mes donnée qui sont stocké en Core Data je les stock aussi dans un tableau (NSArray) où ils y a tout mes jeux de résultat du core data. 


     


    Mes data sont une image et des NSString, je pense pouvoir réussir en récupérant l'indexpath de ma cell sélectionné car je pourrai supprimer mon object de mon tableau au bon index.(ou pas)


     


    Mes data sont stocké dans un NSManagedObject subclass



    #import <Foundation/Foundation.h>
    #import <CoreData/CoreData.h>


    @interface ScanDetail : NSManagedObject

    @property (nonatomic, retain) NSString * date;
    @property (nonatomic, retain) NSString * fournisseur;
    @property (nonatomic, retain) NSData * image;
    @property (nonatomic, retain) NSString * mode;
    @property (nonatomic, retain) NSString * titre;
    @property (nonatomic, retain) NSString * ttc;
    @property (nonatomic, retain) NSString * tva;
    @property (nonatomic, retain) NSString * type;
    @property (nonatomic, retain) NSString * autreInfos1;
    @property (nonatomic, retain) NSString * autreInfos2;
    @property (nonatomic, retain) NSString * autreInfos3;
    @property (nonatomic, retain) NSString * autreInfos4;

    @end

    Ceci est la manière dont je stock mes données dans mon Core Data :



    // rajoute une donnée a ma base

    // création et configuration d'une instance de ma classe ScanDetail
    ScanDetail * scan = [NSEntityDescription insertNewObjectForEntityForName:@ScanDetail
    inManagedObjectContext:self.managedObjectContext];
    // la pas besoin de dire quesqu'il ce passe

    scan.titre = self.titre.text;
    scan.type = self.typeDoc.text;
    scan.date = self.dateDoc.text;
    scan.fournisseur = self.fourniDoc.text;
    scan.ttc = self.ttcDoc.text;
    scan.tva = self.tvaDoc.text;
    scan.mode = self.modeDoc.text;
    scan.autreInfos1 = self.autreField.text;
    scan.autreInfos2 = self.autreFIeld2.text;
    scan.autreInfos3 = self.autreField3.text;




    // mon image
    UIImage *image = _imgDoc.image;
    scan.image = UIImageJPEGRepresentation(image, 100);

    // pour recup self.imageView.image = [UIImage imageWithData:scan.image];
    }
    // gestion des erreur de sauvegarde
    NSError *error;
    if (![self.managedObjectContext save:&error]) {
    NSLog(@Whoops, échec de sauvegarde %@", [error localizedDescription]);
    }


    puis je place mes donnée dans mon TableView comme cela 



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

    TableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@prototypCell forIndexPath:indexPath];
    tableView.rowHeight=50;

    ScanDetail *scan = [self.fetchedScanArray objectAtIndex:indexPath.row];

    cell.dateLabel.text = [NSString stringWithFormat:@%@", [miseEnForme stringFromDate:date]];

    [cell.label setText:[NSString stringWithFormat:@%@",scan.type]];
    cell.typeLable.text = [NSString stringWithFormat:@%@",scan.titre];
    cell.dateLabel.font = [cell.textLabel.font fontWithSize:14];
    cell.typeLable.font = [cell.textLabel.font fontWithSize:14];
    cell.label.font = [cell.textLabel.font fontWithSize:14];

    cell.image.image =[UIImage imageWithData:scan.image];
    cell.delegate = self;

    return cell;



    }


    J'espère t'avoir éclairci quelque peu sur mon projet. 


     


    Merci beaucoup pour l'aide apporté et du temps passé sur mon cas merci .


  • J'avoue ne pas maitriser suffisamment coredata. Mais quoi qu'il en soit dans ton viewcontrollerB il faut chercher à  détruire ton objet puis a revenir sur ton viewcontrollerA. Peut être avec un reload data sur la tableview ?


     


    En aucun cas la tableView peut être différente de la source de données. Il faut supprimer les données et la tableview se débrouille

  • AliGatorAliGator Membre, Modérateur
    juillet 2014 modifié #10
    Oui comme dit iLandes, une fois que tu as supprimé ta donnée de CoreData dane le ViewController B, quand tu reviens sur ton ViewController 1 il faut bien mettre à  jour ton dataSource, autrement dit :

    - Refaire un fetch de tes données CoreData dans ton fetchedScanArray histoire d'avoir ton NSArray avec les nouveaux éléments (en particulier ne plus avoir l'élément supprimé)

    - Faire un [tableview reloadData] pour que ta TableView redemande au dataSource à  nouveau le nouveau contenu des cellules


    Ceci dit, cette approche n'est pas la meilleure. En effet, non seulement ta solution nécessite de mettre à  jour à  la fois ton NSArray qui te sert de dataSource + demander à  ta tableView de se reloader, mais en plus il faut que tu penses à  faire ces 2 actions à  chaque fois que tu changes le contenu de ta base CoreData pour ajouter ou supprimer ou modifier un élément.
    Là  dans ton cas où tu as un ViewControllerB qui supprime un élément tu y penses, mais si tu dois y penser partout (peut-être qu'à  faire de coder ton appli il va y avoir plein d'autres endroits où le contenu de ta base est mis à  jour) ça peut vite être lourd.


    Je te conseille plutôt de te pencher du côté de la classe NSFetchedResultsController qui permet de s'abstraire de tout cela. Cette classe est faite pour intégrer facilement des données venant de CoreData dans une UITableView ou UICollectionView :
    • Tu lui fournis une requête CoreData (NSFetchRequest),
    • Tu utilises ensuite les méthodes de NSFetchedResultsController pour demander de récupérer le nombre d'éléments, l'élément à  tel index, etc... (un peu comme tu fais actuellement avec ton NSArray)
    • Et surtout il te prévient (méthode de delegate) quand il y a besoin de mettre à  jour sans que tu n'aies rien à  faire.
    En effet, les gros avantages de NSFetchedResultsController est que :
    • il détecte tout seul quand ton contenu CoreData a changé et t'appelle la méthode de delegate " dans laquelle, typiquement, tu vas appeler [tableView reloadData]. Donc pas besoin de penser à  prévenir ton ViewControllerA quand le ViewControllerB ou un autre a supprimé un objet, le FRC le voit tout seul
    • Il gère un cache interne d'objets ce qui accélère les requêtes et le scrolling
    • Il préfetch les données par blocs de N (je crois que N=100 par défaut, réglé via la propriété "batchSize"), ce qui fait que même si ta requête CoreData retourne 50000 éléments alors que ta tableView ne peut en afficher que 6 à  la fois vu la taille de l'écran, il ne va récupérer que les N premiers, et quand il voit qu'en scrollant tu vas arriver pas loin des derniers qu'il a récupéré, il récupère tout seul les N suivants. Ca évite de récupérer les 50000 éléments pour rien, et donc ça accélère en + la requête même si ta base est conséquente
    Bref, c'est vraiment fait pour et bien pensé, je te conseille vivement d'y passer. Et du coup ça règlera magiquement ton problème de suppression de ligne dans ta TableView du ViewControllerA quand il a été supprimé dans CoreData par le ViewControllerB.
  • ok parfait je regarde cela et je vous tiens au courant merci beaucoup !!!!   o:)


  • Yes i did it 


     


    bon je ne suis pas passer par NSFetchedResultsController car je manque de temps et toutes mes fonction passe par mon fecthArray.


    j'ai donc récupéré l'objectAtIndex de mon tableau que je supprime sur l'action de mon bouton et le tour est joué, par contre je me retrouve avec un tableau où ma ligne contient (null) ( je suis obliger de rafraichir ma tableView pour ne plus avoir la ligne )



    // controllerA

    - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
    {
    if ([[segue identifier] isEqualToString:@updateEdit])
    {
    ScanDetail *scan = [self.fetchedScanArray objectAtIndex:[[self.tableView indexPathForSelectedRow] row]];
    DetailViewController *destViewController = segue.destinationViewController;

    destViewController.devise = scan;
    //rajoute cette ligne pour mon delete
    destViewController.number =scan;
    }
    }



    // controllerB

    - (IBAction)deleteRow:(id)sender
    {
    // 3
    ScanDetail *deleteRow = number;
    [self.managedObjectContext deleteObject:deleteRow];

    NSError *error;
    if (![self.managedObjectContext save:&error]) {
    NSLog(@Whoops, couldn't save: %@", [error localizedDescription]);
    }

    //FirstViewController *FirstViewController1 = [FirstViewController alloc];
    //[self presentViewController:FirstViewController1 animated:YES completion:nil];
    [self dismissViewControllerAnimated:YES completion:nil];

    }

    merci beaucoup de m'avoir mis sur la piste !!!


  • DarknightDarknight Membre
    juillet 2014 modifié #13


    Yes i did it 


     


    bon je ne suis pas passer par NSFetchedResultsController car je manque de temps et toutes mes fonction passe par mon fecthArray.


    j'ai donc récupéré l'objectAtIndex de mon tableau que je supprime sur l'action de mon bouton et le tour est joué, par contre je me retrouve avec un tableau où ma ligne contient (null) ( je suis obliger de rafraichir ma tableView pour ne plus avoir la ligne )



    // controllerA

    - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
    {
    if ([[segue identifier] isEqualToString:@updateEdit])
    {
    ScanDetail *scan = [self.fetchedScanArray objectAtIndex:[[self.tableView indexPathForSelectedRow] row]];
    DetailViewController *destViewController = segue.destinationViewController;

    destViewController.devise = scan;
    //rajoute cette ligne pour mon delete
    destViewController.number =scan;
    }
    }



    // controllerB

    - (IBAction)deleteRow:(id)sender
    {
    // 3
    ScanDetail *deleteRow = number;
    [self.managedObjectContext deleteObject:deleteRow];

    NSError *error;
    if (![self.managedObjectContext save:&error]) {
    NSLog(@Whoops, couldn't save: %@", [error localizedDescription]);
    }

    //FirstViewController *FirstViewController1 = [FirstViewController alloc];
    //[self presentViewController:FirstViewController1 animated:YES completion:nil];
    [self dismissViewControllerAnimated:YES completion:nil];

    }

    merci beaucoup de m'avoir mis sur la piste !!!




    Mais en faites quand on regarde bien number ne sert a rien je peut tout simplement utilisé devise qui sert a upgrde les infos quand motif dans le ControllerB


    du coup :



    // controllerA

    - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
    {
    if ([[segue identifier] isEqualToString:@updateEdit])
    {
    ScanDetail *scan = [self.fetchedScanArray objectAtIndex:[[self.tableView indexPathForSelectedRow] row]];
    DetailViewController *destViewController = segue.destinationViewController;

    destViewController.devise = scan;
    }
    }



    - (IBAction)deleteRow:(id)sender
    {
    // 3
    [self.managedObjectContext deleteObject:devise];

    NSError *error;
    if (![self.managedObjectContext save:&error]) {
    NSLog(@Whoops, couldn't save: %@", [error localizedDescription]);
    }
    [self dismissViewControllerAnimated:YES completion:nil];

    }

    mais toujours ce problème de tableView avec les infos à  (null) alors que j'ai un [tableView reloadData].


     


    merci encore et vive la pomme croqué 


Connectez-vous ou Inscrivez-vous pour répondre.