Вопросы: Как я освободить память, используемую NSManagedObjectContext (я думаю), когда число записей, которые будут вставлены в Core Data непредсказуемы, так что память может эффективно использоваться?Чрезвычайно Массивный и Continuous Импорт в Core Data эффективно
Вот мой случай: У меня есть Bluetooth устройство, которое непрерывно посылать двенадцать комплектов целого на устройство IOS на каждые 0,00125 секунд (минимальный интервал, максимальный случай будет 0.002 секунд), я должен тогда магазин эти целые числа в CoreData с меткой времени.
Объекты данных и ассоциации:
Когда начало процесса, заголовок записи (NSManagedObject) создается в качестве ключа для извлечения партии полученных данных от устройства Bluetooth. Объект сохраняется как сильное свойство в течение всего периода приема данных и будет удаляться из свойства (возможно, установленного нуля), когда процесс завершится.
Дизайн NSManagedObjectContext:
Все три ManagedObjectContext являются одноплодной объект, хранящийся в AppDelegate
Код для создания ManagedObjectContext перечислены ниже:
- (NSManagedObjectContext *)masterManagedObjectContext {
// Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.)
if (_masterManagedObjectContext != nil) {
return _masterManagedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (!coordinator) {
return nil;
}
_masterManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[_masterManagedObjectContext setPersistentStoreCoordinator:coordinator];
[_masterManagedObjectContext setUndoManager:nil];
return _masterManagedObjectContext;
}
-(NSManagedObjectContext*) backgroundManagedObjectContext{
if(_backgroundManagedObjectContext != nil){
return _backgroundManagedObjectContext;
}
_backgroundManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSConfinementConcurrencyType];
[_backgroundManagedObjectContext setUndoManager:nil];
[_backgroundManagedObjectContext setParentContext:[self masterManagedObjectContext]];
return _backgroundManagedObjectContext;
}
-(NSManagedObjectContext*) mainManagedObjectContext{
if(_mainManagedObjectContext !=nil){
return _mainManagedObjectContext;
}
_mainManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[_mainManagedObjectContext setUndoManager:nil];
[_mainManagedObjectContext setParentContext:[self masterManagedObjectContext]];
return _mainManagedObjectContext;
}
Импорт обрабатывается в backgroundManagedObjectContext. Заголовок создается и сохраняется с помощью код ниже:
_header = [NSEntityDescription insertNewObjectForEntityForName:@"Header" inManagedObjectContext:_backgroundManagedObjectContext];
_header.startTime = [NSDate date];
NSError *error;
BOOL success = [_backgroundManagedObjectContext save:&error];
Полученные данные создаются и хранятся с помощью ниже код, когда Bluetooth устройства уволила метод:
@autoreleasepool {
ReceivedData* data = [NSEntityDescription insertNewObjectForEntityForName:@"ReceivedData" inManagedObjectContext:_backgroundManagedObjectContext];
//Data is set here
[_header addFk_header_many_dataObject:data];
currentCount ++;
if(currentCount >=1000){
currentCount = 0;
NSError *error;
BOOL success = [_backgroundManagedObjectContext save:&error];
}
}
полученные данные будут сохранены в managedObjectContext на 1000 полученных данных.
Однажды, если я остановлю процесс, потребляемая память удваивается и длится до тех пор, пока я полностью не закончу приложение.
Код для обработки конца процесса приведена ниже:
_header.endTime = [NSDate date];
_header = nil;
NSError *error;
BOOL success = [_backgroundManagedObjectContext save:&error];
[_masterManagedObjectContext performBlock:^{
NSError* mastererror;
BOOL mastersuccess = [_masterManagedObjectContext save:&mastererror];
}];
Выпуск: Как упомянуто Core Data Performance by Apple, с использованием метода сброса NSManagedObjectContext будут удалены все управляемые объекты, связанные с контекстом и " начните сначала ", как если бы вы только что создали его.
В моем понимании это означает, что я могу назвать этот метод только в конце всего процесса. Я попытался добавить функцию сброса сразу после сохранения _backgroundManagedObjectContext и _masterManagedObjectContext. Однако память остается неизменной.
Иллюстрация использования памяти Для случая данных принимается на каждые 0,002 секунды, 0.5Мб памяти увеличилась на 1000 записей сохраняется в backgroundManagedObjectContext. Таким образом, приложение будет потреблять около 150 МБ в течение 8 минут, а память увеличится до 320 МБ, когда процесс завершится в это время, и сохранит использование памяти около 220 МБ.
Вопросы: Как я освободить память, используемую NSManagedObjectContext (я думаю), когда число записей, вставленной в Core Data непредсказуемы, так что память может эффективно использоваться?
Извините за некоторые идиотские ошибки, поскольку я совершенно новый в iOS. Я попытался изо всех сил искать вокруг, прежде чем отправлять вопрос.
Ваша помощь приветствуется. спасибо.
Замечания Я пробовал вышеупомянутый случай не более 10 минут. Однако реализация должна была распространиться на случай более чем на 1 час процесса. Я до сих пор не знаю, как справиться с таким делом.
EDIT 1 изменил код для показа взаимосвязи ReceivedData и заголовка EDIT 2 обновленный код стандарта упомянутой @flexaddicted
Первое, что нужно сделать, это изменить способ работы вашего фонового MOC. В вашем случае он должен быть напрямую связан с persistentStoreCoordinator, а не с родительским мастером MOC, из-за ненужного использования памяти - для вас все данные должны идти непосредственно для хранения (sqlite), и в конечном итоге пользовательский интерфейс должен быть уведомлен об изменениях и потребностях в обновлении. В вашем коде, когда вы сохраняете фоновый MOC, все изменения необходимо переместить в master MOC и выполнить сброс на фоне. MOC сбросит (возможно) уже очистку MOC, и вся память по-прежнему используется мастером MOC. Вы не писали, на каком MOC вы вызываете сброс. –
Спасибо за ваш комментарий. Для первого комментария я попытался подключиться непосредственно к persistentStoreCoordinator раньше, но производительность не является удовлетворительной. Я также записал, какой MOC я назвал reset в части ** issue **. На самом деле, я сделал оба. –
Вы уже пробовали в вашем 'if (currentCount> = 1000) {' проверить, после вызова 'save', чтобы вызвать сброс контекста? –