Domanda Riordino dei dati di base di UITableView


So che questa domanda è stata fatta prima e ho dato un'occhiata alla risposta a questa domanda. Tuttavia, sono ancora confuso su come implementare il riordino con un UITableView in un progetto Core Data. Quello che so è che ho bisogno di avere un attributo "displayOrder" nella mia Entity per tracciare l'ordine degli oggetti, e ho bisogno di enumerare attraverso tutti gli oggetti nei risultati recuperati e impostare il loro attributo displayOrder.

Nel codice indicato nella domanda a cui ho collegato, il metodo delegate view della tabella chiama un metodo come questo [self FF_fetchResults];e il codice per quel metodo non è dato quindi è difficile dire cosa sia esattamente.

C'è qualche codice di esempio che dimostri questo? Sarebbe più semplice da guardare rispetto alla condivisione di grossi pezzi di codice.

Grazie


25
2018-03-02 04:38


origine


risposte:


Non sono sicuro di quale parte hai problemi (in base ai commenti) ... ma ecco il mio suggerimento. DisplayOrder è solo un semplice attributo su una classe NSManagedObject. Se è possibile salvare un oggetto gestito, sarà possibile completare questa funzione. Per prima cosa prendi un semplice NSManagedObject:

@interface RowObj :  NSManagedObject  
{
}

@property (nonatomic, retain) NSString *rowDescription;
@property (nonatomic, retain) NSNumber *displayOrder;

Successivamente, abbiamo bisogno di avere una copia locale dei dati visualizzati nella vista tabella. Ho letto i commenti che hai fatto e non sono sicuro se stai usando FetchedResultsController o meno. Il mio suggerimento sarebbe di iniziare in modo semplice e utilizzare solo un normale tableviewcontroller in cui aggiorni i dati delle righe ogni volta che un utente modifica l'ordine di visualizzazione ... quindi salva l'ordine quando l'utente ha terminato le modifiche.

L'interfaccia per questo tableviewcontoller sarà simile a questa:

@interface MyTableViewController : UITableViewController {
    NSMutableArray *myTableViewData;
}

@property(nonatomic,retain) NSMutableArray *myTableViewData;

@end 

Successivamente, dobbiamo caricare i dati della vista tabella nel metodo viewWillAppear:

- (void)viewWillAppear:(BOOL)animated {
    myTableViewData = [helper getRowObjects]; // insert method call here to get the data
    self.navigationItem.leftBarButtonItem = [self editButtonItem];
}

Ci sono 2 cose che succedono qui ... (spiegherò più tardi l'editButtonItem) il primo è che abbiamo bisogno di ottenere i nostri dati da CoreData. Quando devo fare questo ho una sorta di aiuto (chiamalo come vuoi) oggetto fare il lavoro. Un tipico metodo di ricerca sarebbe simile a questo:

- (NSMutableArray*) getRowObjects{
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"RowObj" inManagedObjectContext:[self managedObjectContext]];
    [request setEntity:entity];

    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"displayOrder" ascending:YES];
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
    [request setSortDescriptors:sortDescriptors];
    [sortDescriptors release];
    [sortDescriptor release];

    NSError *error;
    NSMutableArray *mutableFetchResults = [[managedObjectContext executeFetchRequest:request error:&error] mutableCopy];
    if (mutableFetchResults == nil) {
        // Handle the error.
    }
    [request release];
    return mutableFetchResults;
}

Ora che hai i tuoi dati, puoi ora aspettare che l'utente modifichi la tabella. Questo è dove il [self editButtonItem] entra in gioco. Questa è una funzione incorporata che restituisce un elemento della barra che alterna il titolo e lo stato associato tra Modifica e Fine. Quando l'utente preme quel pulsante, invocherà il setEditing: animato: metodo:

Per aggiornare l'ordine di visualizzazione è necessario sovrascrivere il metodo setEditing nella classe UITableViewController. Dovrebbe assomigliare a qualcosa di simile a questo:

- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
    [super setEditing:editing animated:animated];
    [myTableView setEditing:editing animated:animated];
    if(!editing) {
        int i = 0;
        for(RowObj *row in myTableViewData) {
            row.displayOrder = [NSNumber numberWithInt:i++];
        }
        [helper saveManagedObjectContext]; // basically calls [managedObjectContext save:&error];
    }
}

Non dobbiamo fare nulla quando l'utente è in modalità di modifica ... vogliamo solo salvare una volta che hanno premuto il pulsante "Fatto". Quando un utente trascina una riga nella tabella, è possibile aggiornare l'ordine di visualizzazione sovrascrivendo i metodi canMoveRowAtIndexPath e moveRowAtIndexPath:

- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
    return true;
}

(void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath {

    RowObj *row = [myTableViewData objectAtIndex:sourceIndexPath.row];
    [myTableViewData removeObjectAtIndex:sourceIndexPath.row];
    [myTableViewData insertObject:row atIndex:destinationIndexPath.row];
}

Anche in questo caso, il motivo per cui non aggiorno il valore displayOrder è perché l'utente è ancora in modalità di modifica ... non sappiamo se l'utente ha terminato la modifica E potrebbero anche annullare ciò che hanno fatto non colpendo il Pulsante "Fatto".

MODIFICARE

Se si desidera eliminare una riga, è necessario eseguire l'override tableView: commitEditingStyle: forRowAtIndexPath e fare qualcosa come questo:

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        // Delete the managed object at the given index path.
        RowObj *row = [myTableViewData objectAtIndex:indexPath.row];
        [helper deleteRow:row];

        // Update the array and table view.
        [myTableViewData removeObjectAtIndex:indexPath.row];
        [myTableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:YES];
    }   
}

56