Я работаю над приложением, которое регулярно обрабатывает вставки, удаления и обновления по 100 КБ с помощью Core Data. Если он задыхается от вставок 5К, необходимо провести некоторую оптимизацию.
Во-первых, создайте некоторый подкласс NSOperation для обработки данных. Переопределите метод -main, чтобы выполнить обработку. Однако этот метод не гарантированно выполняется в основном потоке. Действительно, его цель - избежать выполнения дорогостоящего кода в главном потоке, который мог бы повлиять на работу пользователя, если он сильно зависнет. Таким образом, в методе -main вам нужно создать еще один контекст управляемого объекта, который является потомком контекста управляемого объекта вашего основного потока.
- (void)main
{
NSManagedObjectContext *ctx = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[ctx setPersistentStoreCoordinator:mainManagedObjectContext.persistentStoreCoordinator];
[ctx setUndoManager:nil];
// Do your insertions here!
NSError *error = nil;
[ctx save:&error];
}
Учитывая ваши обстоятельства, я не верю, что вам нужен менеджер по отмене. Наличие одного приведет к снижению производительности, потому что Core Data отслеживает ваши изменения.
Используйте ЭТОТ контекст, чтобы выполнить все ваши действия CRUD в методе -main, затем сохраните этот контекст управляемого объекта. Что бы ни владел контекстом управляемого объекта вашего основного потока, он должен зарегистрироваться, чтобы ответить на NSNotification с именем NSManagedObjectContextDidSaveNotification. Зарегистрируйтесь так:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mocDidSaveNotification:) name:NSManagedObjectContextDidSaveNotification object:nil];
Затем определите этот селектор:
- (void)mocDidSaveNotification:(NSNotification *)notification
{
NSManagedObjectContext *ctx = [notification object];
if (ctx == mainManagedObjectContext) return;
[mainManagedObjectContext mergeChangesFromContextDidSaveNotification:notification];
}
Когда все это объединится, это позволит вам выполнять длительные операции с фоновыми потоками, не блокируя поток пользовательского интерфейса. Существует несколько вариантов этой архитектуры, но центральная тема такова: обработка в потоке BG, объединение в основном потоке, обновление вашего пользовательского интерфейса. Некоторые другие вещи, которые нужно иметь в виду: (1) сохраняйте пул авто-релизов во время обработки и время от времени истощайте его, чтобы снизить потребление памяти. В нашем случае мы делаем это каждые 1000 объектов. Приспособьтесь к своим потребностям, но имейте в виду, что слив может быть дорогостоящим в зависимости от объема памяти, требуемого для объекта, поэтому вы не хотите делать это слишком часто. (2) постарайтесь сократить ваши данные до абсолютного минимума, необходимого для работы функционального приложения. Сокращая объем данных для анализа, вы сокращаете время, необходимое для их сохранения. (3) используя этот многопоточный подход, вы можете одновременно обрабатывать ваши данные. Поэтому создайте 3-4 экземпляра вашего подкласса NSOperation, каждый из которых обрабатывает только часть данных, чтобы они все выполнялись одновременно, что приводит к меньшему количеству реального времени, затрачиваемого на анализ набора данных.