Domanda

Se si utilizza una NSFetchedResultsController per gestire la visualizzazione di oggetti gestiti recuperati in una vista tabella che ha una sezione. La tabella inizia vuota e l'utente può aggiungere nuove entità ad esso utilizzando l'interfaccia utente. Così com'è, il programma funziona sempre quando si aggiunge la prima entità, e sempre si blocca quando si aggiunge un secondo. A volte c'è alcun errore presentato sulla schianto e altre volte ci sono errori di differenti tipi (alcuni incluso di seguito). Attraverso le dichiarazioni di log e tracciamento vedo che il programma si blocca subito dopo controllerWillChangeContent del delegato del NSFetchResultsController (che chiama [self.tableView beginUpdates];) Metodo uscite, ma prima di qualsiasi altro metodo nel mio codice è chiamato. Ecco alcune delle parti relavant del mio codice. Configurazione del NSFetchedResultsController:

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:[NSEntityDescription entityForName:@"Beer"
                                    inManagedObjectContext:self.managedObjectContext]];

// Configure request's entity and predicate
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
[sortDescriptor release];
[sortDescriptors release];

NSString *expression = [NSString stringWithFormat:@"brewery.name LIKE \"%@\"", self.brewery.name];
NSPredicate *predicate = [NSPredicate predicateWithFormat:expression];
[fetchRequest setPredicate:predicate];
self.resultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
                                                             managedObjectContext:self.managedObjectContext
                                                               sectionNameKeyPath:nil
                                                                        cacheName:nil];
self.resultsController.delegate = self;
[fetchRequest release];

NSError *error = nil;
BOOL success = [resultsController performFetch:&error];
if (!success) {
    NSLog(@"Error fetching request %@", [error localizedDescription]);
}

L'aggiunta di nuova entità:

NSEntityDescription *entity = [NSEntityDescription entityForName:@"Beer" inManagedObjectContext:self.managedObjectContext];
Beer *beer = [[Beer alloc] initWithEntity:entity insertIntoManagedObjectContext:self.managedObjectContext];
beer.name = beerName;
beer.brewery = self.brewery;

Ho visto le avvertenze nella documentazione sui problemi che espongono le tabelle con una sezione, e ho usato soluzione di Apple per questo senza alcun risultato. Questi metodi non sono sempre chiamati prima dello schianto in ogni caso.

Alcuni degli errori che ho ricevuto:

Serious application error.  Exception was caught during Core Data change processing: *** -[NSCFString compareObject:toObject:]: unrecognized selector sent to instance 0x4e808c0 with userInfo (null)
Serious application error.  Exception was caught during Core Data change processing: *** -[CALayer compareObject:toObject:]: unrecognized selector sent to instance 0x4e53b80 with userInfo (null)
Serious application error.  Exception was caught during Core Data change processing: *** -[UITextTapRecognizer controllerWillChangeContent:]: unrecognized selector sent to instance 0x4ca5d70 with userInfo (null)
Serious application error.  Exception was caught during Core Data change processing: *** -[CALayer controllerWillChangeContent:]: unrecognized selector sent to instance 0x4e271a0 with userInfo (null)
Serious application error.  Exception was caught during Core Data change processing: *** -[NSCFNumber countByEnumeratingWithState:objects:count:]: unrecognized selector sent to instance 0x4c96ee0 with userInfo (null)

Come si può vedere, gli errori (quando uno è stato presentato) non sono coerenti, anche in assenza di modifica al codice è stato fatto.

Chiunque può capire che cosa sto facendo male?

È stato utile?

Soluzione

I tuoi errori incoerenti indicano un possibile problema over-release. Tanto più che cambiare i vostri delegati di ricaricare solo i dati rende la questione andare via. Personalmente vorrei investire il tempo per risolvere il problema, piuttosto che codifica intorno ad esso, come è sicuramente avere un problema di codice lì che probabilmente mostrerà in seguito da qualche altra parte.

Vorrei fare quanto segue:

  1. Accendere NSZombie
  2. Aggiungi un punto di interruzione per objc_exception_throw
  3. Esegui nel debugger

Quando si verifica l'eccezione, guardare l'indirizzo di memoria e vedere che cosa si accede e dove. Ciò isolare il problema e ti dirà cosa sta succedendo. Sarebbe anche utile, se questo non rivela il problema, per pubblicare i vostri metodi NSFetchedResultsController delegare così posso vedere se c'è qualcosa di strano in loro.

Best per aggiornare la domanda originale con le informazioni aggiuntive.

Altri suggerimenti

Il codice per creare nuove entità è tutto strano. Cosa succede ad usare questo, invece:

Beer* beer = [NSEntityDescription insertNewObjectForEntityForName: @"Beer" 
    inManagedObjectContext: self.managedObjectContext];
beer.name = @"Grolsch";

Inoltre, non sta chiamando NSManagedObjectContext#save:. Ma forse si sta facendo che in una parte del codice che ora è fatto vedere?

Mentre io non ha risolto questo problema particolare, ho preso un approccio leggermente diverso a scrivere la classe che ha dato il la funzionalità che voglio e non ha causato il problema a sorgere. Sto ancora utilizzando NSFetchedResultsController, ma invece di attuare tutti e quattro i metodi delegato, io sto solo implementando controllerDidChangeContent :, che richiede solo [tableView reloadData].

Questa è l'implementazione che è incluso nella classe RootViewController se si crea una nuova applicazione di navigazione basato in XCode che utilizza Core Data per la conservazione. Probabilmente perde un po 'di controllo sulla tabella-modificare le animazioni, ma è molto più semplice e funziona bene per i miei scopi.

Ho avuto un bug simile di recente - il problema è con il rilascio, in particolare:

[sortDescriptors release];

È possibile ottenere i sortDescriptors oggetto da

[NSArray arrayWithObjects:sortDescriptor, nil];

che non ha "alloc", "copia" o "nuovo", quindi restituisce un oggetto autoreleased. Perché lo si rilascia presto, si ottengono due posti dove si può mandare in crash - quando il NSFetchRequest lo usa, e quando viene rilasciato in piscina. Vedere guida di gestione della memoria di Apple per maggiori dettagli .

Questo è un vecchio uno, ma per il bene degli altri che hanno lo stesso problema, ho passato ore a cercare di capire cosa stava succedendo e hanno finalmente trovato un problema con il mio descrittore tipo che stava causando questi crash casuali.

I messaggi di errore variavano ma erano principalmente correlato ad un compareObject: selettore ToObject come sotto

.

- [_ NSCFSet compareObject: ToObject:]: selettore non riconosciuto inviato ad esempio - [ _NSCFString compareObject: ToObject:] selettore non riconosciuto inviato ad esempio

Il mio suggerimento è quello di cercare di eliminare tutti i descrittori di ordinamento e predicati dal codice e quindi aggiungere uno per uno per trovare dove sia il problema.

In bocca al lupo! Rog

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top