将应用程序推送到后台时,NSManagedObjectContext 不会获取或保存对象
Posted
技术标签:
【中文标题】将应用程序推送到后台时,NSManagedObjectContext 不会获取或保存对象【英文标题】:NSManagedObjectContext doesnt fetch or save object when application is pushed to background 【发布时间】:2014-07-08 12:48:13 【问题描述】:在我的应用程序中,我有一个父子上下文。将对象保存到处理自身的核心数据是在 dispatch_async 中完成的。在前台一切正常,但是当应用程序被推送到后台时,获取请求和保存操作被暂停。我也在使用 NSOperationQueue 来排队我的操作。虽然在所有操作都可以正常工作的前台内存使用情况稳定,但当被推送到后台时,即使内存消耗量也会大幅增加,并且应用程序在内存压力下崩溃。
- (void) saveDocument:(ALEXDocument*)document forDownloaded:(BOOL)isDownloadCompleted
BOOL checkWithKillDocId = NO;
if(!document.tocId || [document.tocId isEqualToString:@""])
document.tocId = nil;
NSManagedObjectContext *context = [self getNewPrivateManagedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Document" inManagedObjectContext:context];
[request setEntity:entity];
NSPredicate *predicate;
if (![document.killDocId isEqual:[NSNull null]] && document.killDocId!= nil)
if(![document.killDocId isEqualToString:@"(null)"] && ![document.killDocId isEqualToString:@""])
predicate = [NSPredicate predicateWithFormat:@"killDocId = %@",document.killDocId];
checkWithKillDocId = YES;
else
predicate = [ NSPredicate predicateWithFormat:@"reference == %@ AND section = %d AND tocRelation.tocId = %@ ", document.reference,document.section,document.tocId];
checkWithKillDocId = NO;
else
predicate = [ NSPredicate predicateWithFormat:@"reference == %@ AND section = %d AND tocRelation.tocId = %@ ", document.reference,document.section,document.tocId];
checkWithKillDocId = NO;
[request setPredicate:predicate];
NSError *error;
Document *coreDataDoc = (Document*)[[context executeFetchRequest:request error:&error] lastObject];
NSLog(@"Document");
if (!coreDataDoc || coreDataDoc == nil)
if(checkWithKillDocId)
predicate = [ NSPredicate predicateWithFormat:@"reference == %@ AND section = %d AND tocRelation.tocId = %@ ", document.reference,document.section,document.tocId];
[request setPredicate:predicate];
coreDataDoc = (Document*)[[context executeFetchRequest:request error:&error] lastObject];
if (!coreDataDoc || coreDataDoc == nil)
coreDataDoc = [NSEntityDescription insertNewObjectForEntityForName:@"Document" inManagedObjectContext:context];
else
coreDataDoc = [NSEntityDescription insertNewObjectForEntityForName:@"Document" inManagedObjectContext:context];
coreDataDoc.anchorName = document.anchorName;
coreDataDoc.binary = document.binary;
coreDataDoc.contentSize = [NSNumber numberWithInt:document.contentSize];
coreDataDoc.copyright = document.copyright;
coreDataDoc.createdDate = document.date;
coreDataDoc.domain = document.domain;
coreDataDoc.fileName = document.fileName;
coreDataDoc.htmlContent = document.htmlContent;
coreDataDoc.mimeType = document.mimeType;
coreDataDoc.reference = document.reference;
coreDataDoc.section = [NSNumber numberWithInteger:document.section];
coreDataDoc.source = document.source;
coreDataDoc.title = document.title;
coreDataDoc.tocReference = document.tocReference;
coreDataDoc.nextReference = document.nextReference;
coreDataDoc.nextSection = [NSString stringWithFormat:@"%@",document.nextSection];
coreDataDoc.previousReference = document.previousReference;
coreDataDoc.previousSection = [NSString stringWithFormat:@"%@",document.previousSection];
coreDataDoc.downloadedDate = [NSDate date];
coreDataDoc.status = document.documentStatus;
coreDataDoc.killDocId = document.killDocId;
[self dbSaveInContext:context];
// context = nil;
// coreDataDoc = nil;
// [context reset];
// [context refreshObject:coreDataDoc mergeChanges:NO];
NSLog(@"Context");
【问题讨论】:
【参考方案1】:要在后台运行任何进程,您需要告诉 ios 您的应用将继续并完成任务。
UIBackgroundTaskIdentifier backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^
NSLog(@"Not running background tasks anymore.");
[[UIApplication sharedApplication] endBackgroundTask:backgroundTask];
backgroundTask = UIBackgroundTaskInvalid;
];
它可以让您在短时间内在后台运行任何任务。 (10 分钟到 5 秒)。
【讨论】:
感谢您的回答,但我面临的问题是上面定义的 NSManasgedObjectContext 在后台停止所有执行,而在前台正常工作 你在检查后台任务时间吗?可能会少于完成任务所需的时间。 [UIApplication sharedApplication].backgroundTimeRemaining.以上是关于将应用程序推送到后台时,NSManagedObjectContext 不会获取或保存对象的主要内容,如果未能解决你的问题,请参考以下文章
如何在 django 中运行后台任务,完成后,我可以将信息推送到前端。