CoreData fetch zwischen Apple Watch und iPhone nicht synchron

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

  • CoreData fetch zwischen Apple Watch und iPhone nicht synchron

    Hallo Zusammen,

    ich stehe gerade vor einem für mich sehr komische Problem. Ich habe eine iPhone App mit einer Apple Wacht Erweiterung erstellt. An sich läuft auch beides recht gut, nur das Update der Daten über Core Data bringt mich gerade zum verzweifeln. Zu erst ging ich davon aus, dass es ein Darstellungsproblem auf der Apple Watch ist, aber dies konnte ich auf ein Core Data refresh/fetch Problem eingrenzen.

    Aber gut was ist überhaupt das Problem :-). Ich habe meine Core Data DB über App Groups aufgebaut, so dass iPhone und Watch auf die gleiche DB zugreifen können. Wenn ich jetzt eine Änderung auf der Watch durchführe, soll diese auch auf dem iPhone zusehen sein. Dies geht aber leider nur mit folgender Einschränkung. Die Änderung wird auf der Apple Watch zu 100% dargestellt z.B.: Person A hatte 50€ und dies wird über die Watch auf 0€ geändert. Dann kann man auf der Watch dies in der Übersicht sehen und in der Detailansicht wo auch der Button ist um den Wert zu ändern.

    Auf dem iPhone hingeben wird die Änderung bei der Übersicht nicht dargestellt aber bei der Detailsicht. Was mich natürlich extrem verwundert. Wenn man sich die Daten von Core Data anzeigen lässt, sieht ma auch das der fetch in der Übersicht alte Daten anzeigt. Genau das gleiche Verhalten habe ich,wenn ich den Wert über das iPhone ändere. So ist die Übersicht auf der Watch alt und die Dateiansicht neu.

    Hier mein Code wie ich fetche und meine UITable mit Daten fülle:


    C-Quellcode

    1. #pragma mark - ViewDidLoad
    2. -(instancetype)init {
    3. self = [super init];
    4. if (self) {
    5. // perform initialization
    6. self.numberF = [[NSNumberFormatter alloc] init];
    7. [self.numberF setNumberStyle:NSNumberFormatterDecimalStyle];
    8. [self.numberF setMaximumFractionDigits:2];
    9. self.numberF.numberStyle = NSNumberFormatterCurrencyStyle;
    10. self.wormhole = [[MMWormhole alloc] initWithApplicationGroupIdentifier:@"group.de.bitsmaker.itravel" optionalDirectory:@"wormhole"];
    11. [self.wormhole listenForMessageWithIdentifier:@"updateFromPhone" listener:^(id messageObject) {
    12. NSLog(@"recieved update from wormhole !!");
    13. [JSMCoreDataHelper performOnFetchResultController:self.fetchedResultsController];
    14. [self reloadData];
    15. }];
    16. }
    17. return self;
    18. }
    19. -(void) willActivate {
    20. [JSMCoreDataHelper performOnFetchResultController:self.fetchedResultsController];
    21. [self reloadData];
    22. }
    23. - (void)reloadData {
    24. [self.tableWithPersonsTheyPay setNumberOfRows:[self.fetchedResultsController.fetchedObjects count] withRowType:@"AWPersonTableCell"];
    25. __weak __typeof__(self) weakSelf = self;
    26. [[self.fetchedResultsController fetchedObjects] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
    27. __strong __typeof__(self) strongSelf = weakSelf;
    28. [strongSelf.noDataLabel setHidden:YES];
    29. [strongSelf configureRowAtIndex:idx];
    30. }];
    31. }
    32. - (void)configureRowAtIndex:(NSUInteger)index {
    33. __weak __typeof__(self) weakSelf = self;
    34. dispatch_async(dispatch_get_main_queue(), ^()
    35. {
    36. __strong __typeof__(self) strongSelf = weakSelf;
    37. NSNumber *sumCostsForPerson;
    38. AWPersonTableRow* row = [strongSelf.tableWithPersonsTheyPay rowControllerAtIndex:index];
    39. NSIndexPath *realIndexPath = [NSIndexPath indexPathForRow:index inSection:0];
    40. BMPerson *person = [self.fetchedResultsController objectAtIndexPath:realIndexPath];
    41. row.firstNameLabel.text = @"";
    42. row.lastNameLabel.text = @"";
    43. row.firstNameLabel.text = person.vorname;
    44. row.lastNameLabel.text = person.nachname;
    45. NSPredicate* suchePerson = [NSPredicate predicateWithFormat:@"%K == %@", cEntityKostenRelationshipPerson, person];
    46. sumCostsForPerson = @(0);
    47. for (BMKosten* gefundeneKosten in [person.kosten filteredSetUsingPredicate:suchePerson]) {
    48. if (gefundeneKosten) {
    49. if (gefundeneKosten.wertOffen.integerValue <0) {
    50. if (gefundeneKosten.wertGezahltAnPerson.integerValue < 0) {
    51. sumCostsForPerson = [NSNumber numberWithDouble: ( sumCostsForPerson.integerValue + gefundeneKosten.wertOffen.integerValue -1* gefundeneKosten.wertGezahltAnPerson.integerValue)];
    52. }else{
    53. sumCostsForPerson = [NSNumber numberWithDouble: (sumCostsForPerson.integerValue + gefundeneKosten.wertOffen.integerValue + gefundeneKosten.wertGezahltAnPerson.integerValue)];
    54. }
    55. }else{
    56. if (gefundeneKosten.wertGezahltAnPerson.integerValue < 0) {
    57. sumCostsForPerson = [NSNumber numberWithDouble: ( sumCostsForPerson.integerValue + gefundeneKosten.wertOffen.integerValue + gefundeneKosten.wertGezahltAnPerson.integerValue)];
    58. }else{
    59. sumCostsForPerson = [NSNumber numberWithDouble: ( sumCostsForPerson.integerValue + gefundeneKosten.wertOffen.integerValue + gefundeneKosten.wertGezahltAnPerson.integerValue)];
    60. }
    61. }
    62. }
    63. }
    64. //Minus Zeichen bei Null entfernen
    65. row.betragLabel.text = @"";
    66. row.betragLabel.text = [self.numberF stringFromNumber:[BMToolBox setStringWithNumberOfVauleOrZero:[BMToolBox changeCentsToMoney:sumCostsForPerson]]];
    67. NSLog(@"Person: %@ Kosten: %@", person.vorname, sumCostsForPerson);
    68. //Farben zuweisen an Hand der Summe ob rot oder grün
    69. [row.betragLabel setTextColor:[BMToolBox setColorForVaule:sumCostsForPerson.integerValue]];
    70. });
    71. }
    72. -(NSFetchedResultsController *)fetchedResultsController {
    73. if(self.detailEventFetchResultsController != nil) {
    74. return self.detailEventFetchResultsController;
    75. }
    76. NSFetchRequest *fetchRequest = [[NSFetchRequest alloc]init];
    77. NSEntityDescription *entityDescription = [NSEntityDescription entityForName:cEntityPerson inManagedObjectContext:[JSMCoreDataHelper managedObjectContext]];
    78. fetchRequest.entity = entityDescription;
    79. fetchRequest.predicate = self.fetchPredicate;
    80. fetchRequest.fetchBatchSize = 64;
    81. NSSortDescriptor *sortPerson = [[ NSSortDescriptor alloc] initWithKey:cEntityPersonAttributeVorname ascending:YES];
    82. NSArray *sortArray = [NSArray arrayWithObject:sortPerson];
    83. fetchRequest.sortDescriptors = sortArray;
    84. self.detailEventFetchResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:[JSMCoreDataHelper managedObjectContext] sectionNameKeyPath:nil cacheName:nil];
    85. self.detailEventFetchResultsController.delegate = self;
    86. return self.detailEventFetchResultsController;
    87. }
    Alles anzeigen
    Wie man in dem Init sehen kann, habe ich das MMWormhole verwendet um mit zu bekommen, ob es eine Änderung auf dem iPhone gab. Der dargestellte Code bezieht sich auf die Watch Erweiterung.

    Vielen Dank
    Vielen Dank

    Gruß

    Bongartz
  • Ja diese Vermutung hatte ich auch nur ich weiß nicht wie ich diese synchron bekomme.

    Beide Contexte schreiben in die gleiche Core Data DB, aber sind ab und zu asynchron. Habe versucht mit refreshContex zu arbeiten aber komm mit dem Syntax nicht klar ;(
    Vielen Dank

    Gruß

    Bongartz
  • Danke dir.

    Jetzt habe ich leider aber wieder das gleiche Verständnisproblem, da ich beide Contexte über die gleiche Methode in der gleichen Klasse erzeuge. Somit weiß ich jetzt gerade nicht wie ich die Contexte abgleichen soll :(

    Hier der Code wie ich zentral den Context erstelle.

    C-Quellcode

    1. NSManagedObjectContext*) managedObjectContext
    2. {
    3. static NSManagedObjectContext *managedObjectContext;
    4. if (managedObjectContext != nil) {
    5. return managedObjectContext;
    6. }
    7. NSError *error;
    8. NSString *sharedContainerPathLocation = [[self getSharedContainerURLPath] path];
    9. NSString *directoryToCreate = @"itravel";
    10. NSString *dirPath = [sharedContainerPathLocation stringByAppendingPathComponent:directoryToCreate];
    11. [[NSFileManager defaultManager] createDirectoryAtPath:dirPath withIntermediateDirectories:YES attributes:nil error:&error];
    12. if (error) {
    13. NSLog(@"Fehler: %@", error.localizedDescription);
    14. return nil;
    15. }
    16. //Pfad anpassung für CoreShare Framework mit Group
    17. NSURL *url = [NSURL fileURLWithPath: [NSString stringWithFormat:@"%@/%@", dirPath, @"data.sqlite" ]];
    18. NSManagedObjectModel *managedModel = [NSManagedObjectModel mergedModelFromBundles:nil];
    19. NSPersistentStoreCoordinator *storeCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:managedModel];
    20. if (! [storeCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:url options:[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil] error:&error]) {
    21. NSLog(@"Fehler: %@", error.localizedDescription);
    22. return nil;
    23. }
    24. managedObjectContext = [[NSManagedObjectContext alloc] init];
    25. managedObjectContext.persistentStoreCoordinator = storeCoordinator;
    26. return managedObjectContext;
    27. }
    Alles anzeigen
    Vielen Dank

    Gruß

    Bongartz