2009-11-11 12 views
17

Próbuję zmienić sortowanie w NSFetchController w locie, przez jakiś segmentowany kontroli. Aby posortować rzecz typu A-> Z Z-> A.Zmiana sortowania w NSFetchedResultsController w locie

Co muszę zrobić, aby to zrobić? Obserwuję przykład Jeff Lamarche tu: Here

Czy muszę zrobić nowy NSFetchedResultsController a następnie ustawić go, czy mogę po prostu zrobić nowy NSFetchRequest i zrobić

fetchedResultController.fetchRequest = newFetchRequest 

i wtedy mój stół automatycznie aktualizacja?

Odpowiedz

31

Utknąłem z tym samym problemem i mogłem to naprawić poprzez ustawienie deskryptorów sortowania w FetchRequest FetchRequestController, następnie wykonanie pobierania (performFetch) iw końcu ponowne załadowanie danych w widoku tabeli.

NSArray *sortDescriptors = [NSArray arrayWithObject: sorter]; 
[[fetchedResultsController fetchRequest] setSortDescriptors:sortDescriptors]; 
NSError *error; 
if (![[self fetchedResultsController] performFetch:&error]) { 
     // Handle you error here 
} 
[sorter release]; 
[myTableView reloadData]; 

To był najłatwiejszy sposób dla mnie do czynienia ze zmianą sortowania w locie bez upuszczenie FRC czy jakikolwiek inny fantazyjny obsługę obiektu. Nie jestem pewien co do wpływu na wydajność i może to mieć wpływ, jeśli zestaw wierszy w tabeli jest ogromny.

+0

Użyłem twojego rozwiązania. Wygląda na to, że nie ma opóźnienia. Ale czy każdy organ wie, czy to zrobi fizyczne pobranie z bazy danych? – user523234

+1

Należy pamiętać, że zmiana instrukcji sortDescriptors na instancji fetchRequest z FRC ma jedną wadę. Podczas używania metody delegatów: kontroler: didChangeObject: atIndexPath: forChangeType: newIndexPath: 'FRC zgłasza obiekt jako" przeniesiony "zamiast" zaktualizowany ", gdy, jak dokumentuje,' zmieniony atrybut obiektu jest jednym z deskryptorów sortowania używanych w pobrać żądanie ". FRC odnotowuje te klawisze tylko w momencie ich utworzenia, więc kiedy później zmienisz sortsekrytoriów na inne keypaty, FRC nie weźmie ich pod uwagę i będzie raportować "aktualizacje" zamiast "ruchów" lub odwrotnie. Lepiej stwórz nowy FRC. – bteapot

2

fetchRequest jest właściwością tylko do odczytu. Linia kodu w Twoim poście nie będzie działać. Jeśli chcesz użyć innej prośby o pobranie, musisz wymienić kontroler na nowy NSFetchedResultsController. Twoja tabela nie zostanie automatycznie załadowana ponownie. Będziesz musiał wysłać mu wiadomość o numerze reloadData jakiś czas po tym, jak wymieniłeś numer NSFetchedResultsController.

+7

Mimo że nie można utworzyć zastąpić właściwości fetchRequest NSFetchedResultsController (jest tylko do odczytu), można zmienić właściwości fetchRequest i ponownie pobrać. To oszczędza ci konieczności odtworzenia NSFetchedResultsController. –

+0

Czy istnieje możliwość zmiany sectionNameKeyPath bez tworzenia nowego NSFetchedResultsController? – ComSubVie

+0

'sectionNameKeyPath' jest właściwością readonly, więc myślę, że musiałbyś utworzyć nowy' NSFetchedResultsController'. – Alex

8

Zamiast używać NSFetchedResultsController jako źródła danych widoku tabeli, utwórz NSArray, który ustawisz, gdy użytkownik zmieni kolejność sortowania za pomocą segmentowanej kontroli, bazując na zawartości tablicy na pobranych wynikach. Następnie posortuj według standardowego sortowania macierzy. Coś takiego:

- (IBAction)segmentChanged:(id)sender 
{ 
    // Determine which segment is selected and then set this 
    // variable accordingly 
    BOOL ascending = ([sender selectedSegmentIndex] == 0); 

    NSArray *allObjects = [fetchedResultsController fetchedObjects]; 

    NSSortDescriptor *sortNameDescriptor = 
         [[[NSSortDescriptor alloc] initWithKey:@"name" 
           ascending:ascending] autorelease]; 

    NSArray *sortDescriptors = [[[NSArray alloc] 
        initWithObjects:sortNameDescriptor, nil] autorelease]; 

    // items is a synthesized ivar that we use as the table view 
    // data source. 
    [self setItems:[allObjects sortedArrayUsingDescriptors:sortDescriptors]]; 

    // Tell the tableview to reload. 
    [itemsTableView reloadData];  
} 

Więc deskryptor sortowania Użyłem nazywany jest „nazwa”, ale można to zmienić na nazwę pola, które chcesz, aby posortować według pobranego w wynikach. Ponadto elementy, do których się odwołałem, będą Twoimi nowymi źródłami danych widoku tabeli. Delegaci widoku tabeli będą teraz wyglądać mniej więcej tak:

- (NSInteger)tableView:(UITableView*)tableView 
numberOfRowsInSection:(NSInteger)section 
{ 
    return [items count]; 
} 

- (UITableViewCell *)tableView:(UITableView *)tableView 
     cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    // Get your table cell by reuse identifier as usual and then grab one of 
    // your records based on the index path 
    // ... 

    MyManagedObject *object = [items objectAtIndex:[indexPath row]]; 

    // Set your cell label text or whatever you want 
    // with one of the managed object's fields. 
    // ... 

    return cell; 
} 

Nie jestem pewien, czy to najlepszy sposób, ale powinien zadziałać.

+0

Ta metoda działa bardzo dobrze. Dzięki Matt. – Dimitris

+1

Ryzyko bycia przedwczesnym optymalizatorem: czy przestałoby to być praktyczne po pewnej liczbie elementów? W przypadku indeksowania, DB będzie znacznie bardziej efektywny w sortowaniu. – TimCinel

+0

Jest to również bardzo przydatne, gdy trzeba posortować na właściwości przejściowej (czego NSFetchedResultsController nie zrobi). – RunLoop

3

Odpowiedź Andreasa Schaefera zadziałała. Sztuką jest ustawienie nowy parametr dla pobrać wniosek z tego, czy to jest ten kod:

[[fetchedResultsController fetchRequest] setSortDescriptors:sortDescriptors]; 

LUB

[[fetchedResultsController fetchRequest] setPredicate:predicate]; 

Przed skontaktowaniem się następująco:

if (![[self fetchedResultsController] performFetch:&error]) { 
     // Handle you error here 
} 

[self.tableView reloadData]; 

wydaje się, że po ustawieniu nowy parametr, niż NSFetchedResultsController, wykona nowe zapytanie o plik w oparciu o to, co ustawisz. Bez ustawienia nowego parametru, nie wykona ponownego pobrania i tylko wywołanie performFetch to nie zadziała ..

Mam nadzieję, że to pomoże komuś innemu ..

+1

Dzięki, zadziałało idealnie dla mnie. Przeważano .. – NSPratik

Powiązane problemy