Search code examples
ioscore-datamagicalrecord

ios Magical Record save on UIApplicationWillTerminateNotification


I have app that stores system events to Core Data Database. To perform saving I use MagicalRecord.

So, in my logger class in init I have:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleDidFinishLaunchingNotification) name:UIApplicationDidFinishLaunchingNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleWillTerminateNotification) name:UIApplicationWillTerminateNotification object:nil];

In handle functions I store simple entity with text and timestamp property:

- (void)handleDidFinishLaunchingNotification
{
    [MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {
        DBMessage *dbMessage = [DBMessage createEntityInContext:localContext];
        dbMessage.text = @"Did finish launching";
        dbMessage.timestamp = [NSDate date];
    }];
}

- (void)handleWillTerminateNotification
{
    [MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {
        DBMessage *dbMessage = [DBMessage createEntityInContext:localContext];
        dbMessage.text = @"Will terminate";
        dbMessage.timestamp = [NSDate date];
    }];
}

When I open and close (without crash) app few times, in my DB I can see "Did finish launching" entries (more that one, so I'm sure app was closed, not only moved to BG), but none of "Will terminate".

I would be less surprised if the launching event were missed, because I could expect that init method will be called after notification is posted.

What I can do to store terminate events?


Solution

  • I have an answer:

    It looks like when application gets terminated, wont't let me to save in new background thread. But saving in current thread works fine. So all I had to do was change saving method to save in current thread, by calling saveWithBlockAndWait: instead of saveWithBlock:

    - (void)handleWillTerminateNotification
    {
        [MagicalRecord saveWithBlockAndWait:^(NSManagedObjectContext *localContext) {
            DBMessage *dbMessage = [DBMessage createEntityInContext:localContext];
            dbMessage.text = @"Will terminate";
            dbMessage.timestamp = [NSDate date];
        }];
    }
    

    Now events are succesfully saved on DB.