Skip to content

Commit 6bf60c6

Browse files
committed
Attempting to solve this nested context problem. Dont do it for ios 5
1 parent fadfdb3 commit 6bf60c6

File tree

8 files changed

+135
-17
lines changed

8 files changed

+135
-17
lines changed

MagicalRecord/Categories/NSManagedObjectContext/NSManagedObjectContext+MagicalRecord.m

Lines changed: 56 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
static NSManagedObjectContext *rootSavingContext = nil;
1212
static NSManagedObjectContext *defaultManagedObjectContext_ = nil;
13+
static NSManagedObjectContext *backgroundWorkContext = nil;
1314

1415

1516
@interface NSManagedObjectContext (MagicalRecordInternal)
@@ -80,17 +81,64 @@ + (void) MR_initializeDefaultContextWithCoordinator:(NSPersistentStoreCoordinato
8081
{
8182
if (defaultManagedObjectContext_ == nil)
8283
{
83-
NSManagedObjectContext *rootContext = [self MR_contextWithStoreCoordinator:coordinator];
84-
85-
[self MR_setRootSavingContext:rootContext];
86-
87-
NSManagedObjectContext *defaultContext = [self MR_newMainQueueContext];
88-
[defaultContext setParentContext:rootSavingContext];
89-
90-
[self MR_setDefaultContext:defaultContext];
84+
if ([MagicalRecord isRunningiOS6]) {
85+
MRLog(@"Wohoo! Running iOS 6, using nested contexts!");
86+
NSManagedObjectContext *rootContext = [self MR_contextWithStoreCoordinator:coordinator];
87+
88+
[self MR_setRootSavingContext:rootContext];
89+
90+
NSManagedObjectContext *defaultContext = [self MR_newMainQueueContext];
91+
[defaultContext setParentContext:rootSavingContext];
92+
93+
[self MR_setDefaultContext:defaultContext];
94+
} else {
95+
MRLog(@"On iOS 5, nested contexts are trouble. Using parallel PSC's!");
96+
// We can't do nested contexts, so let's create a seperate psc and merge from there to main thread context
97+
98+
NSPersistentStoreCoordinator *backgroundCoordinator = [NSPersistentStoreCoordinator MR_coordinatorWithAutoMigratingSqliteStoreNamed:[MagicalRecord defaultStoreName]];
99+
NSManagedObjectContext *rootContext = [self MR_contextWithStoreCoordinator:backgroundCoordinator];
100+
[self MR_setRootSavingContext:rootContext];
101+
rootContext.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy;
102+
// Now set up the UIQueue
103+
NSManagedObjectContext *defaultContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
104+
defaultContext.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy;
105+
// Use the coordinator passed in
106+
[defaultContext setPersistentStoreCoordinator:coordinator];
107+
[self MR_setDefaultContext:defaultContext];
108+
109+
[self MR_makeContext:rootContext mergeChangesToContext:defaultContext];
110+
[self MR_makeContext:defaultContext mergeChangesToContext:rootContext];
111+
}
91112
}
92113
}
93114

115+
+ (void)MR_makeContext:(NSManagedObjectContext *)sourceContext mergeChangesToContext:(NSManagedObjectContext *)targetContext
116+
{
117+
[[NSNotificationCenter defaultCenter] addObserverForName:NSManagedObjectContextDidSaveNotification
118+
object:sourceContext
119+
queue:nil
120+
usingBlock:^(NSNotification *note) {
121+
[targetContext performBlock:^{
122+
[targetContext mergeChangesFromContextDidSaveNotification:note];
123+
}];
124+
}];
125+
}
126+
127+
+ (void)MR_makeContextObtainPermanentIDsBeforeSaving:(NSManagedObjectContext *)context
128+
{
129+
[[NSNotificationCenter defaultCenter] addObserverForName:NSManagedObjectContextWillSaveNotification
130+
object:context
131+
queue:nil
132+
usingBlock:^(NSNotification *note) {
133+
[context performBlockAndWait:^{
134+
NSArray *insertedObjects = [[context insertedObjects] allObjects];
135+
NSError *error;
136+
if (![context obtainPermanentIDsForObjects:insertedObjects error:&error]) {
137+
[MagicalRecord handleErrors:error];
138+
}
139+
}];
140+
}];
141+
}
94142
+ (void) MR_resetDefaultContext
95143
{
96144
void (^resetBlock)(void) = ^{

MagicalRecord/Categories/NSPersistentStoreCoordinator+MagicalRecord.m

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ + (NSDictionary *) MR_autoMigrationOptions;
122122
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
123123
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
124124
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption,
125+
@"journal_mode = WAL;", NSSQLitePragmasOption
125126
nil];
126127
return options;
127128
}

MagicalRecord/Core/MagicalRecord+Actions.m

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,19 +35,49 @@ @implementation MagicalRecord (Actions)
3535

3636
+ (void) saveInBackgroundUsingContext:(NSManagedObjectContext *)localContext block:(void (^)(NSManagedObjectContext *))block completion:(void(^)(void))completion errorHandler:(void(^)(NSError *))errorHandler;
3737
{
38-
dispatch_async(action_queue(), ^{
39-
block(localContext);
38+
39+
// dispatch_async(action_queue(), ^{
40+
// block(localContext);
41+
//
42+
// [localContext MR_saveInBackgroundErrorHandler:errorHandler completion:completion];
43+
// });
4044

41-
[localContext MR_saveInBackgroundErrorHandler:errorHandler completion:completion];
42-
});
45+
[localContext performBlock:^{
46+
block(localContext);
47+
[localContext MR_saveErrorHandler:nil];
48+
if (localContext.parentContext) {
49+
// If we're doing nested contexs, save parent
50+
[localContext.parentContext performBlock:^{
51+
[localContext.parentContext MR_saveErrorHandler:nil];
52+
if (completion) {
53+
dispatch_async(dispatch_get_main_queue(), ^{
54+
completion();
55+
});
56+
}
57+
}];
58+
} else {
59+
// we're not, so just call completion;
60+
if (completion) {
61+
dispatch_async(dispatch_get_main_queue(), ^{
62+
completion();
63+
});
64+
}
65+
}
66+
}];
67+
4368
}
4469

4570
+ (void) saveInBackgroundWithBlock:(void (^)(NSManagedObjectContext *))block completion:(void (^)(void))completion errorHandler:(void (^)(NSError *))errorHandler;
4671
{
47-
NSManagedObjectContext *mainContext = [NSManagedObjectContext MR_defaultContext];
48-
NSManagedObjectContext *localContext = [NSManagedObjectContext MR_contextWithParent:mainContext];
49-
50-
[self saveInBackgroundUsingContext:localContext block:block completion:completion errorHandler:errorHandler];
72+
NSManagedObjectContext *savingContext;
73+
if ([MagicalRecord isRunningiOS6]) {
74+
NSManagedObjectContext *mainContext = [NSManagedObjectContext MR_rootSavingContext];
75+
savingContext = [NSManagedObjectContext MR_contextWithParent:mainContext];
76+
} else {
77+
savingContext = [NSManagedObjectContext MR_rootSavingContext];
78+
}
79+
80+
[self saveInBackgroundUsingContext:savingContext block:block completion:completion errorHandler:errorHandler];
5181
}
5282

5383
+ (void) saveInBackgroundUsingCurrentContextWithBlock:(void (^)(NSManagedObjectContext *))block completion:(void (^)(void))completion errorHandler:(void (^)(NSError *))errorHandler;

MagicalRecord/Core/MagicalRecord+Options.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,6 @@
2828
This is extremely useful during development where every model change could potentially require a delete/reinstall of the app.
2929
*/
3030
+ (BOOL) shouldDeleteStoreOnModelMismatch;
31-
31+
+ (BOOL)isRunningiOS6;
3232

3333
@end

MagicalRecord/Core/MagicalRecord+Options.m

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,9 @@ + (void) setShouldDeleteStoreOnModelMismatch:(BOOL)shouldDeleteStoreOnModelMisma
4646
shouldDeleteStoreOnModelMismatch_ = shouldDeleteStoreOnModelMismatch;
4747
}
4848

