title: Call to NSManagedObjectContext save doesn't return in certain situations
body: <p>I am relatively new to Core Data and am looking for some advice.
  My project: I have a few object here: 
   - SMCoreData which is largely the auto generated code around a CoreData
     project 
   - SMUploader which indexes assets in ALAssetLibrary, writes the results to SMCoreData, and has a queue mechanism to upload photos. 
   - SMUploaderViewController a UICollectionView and a few switches which show the progress of the queue. </p>
  
  <p>These classes work great for the most part. When a user launches the app, their Camera Roll is indexed and uploading begins. It will successfully upload 1000's of photos. </p>
  
  <p>The problem comes later when more is added to the upload queue. I'm observing changes to the ALAssetLibrary (say someone saves a photo using Safari). My app will receive the notification, queue the image, and try to upload it when the user flips the switch (same as earlier).</p>
  
  <p>This is where I am running into a quirk. I first grab the next object from core data, acuire the asset from a URL (core data object), then copy the file to my sandbox. I then go to update CoreData with the filesize and temporaryFilePath. However the call to [context save] never returns (however it has already worked great 1000s of times before). The processor is at 0% and it just sits there not returning. Sounds like a queue problem at first, however I am using background queues:</p>
  
  <p>MYCoreData is mainly the boilerplate code from a CoreData project. I moved it to a class to encapsulate it. I did change how the managedObjectContext is created though:</p>
  
  <pre><code>_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
  </code></pre>
  
  <p>MYUploader has two queues. One for indexing the asset library, and one for processing the upload queue. </p>
  
  <p>MYUploaderViewController has a registers a few calllback blocks with MYUploader so that UI updates can be rendered. These calls are always done from the main queue withing MYUploader. </p>
  
  <p>A little code:</p>
  
  <pre><code>-(void)uploadAsset:(SMUploadAsset*)uploadAsset completion:(SMUploaderBoolBlock)completion{
          // 1.) Dump asset to a temporary file to operate with
          // 1a) Update core data with temporaryFile, size, and md5
          // 2.) Create asset on our server
          // 2a) Update core data with s3URL
          // 3.) Upload file to s3RUL
          // 4.) Tell our server that the upload has completed
          // 5.) Update core data with uploaded and uploadedDate
          // 6.) Delete temporary file
          // 7.) Remove the uploadAsset from the queue
  
          NSLog(@"%s", __func__);
          if(uploadAsset.image){
              NSLog(@"........................................................... Uploading Image ................................................ ");
              uploadAsset.uploadQueueState = SMUploadAssetQueueStateInProgress;
              // 1.) Dump asset to a temporary file to operate with
              NSLog(@"Upload step 1. ");
              NSURL *assetURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@", uploadAsset.image.uri]];
              NSLog(@"--- UPLOAD 1.) Dumping file");
              [SMUploaderImageRipper bytesFromObject:assetURL completion:^(SMUploadProperties *uploadProperties) {
                  if(uploadProperties == nil){
                      NSLog(@"Upload step 1 FAILED");
                      uploadAsset.uploadQueueState = SMUploadAssetQueueStateFailed;
                      NSLog(@"****** UPLOAD ERROR: Failed to dump asset to temporary file");
                      completion(NO);
                      return;
                  }
                  NSLog(@"Upload step 1 complete");
  
                  // 1a) Update core data with temporaryFile, size, and md5
                  NSLog(@"Upload step 1a. Updating core data with temp file, size, and md5");
                  [self updateUploadAsset:uploadAsset uploadProperties:uploadProperties completion:^(BOOL success) {
                      if(success == NO){
                          NSLog(@"Upload step 1a FAILED");
                          uploadAsset.uploadQueueState = SMUploadAssetQueueStateFailed;
                          NSLog(@"****** UPLOAD ERROR: Failed to add temporaryFile, size, and md5 to CoreData");
                          completion(NO);
                          return;
                      }
                      NSLog(@"Upload step 1a complete");
      ....
  </code></pre>
  
  <p>And then the method that updates CoreData object:</p>
  
  <pre><code>-(void)updateUploadAsset:(SMUploadAsset*)uploadAsset
          uploadProperties:(SMUploadProperties*)uploadProperties
                completion:(SMUploaderBoolBlock)completion{
  
          SMCoreData *coreData = [SMCoreData sharedInstance];
          NSManagedObjectContext *context = [coreData managedObjectContext];
          uploadAsset.md5 = uploadProperties.hash;
          uploadAsset.temporaryFile = uploadProperties.temporaryFile;
          uploadAsset.size = uploadProperties.size;
          NSError *cdError;
          // THIS CALL NEVER RETURNS
          if (![context save:&amp;cdError]) {
              NSLog(@"Whoops, couldn't save: %@", [cdError localizedDescription]);
              completion(NO);
          }
          completion(YES);
  }
  </code></pre>
  
  <p>I am happy to post more code or answer questions as I am quite stuck. </p>
  
  <p>UPDATE: It seems to me that it's the ALAssetLibarary observer that's causing this problem somehow. Here is what I am doing for the notification. I've tried using the main queue as well as a different background queue I have, but always this is what gets CoreData into the funky state. If I comment this out, then run the app as described above (go to safari, save an image, return) but instead of receiving this notification, I just press a button which calls this same code (enqueueCameraRollWithCompletion), everthing works great. </p>
  
  <p>What could be the solution here? I would really like to keep this feature in.</p>
  
  <p>[[NSNotificationCenter defaultCenter] addObserverForName:ALAssetsLibraryChangedNotification
                                                    object:nil
                                                     queue:[NSOperationQueue mainQueue]
                                                usingBlock:^(NSNotification *note) {
                                                    dispatch_async(self.processingQueue, ^{
                                                        [self enqueueCameraRollWithCompletion:^(BOOL success) {
                                                        }];
                                                    });
                                                }];</p>
  
  <p>EDIT: Requested code update using performBlockAndWait</p>
  
  <pre><code>-(void)updateUploadAsset:(SMUploadAsset*)uploadAsset
          uploadProperties:(SMUploadProperties*)uploadProperties
                completion:(SMUploaderBoolBlock)completion{
  
      SMCoreData *coreData = [SMCoreData sharedInstance];
      NSManagedObjectContext *context = [coreData managedObjectContext];
  
      [context performBlockAndWait:^{
          uploadAsset.md5 = uploadProperties.hash;
          uploadAsset.temporaryFile = uploadProperties.temporaryFile;
          uploadAsset.size = uploadProperties.size;
  
          if ([coreData saveContext]){
              completion(YES);
          }
          else{
              completion(NO);
          }
  
      }];
  }
  </code></pre>