Как реализовать переупорядочение записей CoreData?

Вы могли использовать некоторый LINQ для получения списка:

var types = from type in this.GetType().Assembly.GetTypes()
            where type is ISomeInterface
            select type;

, Но действительно, который более читаем?

64
задан Krunal 1 November 2017 в 14:20
поделиться

4 ответа

FetchedResultsController и его делегат не предназначены для использования при изменении пользовательской модели. См. справочный документ Apple . Ищите раздел User-Driven Updates (Пользовательские обновления). Так что если вы ищете какой-то волшебный, однострочный способ, то, к сожалению, его нет.

Что вам нужно сделать, так это сделать обновления в этом методе:

- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {
 userDrivenDataModelChange = YES;

 ...[UPDATE THE MODEL then SAVE CONTEXT]...

 userDrivenDataModelChange = NO;
}

а также предотвратить уведомления, чтобы сделать что-нибудь, так как изменения уже сделаны пользователем:

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
 if (userDrivenDataModelChange) return;
 ...
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
 if (userDrivenDataModelChange) return;
 ...
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
 if (userDrivenDataModelChange) return;
 ...
}

Я только что реализовал это в моем приложении to-do (Quickie) и оно работает нормально.

91
ответ дан 24 November 2019 в 15:50
поделиться

Попробуйте ознакомиться с руководством по Core Data для iPhone здесь . В одном из разделов рассказывается о сортировке (с использованием NSSortDescriptor).

Вы также можете найти страницу Основные сведения о данных , которая будет полезной.

-1
ответ дан 24 November 2019 в 15:50
поделиться

Я наконец отказался от FetchController в режиме редактирования, так как мне также нужно изменить порядок ячеек таблицы. Я бы хотел увидеть, как это работает. Вместо этого я сохранил изменяемый массив, являющийся текущим представлением таблицы, а также поддерживал согласованность атрибута CoreData orderItem.

NSUInteger fromRow = [fromIndexPath row]; 
NSUInteger toRow = [toIndexPath row]; 



 if (fromRow != toRow) {

    // array up to date
    id object = [[eventsArray objectAtIndex:fromRow] retain]; 
    [eventsArray removeObjectAtIndex:fromRow]; 
    [eventsArray insertObject:object atIndex:toRow]; 
    [object release]; 

    NSFetchRequest *fetchRequestFrom = [[NSFetchRequest alloc] init];
    NSEntityDescription *entityFrom = [NSEntityDescription entityForName:@"Lister" inManagedObjectContext:managedObjectContext];

    [fetchRequestFrom setEntity:entityFrom];

    NSPredicate *predicate; 
    if (fromRow < toRow) predicate = [NSPredicate predicateWithFormat:@"itemOrder >= %d AND itemOrder <= %d", fromRow, toRow];  
    else predicate = [NSPredicate predicateWithFormat:@"itemOrder <= %d AND itemOrder >= %d", fromRow, toRow];                          
    [fetchRequestFrom setPredicate:predicate];

    NSError *error;
    NSArray *fetchedObjectsFrom = [managedObjectContext executeFetchRequest:fetchRequestFrom error:&error];
    [fetchRequestFrom release]; 

    if (fetchedObjectsFrom != nil) { 
        for ( Lister* lister in fetchedObjectsFrom ) {

            if ([[lister itemOrder] integerValue] == fromRow) { // the item that moved
                NSNumber *orderNumber = [[NSNumber alloc] initWithInteger:toRow];               
                [lister setItemOrder:orderNumber];
                [orderNumber release];
            } else { 
                NSInteger orderNewInt;
                if (fromRow < toRow) { 
                    orderNewInt = [[lister itemOrder] integerValue] -1; 
                } else { 
                    orderNewInt = [[lister itemOrder] integerValue] +1; 
                }
                NSNumber *orderNumber = [[NSNumber alloc] initWithInteger:orderNewInt];
                [lister setItemOrder:orderNumber];
                [orderNumber release];
            }

        }

        NSError *error;
        if (![managedObjectContext save:&error]) {
            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            abort();  // Fail
        }           

    }                                   

}   

Если у кого-нибудь есть решение, использующее fetchController, опубликуйте его.

1
ответ дан 24 November 2019 в 15:50
поделиться

Поздний ответ: возможно, вы могли бы сохранить ключ сортировки в виде строки. Вставить запись между двумя существующими строками можно тривиально, добавив в строку дополнительный символ, например, вставив «AM» между строками «A» и «B». Повторный заказ не требуется. Похожая идея может быть реализована с помощью числа с плавающей запятой или некоторой простой битовой арифметики с 4-байтовым целым числом: вставьте строку со значением ключа сортировки, которое находится на полпути между соседними строками.

Могут возникнуть патологические случаи, когда строка слишком длинная, число с плавающей запятой слишком мало или в int больше нет места, но тогда вы могли бы просто изменить нумерацию объекта и начать все сначала. Сканирование и обновление всех ваших записей в редких случаях намного лучше, чем отказываться от каждого объекта каждый раз, когда пользователь меняет порядок.

Например, рассмотрим int32. Использование старших 3 байтов в качестве начального порядка дает вам почти 17 миллионов строк с возможностью вставки до 256 строк между любыми двумя строками. 2 байта позволяют вставить 65000 строк между любыми двумя строками перед повторным сканированием.

Вот псевдокод, который я имел в виду для увеличения на 2 байта и для вставки на 2 байта:

AppendRow:item
    item.sortKey = tail.sortKey + 0x10000

InsertRow:item betweenRow:a andNextRow:b
    item.sortKey = a.sortKey + (b.sortKey - a.sortKey) >> 1

Обычно вы вызываете AppendRow, в результате чего получаются строки с sortKeys 0x10000, 0x20000, 0x30000 и т. д. Иногда вам потребуется InsertRow,

8
ответ дан 24 November 2019 в 15:50
поделиться
Другие вопросы по тегам:

Похожие вопросы: