drewmccormack / ensembles

A synchronization framework for Core Data.
MIT License
1.63k stars 131 forks source link

Merge on terminate (Mac) never completes #139

Closed mwaterfall closed 10 years ago

mwaterfall commented 10 years ago

In the Ensembles book under "When to Trigger Merges" it describes how to merge on termination of the Mac app. I've implemented this but when you attempt to quit the app it hangs indefinitely. It appears that the merge completion block never gets called. Here's what I'm doing:

- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender {
    // Sync on quit
    dispatch_async(dispatch_get_main_queue(), ^{ // async to let method return
        [_ensemble mergeWithCompletion:^(NSError *error) {
            [sender replyToApplicationShouldTerminate:YES];
        }];
    });
    return NSTerminateLater;
}

Not sure if this is an issue with Ensembles or just our implementation, so I wanted to raise an issue on here to see if it's already tested your end.

Cheers!

drewmccormack commented 10 years ago

Not thoroughly tested no, though I will be testing this in my own app soon.

If it is reproducible for you, it would be great if you could try to locate why it is failing the callback.

I assume you are retaining the ensemble object, correct? Is it possible it is somehow being released before it is finished?

Drew

mwaterfall commented 10 years ago

Whoops, managed to delete my last comment instead of editing it! I previously said that the main thread was being blocked, but that wasn't true. It turns out it's just the call to startNextTask on the next run loop that's the issue. The method just seems never to be invoked. Strange!

mwaterfall commented 10 years ago

Replacing the performSelector:withObject:afterDelay with a GCD dispatch works fine:

dispatch_async(dispatch_get_main_queue(), ^{ [self startNextTask]; });

Perhaps it's running in to this issue: http://stackoverflow.com/a/16956988/106244

drewmccormack commented 10 years ago

I suspect what could be happening is that the main run loop, which is what performSelector: uses (I think), is not running anymore. I will look into using the dispatch option, and see if it introduces any other issues. Thanks!

Drew

On 06 May 2014, at 12:28, Michael Waterfall notifications@github.com wrote:

Replacing the performSelector:withObject:afterDelay with a GCD dispatch works fine:

dispatch_async(dispatch_get_main_queue(), ^{ [self startNextTask]; }); Perhaps it's running in to this issue: http://stackoverflow.com/a/16956988/106244

— Reply to this email directly or view it on GitHub.

drewmccormack commented 10 years ago

I've replaced the delayed-performs with dispatches. Passes tests, and seems to work fine. Pull master to get the changes. Thanks for locating the issue!