如何在删除对象后导致核心数据释放内存?

时间:2014-10-13 06:21:47

标签: objective-c core-data memory nsmanagedobjectcontext

第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 [Mbyte]。 执行步骤3后,我注意到步骤2中分配的内存(通过核心数据)在步骤3之后没有释放。如果我在循环中执行步骤2和3,则内存将继续分配但从未释放。

我读到here它可能是撤销管理器保持这个存储器存活所以我关闭它(在步骤1中)但它没有帮助。 我试过了:

[managedObjectContext refreshObject:g mergeChanges:NO];

或:

[managedObjectContext reset];

在第3步之后。内存被取消分配,但对象没有被删除。

我也尝试过:

[managedObjectContext save:nil];

在第3步之后。记忆没有被解除分配。

有没有办法让核心数据在删除后释放内存? 一般来说,有没有办法让Core Data尽可能少地保留那些重物?

2 个答案:

答案 0 :(得分:0)

刷新对象从持久性存储重新加载。重置已从内存中删除所做的任何更改。

这两项操作都会忘记"您已删除该对象的事实,因为该更改仅在内存中。

删除后需要保存上下文。

答案 1 :(得分: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");
    }
}];

之后,内存被解除分配!

相关问题