CoreData nie mogła spełnić winy za

Mam naprawdę irytujący problem, którego po prostu nie mogę naprawić.

Mam Widok, kiedy wysyłam wiadomość, która zostanie zapisana do podstawowych danych, kiedy to się stało, poprosiłem bazę danych o losową wiadomość (zdanie) i zapisałem ją również do innego wiersza w bazie danych.

Jeśli zrobię ostatnią część zakodowaną na twardo, bez pobierania danych z DB, działa to dobrze i elegancko, ale jak tylko pobieram losowy wiersz z DB, to szaleje.

W moim AppDelegate.m:

- (void)save {
    NSAssert(self.context != nil, @"Not initialized");
    NSError *error = nil;
    BOOL failed = [self.context hasChanges] && ![self.context save:&error];
    NSAssert1(!failed,@"Save failed %@",[error userInfo]);
}

- (NSString*)selectRandomSentence
{
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Sentences" inManagedObjectContext:self.managedObjectContext];
    [request setEntity:entity];

    NSError *error = nil;
    NSUInteger count = [self.context countForFetchRequest:request error:&error];

    NSUInteger offset = count - (arc4random() % count);
    [request setFetchOffset:offset];
    [request setFetchLimit:1];

    NSArray *sentenceArray = [self.context executeFetchRequest:request error:&error];

    [request release];

    return [[sentenceArray objectAtIndex:0] sentence];
}

- (NSManagedObjectContext *)context {

    if (_managedObjectContext != nil)
        return _managedObjectContext;

    NSPersistentStoreCoordinator *coordinator = [self coordinator];
    if (coordinator != nil) {
        _managedObjectContext = [[NSManagedObjectContext alloc] init];
        [_managedObjectContext setPersistentStoreCoordinator:coordinator];
    }

    return _managedObjectContext;
}
W moim Chatcontrolle.m:
- (void)didRecieveMessage:(NSString *)message
{
    [self addMessage:message fromMe:NO];
}

#pragma mark -
#pragma mark SendControllerDelegate

- (void)didSendMessage:(NSString*)text {
    [self addMessage:text fromMe:YES];
}

#pragma mark -
#pragma mark Private methods

- (void)responseReceived:(NSString*)response {
    [self addMessage:response fromMe:NO];
}

- (void)addMessage:(NSString*)text fromMe:(BOOL)fromMe {
    NSAssert(self.repository != nil, @"Not initialized");
    Message *msg = [self.repository messageForBuddy:self.buddy];
    msg.text = text;
    msg.fromMe = fromMe;

    if (fromMe)
    {
        [self.bot talkWithBot:text];
    }

    [self.repository asyncSave];

    [self.tableView reloadData];
    [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:[self.buddy.messages count] - 1] atScrollPosition:UITableViewScrollPositionBottom animated:YES];
}
W Moim Offlinebocie.m:
- (void)talkWithBot:(NSString *)textFromMe
{
    AppDelegate *delegate = [[UIApplication sharedApplication] delegate];
    [self didRecieveMessage:[delegate selectRandomSentence]];
}

- (void)didRecieveMessage:(NSString *)message
{
    if ([self.delegate respondsToSelector:@selector(didRecieveMessage:)])
        [self.delegate didRecieveMessage:message];
}

Repozytorium.m

- (Message*)messageForBuddy:(Buddy*)buddy {
    Message *msg = [self.delegate entityForName:@"Message"];
    msg.source = buddy;
    [self.delegate.managedObjectContext refreshObject:buddy mergeChanges:YES];
    return msg;
}

- (void)asyncSave {
    [self.delegate save];
}

Błąd:

2012-08-10 00:28:20.526 Czat[13170: c07] * awaria twierdzenia w - [AppDelegate save], / Users/paulp/Desktop/TestTask/Classes / AppDelegate.m: 28 2012-08-10 00:28: 20.527 Czat[13170: c07] * Kończenie aplikacji z powodu braku exception 'NSInternalInconsistencyException', reason: 'Save failed {type = immutable dict, count = 2, wpisy = > 1: {spis treści = "NSAffectedObjectsErrorKey"} = ( "(entity: zdania; id: 0x6b8bf10 ; data: )" ) 2: {spis treści = "NSUnderlyingException"} = CoreData nie może spełnić błędu dla "0x6b8bf10 ' }

Co robię źle?

Update Wskazałem błąd w tym wierszu:

NSArray *sentenceArray = [self.context executeFetchRequest:request error:&error];

Kiedy wykonuję ten wiersz, dostaję błąd... to jest podczas pobierania danych. Błąd pojawia się jednak, gdy zapisywanie nowych danych do elementu wiadomości. Losowe zdanie jest pobierane ze zdań.

Po zmianie metody asyncSave na saving directly (czyli nie używając nowego wątku) zapisuje pierwszy czat, ale nic po tym. Umiera.

