CPU Auslastung 100% bei Coredata Abfrage

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

  • CPU Auslastung 100% bei Coredata Abfrage

    Hallo,

    ich habe mir folgenden Coredata Abfrage gebaut:

    Quellcode

    1. //alle reisen suchen die zu der Person gehören
    2. if (self.person != nil) {
    3. NSMutableArray *arrayWithEvents = [NSMutableArray array];
    4. for (id eventForPerson in [self.person valueForKey:@"event"]) {
    5. [arrayWithEvents addObject:[NSPredicate predicateWithFormat:@"ANY %K == %@", cEntityReiseRelationshipEvent, eventForPerson]];
    6. }
    7. //Verknüpfung der einzelen Events mit einem ODER das alle gesucht werden
    8. self.fetchPredicateReise = [NSCompoundPredicate orPredicateWithSubpredicates:arrayWithEvents];
    9. } else {
    10. self.fetchPredicateReise = nil;
    11. }
    Alles anzeigen


    Quellcode

    1. -(NSFetchedResultsController *)fetchedResultsControllerReise {
    2. if(self.detailEventReiseFetchResultsController != nil) {
    3. return self.detailEventReiseFetchResultsController;
    4. }
    5. NSFetchRequest *fetchRequest = [[NSFetchRequest alloc]init];
    6. NSEntityDescription *entityDescription = [NSEntityDescription entityForName:cEntityReise inManagedObjectContext:[JSMCoreDataHelper managedObjectContext]];
    7. fetchRequest.entity = entityDescription;
    8. fetchRequest.predicate = self.fetchPredicateReise;
    9. fetchRequest.fetchBatchSize = 64;
    10. NSSortDescriptor *sortPerson = [[ NSSortDescriptor alloc] initWithKey:cEntityReiseAttributeKurzbezeichnung ascending:YES];
    11. NSArray *sortArray = [NSArray arrayWithObject:sortPerson];
    12. fetchRequest.sortDescriptors = sortArray;
    13. self.detailEventReiseFetchResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:[JSMCoreDataHelper managedObjectContext] sectionNameKeyPath:nil cacheName:nil];
    14. self.detailEventReiseFetchResultsController.delegate = self;
    15. return self.detailEventReiseFetchResultsController;
    16. }
    Alles anzeigen


    Wenn ich nun diese Abfrage ausführe, habe ich das Problem, dass meine Meine App 100% CPU benötigt und gar nix mehr macht. Ich habe raus gefunden das dieses Problem bei dieser Codestelle auftritt:

    Quellcode

    1. + (BOOL) performOnFetchResultController: (NSFetchedResultsController *) fetchResultController{
    2. NSError *error;
    3. if(![fetchResultController performFetch:&error]) {
    4. NSLog(@"Fehler: %@", error.localizedDescription);
    5. return NO;
    6. }
    7. return YES;
    8. }


    Ich denke dass es mit dem NSPredicate zusammenhängt, was ich mir über das Array zusammenbaue, nur leider weiß ich gerade nicht genau, warum ich hier gerade so extreme Performenceprobleme bekomme. Wenn ich 2 oder 3 Events in dem Array habe, läuft alles perfekt, aber wenn ich 8 drin habe geht einfach gar nix mehr.

    Danke

    Gruß

    Bongartz
    Vielen Dank

    Gruß

    Bongartz
  • Der performFetch: dürfte nicht der Fehler sein :-)))
    Der macht ja nur das, was Du ihm sagst.

    Deine For-Schleife sieht irgendwie komisch aus.

    Quellcode

    1. for (id eventForPerson in [self.person valueForKey:@"event"]) {
    2. [arrayWithEvents addObject:[NSPredicate predicateWithFormat:@"ANY %K == %@", cEntityReiseRelationshipEvent, eventForPerson]];
    3. }

    Ohne Deinen Code jetzt ausprobiert zu haben, machst Du grob Folgendes (und das kann so auch nur schief gehen).
    Die For-Bedingung soll Dir alle Objekte ausgeben, die mit dem Wert (wahrscheinlich Deine Relationship Entity) "event" verknüpft ist heraussuchen.
    Und innerhalb der For-Schleife baust Du Dir eine neue Bedinugng mit NSPredicate auf. Ich denke mal, dass er hier auf sich selbst referenziert. Das NSPredicate musst Du Dir wie eine eigene SQL-Select-Anweisung vorstellen. Eigentlich solltest Du ohne die For-Schleife nur anhand Deines Predicates Dein Ergebnis finden. ein NSPredicate liefert ja auch ein vollumfängliches Ergebnis (mit allen gefundenen Datensätzen) zurück.
    Du baust bei jedem Schleifendurchlauf immer ein komplettes Array neu auf. Findet er also 1.000 Datensätze beim ersten For-Lauf, bekommst Du beim zweiten Lauf wieder dieselben (nicht diegleichen) 1.000 Datensätze erneut dazu, usw.
    ----
    Macht's gut und danke für den Fisch
  • Ja was du sagst ist sinnvoll ,aber wenn ich es ohne die interation über den NSSet mit den Events mache bekomme ich immer einen Fehler.

    ohne Schleife:

    Quellcode

    1. self.fetchPredicateReise = [NSPredicate predicateWithFormat:@"ANY %K == %@", cEntityReiseRelationshipEvent, self.person.event];


    Fehler:

    Quellcode

    1. -[_NSFaultingMutableSet longLongValue]: unrecognized selector sent to instance 0x8f788b0
    2. *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[_NSFaultingMutableSet longLongValue]: unrecognized selector sent to instance 0x8f788b0'


    Wahrscheinlich habe ich gerade nur die Augen zu :)

    Danke
    Vielen Dank

    Gruß

    Bongartz
  • Hier der Inhalt des Array's, welcher für mich jetzt eigentlich gar nicht so schlecht aussieht.

    Quellcode

    1. arrayWithEvents: (
    2. "ANY event == <Event: 0x8b4fff0> (entity: Event; id: 0x8b4f290 <x-coredata://7FF3C06C-9297-4BDC-8B14-8B9E2485E6D5/Event/p5> ; data: <fault>)",
    3. "ANY event == <Event: 0x8b4ffb0> (entity: Event; id: 0x8b4f280 <x-coredata://7FF3C06C-9297-4BDC-8B14-8B9E2485E6D5/Event/p4> ; data: <fault>)",
    4. "ANY event == <Event: 0x8b4ff70> (entity: Event; id: 0x8b4f510 <x-coredata://7FF3C06C-9297-4BDC-8B14-8B9E2485E6D5/Event/p3> ; data: <fault>)",
    5. "ANY event == <Event: 0x8b500d0> (entity: Event; id: 0x8b4f2c0 <x-coredata://7FF3C06C-9297-4BDC-8B14-8B9E2485E6D5/Event/p8> ; data: <fault>)",
    6. "ANY event == <Event: 0x8b50090> (entity: Event; id: 0x8b4f2b0 <x-coredata://7FF3C06C-9297-4BDC-8B14-8B9E2485E6D5/Event/p7> ; data: <fault>)",
    7. "ANY event == <Event: 0x8b50050> (entity: Event; id: 0x8b4f2a0 <x-coredata://7FF3C06C-9297-4BDC-8B14-8B9E2485E6D5/Event/p6> ; data: <fault>)",
    8. "ANY event == <Event: 0x8b4f4b0> (entity: Event; id: 0x8b4f500 <x-coredata://7FF3C06C-9297-4BDC-8B14-8B9E2485E6D5/Event/p2> ; data: <fault>)",
    9. "ANY event == <Event: 0x8b50150> (entity: Event; id: 0x8b4f2d0 <x-coredata://7FF3C06C-9297-4BDC-8B14-8B9E2485E6D5/Event/p9> ; data: <fault>)",
    10. "ANY event == <Event: 0x8b50190> (entity: Event; id: 0x8b4f2e0 <x-coredata://7FF3C06C-9297-4BDC-8B14-8B9E2485E6D5/Event/p10> ; data: <fault>)"
    11. )
    Alles anzeigen


    Aber irgendwo muss ja mein Denkfehler sein.
    Vielen Dank

    Gruß

    Bongartz
  • Weil Event ein to-many-Ralationship ist, ohne das ANY geht es leider gar nicht.

    Mein Datenmodel ist so auf gebaut:

    reise <--> Event <--> Person.

    Jetzt will ich über die Person an die Reisen kommen. Ich weiß welche Evetns die Person hat und Scheiter jetzt gerade an dieser abfrage :(
    Vielen Dank

    Gruß

    Bongartz
  • puh ... das ist echt schwieriger.
    da muss ich mal zu Hause schauen, ob mein letztes CD-Modell ähnlich war.
    was würde passieren, wenn Du ohne event nach den reisen suchst? manchmal ist CD ja schlauer als SQL - zumindest passieren für mich ab und zu gefühlt noch wunder, weil man sich nicht um alles kümmern muss.
    probier doch mal ob CD ein "self.Person.Event.reise" verkraftet.
    ----
    Macht's gut und danke für den Fisch
  • Sollte es nicht einfach sein nach den events zu suchen die die Person hat und danach die Reisen für diese Events? Also erst einen Fetch auf die Events mit Person.ID wie gewünscht und dann einfach events.Reise auszugeben?

    Gruß

    Claus
    2 Stunden Try & Error erspart 10 Minuten Handbuchlesen.

    Pre-Kaffee-Posts sind mit Vorsicht zu geniessen :)
  • Also entweder ich verstehe den Aufbau falsch oder es wird zu kompliziert gedacht.

    Core Data ist nun einmal keine Datenbank.

    Du hast eine Person?
    Du möchtest die Reisen dieser Person kennen?

    Gesetzt dem Fall Dein Datenmodell ist korrekt angelegt und die Hin- und Rückbeziehungen stehen:

    C-Quellcode

    1. // Ich wrappe diese direkten valueForKey: Zugriffe ja lieber in Methoden einer eigenen Klasse…
    2. NSSet * personalEvents = [person valueForKey:@"event"]; // Sieht für mich nach einer Collection aus, wenn ich Dein Predicate richtig verstehe.
    3. for(Event * currentEvent in personalEvents) {
    4. Reise * eventReise = [currentEvent valueForKey:@"reise"]; // Sieht für mich nach einem einzigen Objekt aus, wenn Ich dein Predicate richtig verstehe.
    5. }


    Eventuell kannst Du das ja in ein NSPredicate packen.

    C-Quellcode

    1. NSPredicate * reisenPredicate = [NSPredicate predicateWithFormat:@"%K", "event.reise"];
    2. [personalEvents filteredArrayUsingPredicate:reisenPredicate];


    Ihr immer mit euren Fetches…
    «Applejack» "Don't you use your fancy mathematics to muddle the issue!"

    Iä-86! Iä-64! Awavauatsh fthagn!

    kmr schrieb:

    Ach, Du bist auch so ein leichtgläubiger Zeitgenosse, der alles glaubt, was irgendwelche Typen vor sich hin brabbeln. :-P
  • So habe es jetzt ohne fetch gelöst, ich weiß dass man es bestimmt noch eleganter lösen kann, aber nagt diese Lösung ist mir jetzt eingefallen und es läuft so wie man es erwartet:

    Quellcode

    1. self.eventReise = [NSMutableArray array];
    2. BOOL boolFoundReise;
    3. NSSet * personalEvents = [self.person valueForKey:@"event"]; // Sieht für mich nach einer Collection aus, wenn ich Dein Predicate richtig verstehe.
    4. for(Event * currentEvent in personalEvents) {
    5. Reise* tempReise = [currentEvent valueForKey:@"reise"];
    6. boolFoundReise = NO;
    7. if ([self.eventReise count] == 0) {
    8. [self.eventReise addObject:tempReise];
    9. } else {
    10. for(Reise *serachReise in self.eventReise){
    11. if (serachReise == tempReise) {
    12. boolFoundReise = YES;
    13. }
    14. if (!boolFoundReise){
    15. [self.eventReise addObject:tempReise];
    16. }
    17. }
    18. }
    19. }
    Alles anzeigen


    Danke für Eure Hilfe und den richtigen Denkanstoß :)
    Vielen Dank

    Gruß

    Bongartz