2014-10-13 1 views
0

Шаг 1: Я открыть документКак заставить данные ядра освободить память после удаления объекта?

NSFileManager *fileManager = [NSFileManager defaultManager]; 
NSURL *documentDirectory = [[fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] firstObject]; 
NSString *documentName = @"MyDocument"; 
NSURL *url = [documentDirectory URLByAppendingPathComponent:documentName]; 
document = [[UIManagedDocument alloc] initWithFileURL:url]; 
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:url.path]; 
if (fileExists) { 
    [document openWithCompletionHandler:^(BOOL success) {[self documentOpened:success];}]; 

}else{ 
    [document saveToURL:url forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success){[self documentOpened:success];}]; 
} 

...

-(void)documentOpened:(BOOL)success 
{ 
    NSLog(@"Document opened"); 
    if (success) 
    { 
     if (self.document.documentState == UIDocumentStateNormal) 
     { 
      self.managedObjectContext = document.managedObjectContext; 
      [self.managedObjectContext setUndoManager:nil]; 
      // [self loadGames]; 
     } 
    }else 
    { 
     NSLog(@"Fail to open file"); 
    } 
} 

шаг 2: Я Забрать объект

+(Game*) gameWithDate:(NSDate*)date 
      inContext:(NSManagedObjectContext*)context 
{ 
    Game* res; 
    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Game"]; 
    request.predicate = [NSPredicate predicateWithFormat:@"date == %@", date]; 
    NSError *error; 
    NSArray *matches = [context executeFetchRequest:request error:&error  ]; 
    if(!matches || error || [matches count] > 1) 
    { 
     NSLog(@"Error: NO Game in DB"); 
    }else 
    { 
     if ([matches count]) 
     { 
      res = [matches firstObject]; 
      NSLog(@"Fetching existing game"); 
     }else 
     { 
      NSLog(@"Creating a game"); 
     } 

    } 
    return res; 
} 

шаг 3: Я удалить объект:

Game *g = [Game gameWithDate:lastDate inContext:managedObjectContext]; 
[managedObjectContext deleteObject:g]; 
g = nil; 

Игра объектов около 20 [Мбайт]. После выполнения шага 3 я отметил, что память, выделенная на шаге 2 (по данным ядра), не была освобождена после шага 3. Если я выполняю шаги 2 и 3 в цикле, память продолжает получать выделение, но никогда не будет выпущена.

Я читал here, что это может быть менеджер отмены, сохраняющий эту память, поэтому я закрыл ее (на шаге 1), но это не помогло. Я пробовал:

[managedObjectContext refreshObject:g mergeChanges:NO]; 

или:

[managedObjectContext reset]; 

сразу после шага 3. Память был освобождаться, но объект не удален.

Я также попытался:

[managedObjectContext save:nil]; 

сразу после шага 3. Память не получил перераспределена.

Есть ли способ заставить данные ядра удалять память после удаления? И вообще, есть ли способ заставить Core Data сохранить эти тяжелые объекты как можно меньше?

ответ

0

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

Обе эти операции «забудут» тот факт, что вы удалили объект, поскольку это изменение происходит только в памяти.

Необходимо сохранить контекст после удаления.

+0

Я пробовал, но это не помогло. Я редактировал вопрос. – Yony

+0

Действительно ли вы сохраняете контекст перед сбросом? –

+0

Обратите внимание, что я использую управляемый документ, который является уровнем абстракции над CoreData. отправка save: в мой managedObjectContext не влияет, потому что это детский контекст. Я расследую его теперь надеюсь опубликовать ответ в ближайшее время ... – Yony

0

Очевидно, что UIManagedDocument допускает автоматическое сохранение изменений и после этого отказаться от указателей игры (в результате чего IOS освободит память). UIManagedDocument автоматически сохраняет в своем собственном времени. Это время не включает вышеприведенный случай, так что память осталась. Обойти было заставить UIDocument, чтобы сохранить все изменения в постоянной памяти с помощью:

NSFileManager *fileManager = [NSFileManager defaultManager]; 
NSURL *documentDirectory = [[fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] firstObject]; 
NSString *documentName = @"MyDocument"; 
NSURL *url = [documentDirectory URLByAppendingPathComponent:documentName]; 
[document saveToURL:url forSaveOperation:UIDocumentSaveForOverwriting completionHandler:^(BOOL success) { 
    if (!success) { 
     NSLog(@"Failed in saveToURL"); 
    } 
}]; 

После этого, память освобождаться!