Quindi, dopo aver dedicato un po 'di tempo a questo problema ...!
Le risposte di cui sopra sono ottimi mattoni e senza di loro sarei stato perso, ma come con altri intervistati ho scoperto che funzionavano solo parzialmente. Se li realizzi, scoprirai che funzionano una o due volte, poi un errore o perdi dati mentre vai. La risposta qui sotto è ben lungi dall'essere perfetta: è il risultato di molte nottate, prove ed errori.
Ci sono alcuni problemi con questi approcci:
La NSFetchedResultsController legato alla NSMutableArray non garantisce che il contesto sarà aggiornato, così si può vedere che questo funziona a volte, ma non altri.
La copia quindi elimina l'approccio per lo scambio di oggetti è anche un comportamento difficile da prevedere. Ho trovato riferimenti altrove a comportamenti imprevedibili nel fare riferimento a un oggetto che era stato eliminato nel contesto.
Se si utilizza la riga di indice dell'oggetto e si dispone di sezioni, questo non si comporterà correttamente. Parte del codice sopra utilizza solo la proprietà .row e sfortunatamente questo potrebbe riferirsi a più di una riga in un
Utilizzo di NSFetchedResults Delegato = nil, è ok per le applicazioni semplici, ma si consideri che si desidera utilizzare il delegato per acquisire le modifiche che verranno replicate in un database, è possibile vedere che questo non funzionerà correttamente.
Core Data non supporta in realtà l'ordinamento e l'ordinamento nel modo in cui funziona un database SQL corretto. La soluzione loop for above è buona, ma dovrebbe esserci un modo corretto di ordinare i dati - IOS8? - Quindi devi entrare in questo aspetto aspettando che i tuoi dati saranno dappertutto.
I problemi che le persone hanno inviato in risposta a questi post riguardano molti di questi problemi.
ho ottenuto un tavolo semplice applicazione con le sezioni a 'parzialmente' lavoro - ci sono ancora comportamenti UI inspiegabili che sto lavorando, ma credo che ho avuto modo di fondo di esso ...
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
Questa è la solita delegato
{
userDrivenDataModelChange = YES;
utilizza il meccanismo semaforo come descritto sopra con le strutture di ritorno, se().
NSInteger sourceRow = sourceIndexPath.row;
NSInteger sourceSection = sourceIndexPath.section;
NSInteger destinationRow = destinationIndexPath.row;
NSInteger destinationSection = destinationIndexPath.section;
Non
tutti questi sono utilizzati nel codice, ma è utile avere loro per il debug
NSError *error = nil;
NSIndexPath *destinationDummy;
int i = 0;
inizializzazione finale di variabili
destinationDummy = [NSIndexPath indexPathForRow:0 inSection:destinationSection] ;
// there should always be a row zero in every section - although it's not shown
Io uso una riga 0 in ogni sezione che è nascosta, memorizza il nome della sezione. Ciò consente alla sezione di essere visibile, anche quando non ci sono "registrazioni live". Io uso la riga 0 per ottenere il nome della sezione. Il codice qui è un po 'disordinato, ma fa il lavoro.
NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
NSManagedObject *currentObject = [self.fetchedResultsController objectAtIndexPath:sourceIndexPath];
NSManagedObject *targetObject = [self.fetchedResultsController objectAtIndexPath:destinationDummy];
Prendi il contesto e la fonte e oggetti di destinazione
Questo codice crea un nuovo oggetto che è prende i dati dalla sorgente, e la sezione dalla destinazione.
// set up a new object to be a copy of the old one
NSManagedObject *newObject = [NSEntityDescription
insertNewObjectForEntityForName:@"List"
inManagedObjectContext:context];
NSString *destinationSectionText = [[targetObject valueForKey:@"section"] description];
[newObject setValue:destinationSectionText forKeyPath:@"section"];
[newObject setValue: [NSNumber numberWithInt:9999999] forKey:@"rowIndex"];
NSString *currentItem = [[currentObject valueForKey:@"item"] description];
[newObject setValue:currentItem forKeyPath:@"item"];
NSNumber *currentQuantity =[currentObject valueForKey:@"quantity"] ;
[newObject setValue: currentQuantity forKey:@"rowIndex"];
Ora creare un nuovo oggetto e salvare il contesto - questo è barare l'operazione di spostamento - non si potrebbe ottenere il nuovo record esattamente il posto che è stata abbandonata - ma almeno sarà nella sezione giusta.
// create a copy of the object for the new location
[context insertObject:newObject];
[context deleteObject:currentObject];
if (![context save:&error]) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
Ora eseguire l'aggiornamento del ciclo for come descritto sopra. Si noti che il contesto viene salvato prima di eseguire questa operazione, non so perché è necessario, ma non funzionava correttamente quando non lo era!
i = 0;
for (NSManagedObject *mo in [self.fetchedResultsController fetchedObjects])
{
[mo setValue:[NSNumber numberWithInt:i++] forKey:@"rowIndex"];
}
if (![context save:&error]) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
Impostare il semaforo indietro e aggiornare la tabella
userDrivenDataModelChange = NO;
[tableView reloadData];
}
Vedi esempio di codice qui: http://stackoverflow.com/a/15625897/308315 – iwasrobbed