49+
+ (BOOL)isRunningiOS6
50+
{
51+
return NSClassFromString(@"UUID") != nil;
52+
}
53+
4954
@end
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
//
2+
// MagicalRecordSaveStrategy.h
3+
// Magical Record
4+
//
5+
// Created by Stephen J Vanterpool on 8/30/12.
6+
// Copyright (c) 2012 Magical Panda Software LLC. All rights reserved.
7+
//
8+
9+
#import <Foundation/Foundation.h>
10+
11+
@interface MagicalRecordSaveStrategy : NSObject
12+
13+
@end
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
//
2+
// MagicalRecordSaveStrategy.m
3+
// Magical Record
4+
//
5+
// Created by Stephen J Vanterpool on 8/30/12.
6+
// Copyright (c) 2012 Magical Panda Software LLC. All rights reserved.
7+
//
8+
9+
#import "MagicalRecordSaveStrategy.h"
10+
11+
@implementation MagicalRecordSaveStrategy
12+
13+
@end

Project Files/Magical Record.xcodeproj/project.pbxproj

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
objects = {
88

99
/* Begin PBXBuildFile section */
10+
4B0454B415F00C5A00BAD2C6 /* MagicalRecordSaveStrategy.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B0454B315F00C5A00BAD2C6 /* MagicalRecordSaveStrategy.m */; };
11+
4B0454B515F00C5A00BAD2C6 /* MagicalRecordSaveStrategy.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B0454B315F00C5A00BAD2C6 /* MagicalRecordSaveStrategy.m */; };
1012
C70B6E7113D0F62500709450 /* NSPersisentStoreHelperTests.m in Sources */ = {isa = PBXBuildFile; fileRef = C70B6E7013D0F62500709450 /* NSPersisentStoreHelperTests.m */; };
1113
C70B6E7413D0F64000709450 /* NSPersistentStoreCoordinatorHelperTests.m in Sources */ = {isa = PBXBuildFile; fileRef = C70B6E7313D0F64000709450 /* NSPersistentStoreCoordinatorHelperTests.m */; };
1214
C70B6E7713D0F66000709450 /* NSManagedObjectModelHelperTests.m in Sources */ = {isa = PBXBuildFile; fileRef = C70B6E7613D0F66000709450 /* NSManagedObjectModelHelperTests.m */; };
@@ -234,6 +236,8 @@
234236
/* End PBXCopyFilesBuildPhase section */
235237

