CoreData Inhalt in UITableView wird nach dem ändern falsch angezeigt aber richtig abgespeichert!?

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • CoreData Inhalt in UITableView wird nach dem ändern falsch angezeigt aber richtig abgespeichert!?

    Hallo liebe Entwicklergemeinde,
    nachdem ich sehr gute Erfahrungen in diesem Forum sammeln konnte, wende ich mich erneut verzweifelt an euch und bitte euch um Hilfe....

    Ich versuche aktuell eine Art AutoComplete Funktion für meine App zu erstellen. Diese greift auf eine CoreData Datenbank zu um die Daten mit dem Key "flag" auszulesen und zu vergleichen. Dies klappt auch soweit ganz gut...
    Leider wird mir aber bei der Änderung der Wert in meinem CoreData Model ordentlich gespeichert, aber in der AutoCompleteTabelle werden noch die alten Daten angezeigt!? Beende ich die App oder gehe nur kurz aus ihr aus, werden die Daten wieder richtig angezeigt!?

    Hier die Action für das Textfeld in dem ich die Daten aus Core Data abrufe und vergleiche:

    Quellcode

    1. - (IBAction)autoComplete:(id)sender {
    2. if (editingFlag) {
    3. //autocompleteTableView.hidden = YES;
    4. [self.view addSubview:autocompleteTableView];
    5. NSLog(@"editingFlag gesetzt, --> autoComplete Action");
    6. AppDelegate *del = [[UIApplication sharedApplication] delegate];
    7. NSManagedObjectContext *moc = [del managedObjectContext];
    8. NSEntityDescription *entity = [NSEntityDescription entityForName:@"LearningObjects" inManagedObjectContext:moc];
    9. NSFetchRequest *fr = [[NSFetchRequest alloc] init];
    10. [fr setEntity:entity];
    11. NSPredicate *predicate = [NSPredicate predicateWithFormat:@"flag beginswith[code=c] %@",textField.text];
    12. [fr setPredicate:predicate];
    13. NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"flag" ascending:YES];
    14. NSMutableArray *sortDescriptors = [[NSMutableArray alloc] initWithObjects:sortDescriptor, nil];
    15. [fr setSortDescriptors:sortDescriptors];
    16. [fr setResultType:NSDictionaryResultType];
    17. [fr setPropertiesToFetch:[NSArray arrayWithObject:@"flag"]];
    18. fr.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"flag" ascending:YES]];
    19. [fr setReturnsDistinctResults:YES];
    20. NSLog(@"Objekte im fetch request: %@", fr);
    21. NSError *error = nil;
    22. globalesArray = [[moc executeFetchRequest:fr error:&error] mutableCopy];
    23. NSLog(@"Objekte im Array - autoComplete Action: %@",globalesArray);
    24. [autocompleteTableView reloadData];
    25. [sortDescriptor release];
    26. [sortDescriptors release];
    27. [fr release];
    28. }
    29. else {
    30. NSLog(@"editingFlag nicht gesetzt, --> autoComplete Action");
    31. }
    32. }
    Alles anzeigen



    Hier der Code für die Anzeige in der Tabelle:

    Quellcode

    1. #pragma mark UITableViewDataSource methods
    2. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger) section {
    3. if (globalesArray.count == 0) {
    4. if (self.autocompleteTableView.alpha != 0.0) {
    5. NSLog(@"TableView FadeOut in tableView numberOfRowsInSection:");
    6. [UIView beginAnimations:@"FadeOut" context:nil];
    7. [UIView setAnimationDuration:0.0];
    8. //self.autocompleteTableView.transform = CGAffineTransformMakeTranslation(0, 500);
    9. self.autocompleteTableView.alpha = 1.0;
    10. [UIView setAnimationDuration:1.0];
    11. self.autocompleteTableView.alpha = 0.0;
    12. //self.autocompleteTableView.transform = CGAffineTransformMakeTranslation(0, 0);
    13. [UIView commitAnimations];
    14. autocompleteTableView.hidden = NO;
    15. }
    16. }
    17. else {
    18. if (self.autocompleteTableView.alpha != 1.0) {
    19. NSLog(@"TableView FadeIn in tableView numberOfRowsInSection:");
    20. [UIView beginAnimations:@"FadeIn" context:nil];
    21. [UIView setAnimationDuration:0.0];
    22. //self.autocompleteTableView.transform = CGAffineTransformMakeTranslation(0, 500);
    23. self.autocompleteTableView.alpha = 0.0;
    24. [UIView setAnimationDuration:1.0];
    25. self.autocompleteTableView.alpha = 1.0;
    26. //self.autocompleteTableView.transform = CGAffineTransformMakeTranslation(0, 0);
    27. [UIView commitAnimations];
    28. autocompleteTableView.hidden = NO;
    29. }
    30. }
    31. NSLog(@"Was steht in tableView - numberOfRowsInSection drin: %i",globalesArray.count);
    32. return globalesArray.count;
    33. }
    34. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    35. static NSString *CellIdentifier = @"Cell";
    36. UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    37. if (cell == nil) {
    38. cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    39. }
    40. // Configure the cell.
    41. [self configureCell:cell atIndexPath:indexPath];
    42. if (cell.textLabel.text == textField.text) {
    43. NSLog(@"TableView FadeOut in configureCell");
    44. [UIView beginAnimations:@"FadeOut" context:nil];
    45. [UIView setAnimationDuration:0.0];
    46. //self.autocompleteTableView.transform = CGAffineTransformMakeTranslation(0, 500);
    47. self.autocompleteTableView.alpha = 1.0;
    48. [UIView setAnimationDuration:1.0];
    49. self.autocompleteTableView.alpha = 0.0;
    50. //self.autocompleteTableView.transform = CGAffineTransformMakeTranslation(0, 0);
    51. [UIView commitAnimations];
    52. autocompleteTableView.hidden = NO;
    53. }
    54. return cell;
    55. }
    56. - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    57. return @"Bisher verwendete Markierungen:";
    58. }
    59. #pragma mark UITableViewDelegate methods
    60. - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    61. NSDictionary *item = [globalesArray objectAtIndex:indexPath.row];
    62. NSLog(@"item itemtext = %@", [item objectForKey:@"flag"]);
    63. textField.text = [item objectForKey:@"flag"];
    64. NSLog(@"TableView FadeOut in tableView numberOfRowsInSection:");
    65. [UIView beginAnimations:@"FadeOut" context:nil];
    66. [UIView setAnimationDuration:0.0];
    67. //self.autocompleteTableView.transform = CGAffineTransformMakeTranslation(0, 500);
    68. self.autocompleteTableView.alpha = 1.0;
    69. [UIView setAnimationDuration:1.0];
    70. self.autocompleteTableView.alpha = 0.0;
    71. //self.autocompleteTableView.transform = CGAffineTransformMakeTranslation(0, 0);
    72. [UIView commitAnimations];
    73. autocompleteTableView.hidden = NO;
    74. }
    75. - (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
    76. NSLog(@"Was steht in configureCell im globalesArray: %@", globalesArray);
    77. NSDictionary *item = [globalesArray objectAtIndex:indexPath.row];
    78. NSLog(@"item itemtext = %@", [item objectForKey:@"flag"]);
    79. cell.textLabel.text = [item objectForKey:@"flag"];
    80. }
    Alles anzeigen



    In der Funktion viewDidLoad wird die Tabelle wie folgt erzeugt:

    Quellcode

    1. autocompleteTableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 120, 320, 145) style:UITableViewStylePlain];
    2. autocompleteTableView.delegate = self;
    3. autocompleteTableView.dataSource = self;
    4. autocompleteTableView.scrollEnabled = YES;
    5. autocompleteTableView.alpha = 1.0;



    Da ich selber kein prof. Entwickler bin, das ganze mir selber als Hobby beigebracht habe, bitte ich ggf. falsche Formulierungen zu entschuldigen. Ich vermute das mein Problem daran liegt, wie ich die Daten in der Action aus CoreData abfrage! Allerdings finde ich keinen Fehler, was ja nicht heißt das dieser nicht doch vorhanden ist ;)
    Für einen Denkanstoß oder eine Hilfe wäre ich sehr dankbar. Ich konnte von euch schon viel lernen, vielleicht ja auch diesesmal wieder ...!?

    Danke im vorraus...
    Dirk
  • Hey ...

    liegt etwas daran, wie Du CoreData eingebunden hast.
    Sofern Du es quasi selbst programmiert hast oder ältere Apple-Vorlagen oder Tutorial-Vorlagen verwendet hast, fehlt Dir wahrscheinlich ein reloadData

    Quellcode

    1. - (void)viewWillAppear:(BOOL)animated {
    2. [self.tableView reloadData];
    3. }


    Mir ist nicht ganz klar, warum Du die Action "autoComplete" benötigst. Eigentlich werden beim Aufruf der TableView die Daten aktiv aus dem Speicher gezogen. Kann man sehr schön in den neuen Vorlagen-Beispieln von Apple sehen (leg einfach mal ein neues Projekt an). Ansonsten müsste Dir eigentlich der viewWillAppear-Code schon reichen.

    Gruß
    iet
    ----
    Macht's gut und danke für den Fisch
  • Hallo iet und danke für deine schnelle Antwort.

    Leider habe ich den reloadData in viewWillAppear drinnen stehen. Bringt auch keinen Erfolg.
    Ich habe die Befürchtung das er mir die Daten nur einmal aktuell zieht und danch die Veränderung zwar speichert, aber der managedContext nicht aktuallisiert.
    Ich brauche die AutoComplete Action, um eine Abfrage aus einen TextFeld mit meinem CoreData Modell abzugleichen.

    Beispiel:
    Der Anwender hat z.b. als flag "englisch / deutsch" gepeichert, ebenso in einem anderen gespeicherten Objekt "englisch / französisch". Nun will er bei einem neuen Objekt einen flag setzten der z.B. "englisch / portugiesisch" lautet.
    Jetzt greift meine AutoCompleteAction.... Tippt er ins TextFeld ein "e" ein, sollen in der Tablle alle Werte des Attributes "flag" beginnend mit "e" angezeigt werden.
    Dies funktioniert auch soweit. Nur ändert der User ein flag, oder erstellt ein neues, wird dieses erst nach beendigung und erneuten aufrufen (z.B. drücken des HomeButtons) der App angezeigt!?

    Ich hoffe es ist verständlich....!?
  • So ... nun anbei der Code.

    In der viewDidLoad wird nur der Button erstellt. Kannst Du natürlich wahlweise auch über Storyboard einbinden und dann als Action-Outlet verwenden.
    Ich habe es hier direkt im Code gelöst. Hat den Vorteil, dass ich "schneller" ein entsprechendes Bild verwenden kann und das auch noch verstehe. Sonst nix wichtiges in der Methode. Nur der @selector-Aufruf "dueFilter".

    Quellcode

    1. - (void)viewDidLoad {
    2. [super viewDidLoad];
    3. // ...
    4. // Knöpfchen (rechts)
    5. UIBarButtonItem *filterButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"filter.png"]
    6. style:UIBarButtonItemStylePlain
    7. target:self
    8. action:@selector(dueFilter)];
    9. self.navigationItem.rightBarButtonItem = filterButton;
    10. [filterButton release]; // noch ohne ARC
    11. // ...
    12. }
    Alles anzeigen



    Dann noch das "Herzstück": Der Filter, der sofort einen eigenen FetchRequest aufruft, wenn er gedrückt wird. In meiner App ziemlich simple-Anwendung: Klick auf den Filter und er zeigt Dir nur eine bestimmte Auswahl an und klick noch einmal drauf und er zeigt wieder alles an. Die Filterung basiert hier auf das aktuelle Datum.



    Quellcode

    1. - (void)dueFilter {
    2. // NSLog(@"..auf'n Filter geklickt");
    3. // Mit heutigem Datum den Filter setzen ..
    4. NSDate *heute = [NSDate date];
    5. NSFetchRequest *fetchRequest = self.fetchedResultsController.fetchRequest;
    6. NSError *error2;
    7. // merken des aktuellen Filters!
    8. NSArray *fetchedItemsBefore = [self.moc executeFetchRequest:fetchRequest error:&error2];
    9. NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(returnDate < %@)", heute];
    10. [fetchRequest setPredicate:predicate];
    11. // Vergleich, ob sich etwas an dem Vergleich zw fetchedItemsAfter und ..Before verändert hat
    12. // wenn nicht, wurde zum 2x auf den Filter geklickt. Also wird der Filter jetzt wieder gelöscht
    13. // und alles wird wieder sichtbar
    14. NSArray *fetchedItemsAfter = [self.moc executeFetchRequest:fetchRequest error:&error2];
    15. // Vergleiche das Ergebnis Filter vorher und Filter nachher :-)
    16. if ([fetchedItemsBefore count] == [fetchedItemsAfter count]) {
    17. predicate = [NSPredicate predicateWithFormat:@"(wer != nil) || (was != nil)"];
    18. [fetchRequest setPredicate:predicate];
    19. }
    20. // leere Menge: zeige wieder alles an und gib einen Alert aus
    21. if ([fetchedItemsAfter count] == 0) {
    22. predicate = [NSPredicate predicateWithFormat:@"(wer != nil) || (was != nil)"];
    23. [fetchRequest setPredicate:predicate];
    24. UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Hinweis","")
    25. message:NSLocalizedString(@"Es wurden keine fälligen Einträge gefunden","")
    26. delegate:self
    27. cancelButtonTitle:@"OK"
    28. otherButtonTitles:nil];
    29. [alert show];
    30. [alert release]; // ... mit ARC nicht mehr notwendig
    31. }
    32. // .. und perform the Fetch ;-)
    33. NSError *error;
    34. if (![[self fetchedResultsController] performFetch:&error]) {
    35. NSLog(@"Filter funzt nicht %@, %@", error, [error userInfo]);
    36. abort();
    37. }
    38. [self.tableView reloadData];
    39. }
    Alles anzeigen


    Hoffe Dir hilft es.
    Gruß
    iet
    ----
    Macht's gut und danke für den Fisch
  • Moin iet,
    danke erst einmal für deine Antwort und den Code :)

    Werde es mir heute Abend mal anschauen und prüfen ob ich es auch für meine App nutzen kann. Es ist ja eine ganz andere rangehensweise. Vieleicht klappt es so....

    Werde dich auf dem laufenden halten.

    Danke und Gruß
    Dirk