这是我的情况: 我有一个蓝牙设备,每0.00125秒(最小间隔,最大情况将是0.002秒)会连续向iOS设备发送十二组整数,然后我应该将这些整数与时间戳一起存储到CoreData中。
数据对象和关联: 当流程开始时,创建一个头记录(NSManagedObject),作为从蓝牙设备检索接收到的数据批次的关键。在整个数据接收期间,该对象作为强属性保留,并在流程结束时从属性中删除(可能设置为nil)。
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:
_header = [NSEntityDescription insertNewObjectForEntityForName:@"Header" inManagedObjectContext:_backgroundManagedObjectContext];
_header.startTime = [NSDate date];
NSError *error;
BOOL success = [_backgroundManagedObjectContext save:&error];
当蓝牙设备触发该方法时,使用以下代码创建和存储接收到的数据:
@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];
}
}
接收到的数据将会按照每1000个数据存储到 managedObjectContext 中。
如果我停止这个进程,所占用的内存将会增加一倍,并且持续到我完全终止应用程序。
处理进程结束的代码如下:
_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 所述,使用 NSManagedObjectContext 的 reset 方法将删除与上下文相关的所有托管对象,重新开始就像您刚创建它一样。
据我理解,这意味着我只能在整个进程结束时调用此方法。我试过在 _backgroundManagedObjectContext 和 _masterManagedObjectContext 保存后添加重置功能。但是,内存仍然没有改变。
内存使用说明:
对于每0.002秒接收到的数据,将保存1000条记录到背景管理上下文中增加0.5MB内存。因此,应用程序在8分钟的处理时间内将消耗大约150 MB的内存,并且当进程在该时间终止时,内存将增加到320MB,并保持内存使用量为220MB左右。
问题:当要插入到 Core Data 中的记录数不可预见时,如何释放 NSManagedObjectContext(我猜测)使用的内存,以便有效地使用内存?
很抱歉,由于我很新手 iOS,可能会有一些错误。在发布问题之前,我已经尽力搜索了。
非常感谢您的帮助。
备注:
我在不超过10分钟的处理时间内尝试了上述情况。然而,这种实现应该已经扩展到超过1小时的处理时间。我仍然不知道如何处理这种情况。
编辑1: 修改了代码以显示ReceivedData和Header之间的关系。编辑2: 根据 @flexaddicted 提供的标准更新了代码。
if(currentCount >=1000){
检查内,在save
调用之后,调用上下文的重置? - Lorenzo BReceiveData
和Header
之间的关系? - Lorenzo B