在我的应用程序中,我使用的是Core Data,存储类型为NSSQLiteStoreType。启动ios 8 sdk所有对象的关系都不从Core Data获取。任何人都可以解释ios 8中Core Data的不同之处,我该如何解决这个问题呢?
以下是我的DataService代码:
-(id)init{
self = [super init];
if (self){
coreDataHelpersForDispatchQueues = [NSMutableDictionary dictionary];
contextsForQispatchQueues = [NSMutableDictionary dictionary];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:[[NSBundle mainBundle] URLForResource:@"Name" withExtension:@"momd"]];
_persistentStoreCoordinator = [self createStoreCoordinatorWithDataModel:_managedObjectModel storeUrl:[NSURL fileURLWithPath:[self databaseLocationPath:@"Name.sqlite"]]];
self.coreDataHelper = self.coreDataHelperForCurrentDispatchQueue;
_managedObjectContext = self.coreDataHelper.moc;
_managedObjectContext.mergePolicy = NSOverwriteMergePolicy;
[self logCount];
}
return self;
}
-(void)logCount{
@synchronized(coreDataHelpersForDispatchQueues){
//NSLog(@"count|%d|",coreDataHelpersForDispatchQueues.count);
}
[self performSelector:@selector(logCount) withObject:nil afterDelay:1];
}
#pragma mark - currentCDH
-(CoreDataHelper*)coreDataHelperForCurrentDispatchQueue{
@synchronized(coreDataHelpersForDispatchQueues){
CoreDataHelper* helper = coreDataHelpersForDispatchQueues[dispatch_current_queue_id];
if (!helper){
helper = [[CoreDataHelper alloc] initWithContext:self.newManagedObjectContext];
helper.retainCounter = 1;
coreDataHelpersForDispatchQueues[dispatch_current_queue_id] = helper;
NSLog(@"new helper|%@| context|%@| queue|%s|",helper,helper.moc,dispatch_queue_get_label(dispatch_get_current_queue()));
}
return helper;
}
}
-(void)retainCoreDataHelper:(CoreDataHelper*)coreDataHelper_{
coreDataHelper_.retainCounter ++;
}
-(void)releaseCoreDataHelper:(CoreDataHelper *)coreDataHelper_ now:(BOOL)now_{
if (!coreDataHelper_ || (coreDataHelper_.moc == self.coreDataHelper.moc && !now_))
return;
coreDataHelper_.retainCounter --;
if (now_ || coreDataHelper_.retainCounter <= 0){
__block CoreDataHelper* helper = coreDataHelper_;
dispatch_block_t doit = ^{
NSLog(@"consuming helper|%@| context|%@| started",helper,helper.moc);
[[NSNotificationCenter defaultCenter] removeObserver:self name:NSManagedObjectContextDidSaveNotification object:helper.moc];
@synchronized(contextsForQispatchQueues){
NSNumber* keyToRemove = nil;
for (NSNumber* key in contextsForQispatchQueues) {
if (contextsForQispatchQueues[key] == helper.moc){
keyToRemove = key;
break;
}
}
if (keyToRemove)
[contextsForQispatchQueues removeObjectForKey:keyToRemove];
}
@synchronized(coreDataHelpersForDispatchQueues){
NSNumber* keyToRemove = nil;
for (NSNumber* key in coreDataHelpersForDispatchQueues) {
if (coreDataHelpersForDispatchQueues[key] == coreDataHelper_){
keyToRemove = key;
break;
}
}
if (keyToRemove)
[coreDataHelpersForDispatchQueues removeObjectForKey:keyToRemove];
}
NSLog(@"consuming helper|%@| context|%@| finished",helper,helper.moc);
};
if (now_){
NSLog(@"will consume helper|%@| context|%@| queue|%s| just now",helper,helper.moc,dispatch_queue_get_label(dispatch_get_current_queue()));
doit();
}else{
int64_t delayInSeconds = 5.0;
NSLog(@"will consume helper|%@| context|%@| queue|%s| in %lld seconds",helper,helper.moc,dispatch_queue_get_label(dispatch_get_current_queue()),delayInSeconds);
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_global_queue(0, 0), doit);
}
}
}
-(NSManagedObjectContext*)newManagedObjectContext{
NSManagedObjectContext* context = [[NSManagedObjectContext alloc] init];
context.persistentStoreCoordinator = self.persistentStoreCoordinator;
@synchronized(contextsForQispatchQueues){
contextsForQispatchQueues[dispatch_current_queue_id] = context;
}
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleContextDidSaveNotification:) name: NSManagedObjectContextDidSaveNotification object:context];
return context;
}
-(void)handleContextDidSaveNotification:(NSNotification *)notification {
@synchronized(contextsForQispatchQueues){
NSManagedObjectContext* savedContext = notification.object;
for (NSManagedObjectContext* context in contextsForQispatchQueues.allValues) {
if (context != savedContext)
[context mergeChangesFromContextDidSaveNotification:notification];
}
}
}
#pragma mark -
-(NSPersistentStoreCoordinator*)createStoreCoordinatorWithDataModel:(NSManagedObjectModel*)model storeUrl:(NSURL*)url{
NSError *error = nil;
NSPersistentStoreCoordinator* cordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
NSDictionary *options = @{
NSSQLitePragmasOption: @{@"journal_mode": @"OFF"}
};
if (![cordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:url options:options error:&error]){
[[NSFileManager defaultManager] removeItemAtURL:url error:nil];
NSLog(@"database was purged: %@",url.absoluteString);
NSError* error2 = nil;
if (![cordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:url options:options error:&error2]) {
NSLog(@"Unresolved error %@, %@", error2, [error2 userInfo]);
abort();
}
}
return cordinator;
}
-(NSManagedObjectContext*)createManagedObjectContextForStoreCoordinator:(NSPersistentStoreCoordinator*)coordinator{
NSManagedObjectContext* context = [[NSManagedObjectContext alloc] init];
context.persistentStoreCoordinator = coordinator;
// [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleContextSavedNotification:) name:NSManagedObjectContextDidSaveNotification object:context];
return context;
}
#pragma mark - Core Data stack
-(NSString*)databaseLocationPath:(NSString*)databaseName{
NSArray* documentDirectoryFolderLocation = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
return [[documentDirectoryFolderLocation objectAtIndex:0] stringByAppendingPathComponent:databaseName];
}
更新
以下是我获取结果的代码:
NSFetchRequest* oldInstructionsRequest = [[NSFetchRequest alloc] initWithEntityName:@"Instruction"];
oldInstructionsRequest.predicate = [NSPredicate predicateWithFormat:@"isFromList == NO && isForUpload == NO"];
oldInstructions = [app.dataService.managedObjectContextCopy executeFetchRequest:oldInstructionsRequest error:nil];
<Instruction: 0x190fae40> (entity: Instruction; id: 0x190fa7b0 <x-coredata://BDC5225D-BD51-412B-A247-C0A66947EA74/Instruction/p1> ; data: {
author = Public;
color = "";
created = "2014-02-28 10:21:50 +0000";
estimation = 0;
evaluation = nil;
favourite = 0;
id = "100b1974-0cdd-4d94-a34f-caf3e2c0cc08";
imageId = 1955;
isForUpdate = 0;
isForUpload = 0;
isFromList = 1;
isNew = 0;
isRemoved = 0;
modified = "2014-04-18 16:33:55 +0000";
name = "Types of steps";
state = 4;
steps = "<relationship fault: 0x17f45ab0 'steps'>";
}),
答案 0 :(得分:1)
您的核心数据并发方法(使用调度队列)并不能保证能够正常工作。您只能从单个线程访问NSManagedObjectContext
中的对象,但可以在不同的线程上执行在调度队列上调度的块。
使用performBlock:
中的performBlockAndWait:
或NSManagedObjectContext
方法。如果你这样做,你根本不需要@synchronized
个陈述。