Update Wszystko wydaje się działać używając tego w moim didFinishLaunchingWithOptions:

[self.context setRetainsRegisteredObjects:YES];

Rozumiem, że kontekst modelu obiektowego CodeData nie zwalnia swoich obiektów, co wydaje się być problemem pomiędzy dodawaniem i zapisywaniem. Ale dlaczego?

Author: Paul Peelen, 2012-08-10

5 answers

Nie jest tak naprawdę możliwe koncepcyjnie " zapisywanie" podstawowych obiektów danych " w różnych wierszach". Pamiętaj, że podstawowe dane to Wykres obiektowy, a nie baza danych.

Jeśli chcesz "przenieść" swoje zdanie, najlepszym sposobem jest zniszczenie go i odtworzenie. Jeśli chcesz zachować starą instancję, po prostu utwórz nową, a następnie wypełnij właściwości z istniejącej.

Do niszczenia, użyj

[self.context deleteObject:sentenceObject];

Do odtworzenia użyj

Sentence *newSentence = [NSEntityDescription insertNewObjectForEntityForName:
  "Sentences" inManagedObjectContext:self.context];
newSentence.sentence = sentenceObject.sentence;
// fill in other properties, then
[self.context save:error];

Jeśli chciałbyś przeczytaj o tym, spójrz na "Copying and Copy and Paste "w sekcji" Using Managed Objects "w"Core Data Programming Guide".

 6
Author: Mundi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-13 13:12:56

Hmm. Czy poprawnie implementujesz współbieżność zgodnie z tym przewodnikiem ? Problem, który widzisz, jest powszechny podczas korzystania z podstawowych danych w wielu wątkach. Obiekt został usunięty w "kontekście tła" , a następnie jest dostępny przez inny kontekst. Wywołanie [context processPendingChanges] w kontekście tła po usunięciu, ale przed zapisaniem może pomóc.

Istnieje również sesja WWDC 2010 (137) na temat optymalizacji wydajności danych podstawowych, która przechodzi w usuwanie bitów.

Kiedy wykonując polecenie Fetch Core Data zwraca kolekcję obiektów pasujących do podanego predykatu. Te obiekty nie mają jeszcze ustawionych wartości właściwości. Gdy uzyskujesz dostęp do właściwości, Podstawowe Dane wracają do sklepu, aby "odpalić błąd" - wypełnić właściwość danymi ze sklepu. "Nie mógł spełnić winy..."wyjątki zdarzają się, gdy podstawowe dane trafiają do magazynu w celu uzyskania wartości właściwości obiektu, ale obiekt nie istnieje w magazynie trwałym. Zarządzane kontekst obiektu myślał powinien istnieć, dlatego mógłby próbować popełnić błąd - i tam jest problem. Kontekst, który spowodował wyrzucenie wyjątku, nie wiedział, że ten obiekt został usunięty ze sklepu przez coś innego (np. inny kontekst).

Uwaga powyższy przewodnik dotyczący współbieżności jest już nieaktualny, powinieneś używać kontekstów rodzic-dziecko i prywatnej kolejki współbieżności zamiast starszego modelu ograniczającego wątek. Konteksty rodzic-dziecko są bardzo mniej prawdopodobne, aby uruchomić " nie może spełnić błąd..."z wielu powodów. I proszę, zgłoś błąd w dokumentacji lub skorzystaj z formularza zwrotnego, aby poprosić o aktualizację przewodnika współbieżności.

 61
Author: quellish,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-07 02:56:27

Sprawdź mechanizm podstawowych danych. "Błąd zmniejsza ilość pamięci zużywanej przez aplikację. Błąd jest obiektem zastępczym, który reprezentuje zarządzany obiekt, który nie został jeszcze w pełni zrealizowany, lub obiektem kolekcji, który reprezentuje relację: "

 1
Author: paul,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-30 03:39:55

Dzieje się tak, ponieważ dodajesz "losową wiadomość" do nowego wiersza przed zakończeniem pobierania wszystkich relacji pierwszego wywołania.

Możesz dodać prefetch do pierwszego połączenia, aby uniknąć leniwego ładowania, a problem zostanie rozwiązany, jak sądzę.

W ten sposób możemy wykonać prefetching dla zapytania:

[request setRelationshipKeyPathsForPrefetching:[NSArray arrayWithObjects:@"whatEverOfYourWillNumberOne",@"whatEverOfYourWillNumberTwo", nil]];
Mam nadzieję, że to pomoże.
 0
Author: Deepukjayan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-25 04:23:35

Naprawiłem błąd zmieniając łańcuch "cacheName" kontrolera NSFetchedResultsController na nil.

Nsfetchedresultscontroller *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext: self.managedObjectContext sectionNameKeyPath:nil cacheName:@"Root"nil];

 0
Author: mishimay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-02 08:20:25