diff --git a/MagicalRecord/Categories/NSManagedObjectContext/NSManagedObjectContext+MagicalSaves.m b/MagicalRecord/Categories/NSManagedObjectContext/NSManagedObjectContext+MagicalSaves.m index c7ea37a..bd4c98a 100644 --- a/MagicalRecord/Categories/NSManagedObjectContext/NSManagedObjectContext+MagicalSaves.m +++ b/MagicalRecord/Categories/NSManagedObjectContext/NSManagedObjectContext+MagicalSaves.m @@ -43,7 +43,9 @@ if (completion) { - completion(NO, nil); + dispatch_async(dispatch_get_main_queue(), ^{ + completion(NO, nil); + }); } return; @@ -72,7 +74,9 @@ [MagicalRecord handleErrors:error]; if (completion) { - completion(saved, error); + dispatch_async(dispatch_get_main_queue(), ^{ + completion(saved, error); + }); } } else { // If we're the default context, save to disk too (the user expects it to persist) @@ -86,8 +90,11 @@ // If we are not the default context (And therefore need to save the root context, do the completion action if one was specified else { MRLog(@"→ Finished saving: %@", [self MR_description]); + if (completion) { - completion(saved, error); + dispatch_async(dispatch_get_main_queue(), ^{ + completion(saved, error); + }); } } } diff --git a/Project Files/Mac Unit Tests/MagicalRecord+ActionsSpec.m b/Project Files/Mac Unit Tests/MagicalRecord+ActionsSpec.m index e7e675c..b0451c8 100644 --- a/Project Files/Mac Unit Tests/MagicalRecord+ActionsSpec.m +++ b/Project Files/Mac Unit Tests/MagicalRecord+ActionsSpec.m @@ -40,14 +40,16 @@ describe(@"MagicalRecord", ^{ }); context(@"asynchronous save action", ^{ - it(@"should call completion block", ^{ + it(@"should call completion block on the main thread", ^{ __block BOOL completionBlockCalled = NO; + __block BOOL completionBlockIsOnMainThread = NO; [MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) { [SingleEntityWithNoRelationships MR_createInContext:localContext]; } completion:^(BOOL success, NSError *error) { - // Ignore the success state — we only care that this block is executed + // Ignore the success state — we only care that this block is executed on the main thread completionBlockCalled = YES; + completionBlockIsOnMainThread = [NSThread isMainThread]; }]; [[expectFutureValue(@(completionBlockCalled)) shouldEventually] beTrue]; @@ -100,14 +102,16 @@ describe(@"MagicalRecord", ^{ }); context(@"running asynchronously", ^{ - it(@"should call completion block", ^{ + it(@"should call completion block on the main thread", ^{ __block BOOL completionBlockCalled = NO; - + __block BOOL completionBlockIsOnMainThread = NO; + [MagicalRecord saveUsingCurrentThreadContextWithBlock:^(NSManagedObjectContext *localContext) { [SingleEntityWithNoRelationships MR_createInContext:localContext]; } completion:^(BOOL success, NSError *error) { - // Ignore the success state — we only care that this block is executed + // Ignore the success state — we only care that this block is executed on the main thread completionBlockCalled = YES; + completionBlockIsOnMainThread = [NSThread isMainThread]; }]; [[expectFutureValue(@(completionBlockCalled)) shouldEventually] beTrue]; diff --git a/Project Files/Mac Unit Tests/NSManagedObjectContext+MagicalSavesSpec.m b/Project Files/Mac Unit Tests/NSManagedObjectContext+MagicalSavesSpec.m index fee20f9..f0ecca5 100644 --- a/Project Files/Mac Unit Tests/NSManagedObjectContext+MagicalSavesSpec.m +++ b/Project Files/Mac Unit Tests/NSManagedObjectContext+MagicalSavesSpec.m @@ -53,13 +53,15 @@ describe(@"NSManagedObjectContext+MagicalSaves", ^{ }); context(@"asynchronously", ^{ - it(@"should call completion block", ^{ + it(@"and should call the completion block on the main thread", ^{ __block BOOL completionBlockCalled = NO; - + __block BOOL completionBlockIsOnMainThread = NO; + [SingleEntityWithNoRelationships MR_createInContext:managedObjectContext]; [managedObjectContext MR_saveOnlySelfWithCompletion:^(BOOL success, NSError *error) { completionBlockCalled = YES; + completionBlockIsOnMainThread = [NSThread isMainThread]; }]; [[expectFutureValue(@(completionBlockCalled)) shouldEventually] beTrue]; @@ -123,15 +125,17 @@ describe(@"NSManagedObjectContext+MagicalSaves", ^{ }); context(@"asynchronously", ^{ - it(@"and should call completion block", ^{ + it(@"and should call the completion block on the main thread", ^{ __block BOOL completionBlockCalled = NO; - + __block BOOL completionBlockIsOnMainThread = NO; + [SingleEntityWithNoRelationships MR_createInContext:managedObjectContext]; [[@([managedObjectContext hasChanges]) should] beTrue]; [managedObjectContext MR_saveToPersistentStoreWithCompletion:^(BOOL success, NSError *error) { completionBlockCalled = YES; + completionBlockIsOnMainThread = [NSThread isMainThread]; }]; [[expectFutureValue(@(completionBlockCalled)) shouldEventually] beTrue]; @@ -290,7 +294,7 @@ describe(@"NSManagedObjectContext+MagicalSaves", ^{ errorHandlerCalled = YES; }]; - [[@(errorHandlerCalled) should] beTrue]; + [[expectFutureValue(@(errorHandlerCalled)) shouldEventually] beTrue]; }); it(@"should save", ^{ @@ -441,7 +445,7 @@ describe(@"NSManagedObjectContext+MagicalSaves", ^{ errorHandlerCalled = YES; }]; - [[@(errorHandlerCalled) should] beTrue]; + [[expectFutureValue(@(errorHandlerCalled)) shouldEventually] beTrue]; }); it(@"should save", ^{