236238
/* Begin PBXFileReference section */
239+
4B0454B215F00C5A00BAD2C6 /* MagicalRecordSaveStrategy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MagicalRecordSaveStrategy.h; sourceTree = "<group>"; };
240+
4B0454B315F00C5A00BAD2C6 /* MagicalRecordSaveStrategy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MagicalRecordSaveStrategy.m; sourceTree = "<group>"; };
237241
C70B6E6F13D0F62500709450 /* NSPersisentStoreHelperTests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NSPersisentStoreHelperTests.h; path = "Unit Tests/NSPersisentStoreHelperTests.h"; sourceTree = "<group>"; };
238242
C70B6E7013D0F62500709450 /* NSPersisentStoreHelperTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NSPersisentStoreHelperTests.m; path = "Unit Tests/NSPersisentStoreHelperTests.m"; sourceTree = "<group>"; };
239243
C70B6E7213D0F64000709450 /* NSPersistentStoreCoordinatorHelperTests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NSPersistentStoreCoordinatorHelperTests.h; path = "Unit Tests/NSPersistentStoreCoordinatorHelperTests.h"; sourceTree = "<group>"; };
@@ -789,6 +793,8 @@
789793
C7DD72CF150F832A00216827 /* MagicalRecord+ShorthandSupport.h */,
790794
C7DD72D0150F832A00216827 /* MagicalRecord+ShorthandSupport.m */,
791795
C7DD72D3150F832A00216827 /* MagicalRecordShorthand.h */,
796+
4B0454B215F00C5A00BAD2C6 /* MagicalRecordSaveStrategy.h */,
797+
4B0454B315F00C5A00BAD2C6 /* MagicalRecordSaveStrategy.m */,
792798
);
793799
path = Core;
794800
sourceTree = "<group>";
@@ -1042,6 +1048,7 @@
10421048
C7DD7303150F832B00216827 /* MagicalRecord+Setup.m in Sources */,
10431049
C7DD7305150F832B00216827 /* MagicalRecord+ShorthandSupport.m in Sources */,
10441050
C7DD7307150F832B00216827 /* MagicalRecord.m in Sources */,
1051+
4B0454B415F00C5A00BAD2C6 /* MagicalRecordSaveStrategy.m in Sources */,
10451052
);
10461053
runOnlyForDeploymentPostprocessing = 0;
10471054
};
@@ -1116,6 +1123,7 @@
11161123
C7DD7304150F832B00216827 /* MagicalRecord+Setup.m in Sources */,
11171124
C7DD7306150F832B00216827 /* MagicalRecord+ShorthandSupport.m in Sources */,
11181125
C7DD7308150F832B00216827 /* MagicalRecord.m in Sources */,
1126+
4B0454B515F00C5A00BAD2C6 /* MagicalRecordSaveStrategy.m in Sources */,
11191127
);
11201128
runOnlyForDeploymentPostprocessing = 0;
11211129
};

0 commit comments

Comments
 (0)