0

I am working on an IPhone application.

I am doing an asynchronous update from the server. When the update finishes downloading, I issue a NSNotification

[[NSNotificationCenter defaultCenter] postNotificationName:NOTIFICATION_DATA_RECEIVED object:self userInfo:@{ @"updateKey": updateKey }];

In my viewController I declared the observer

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateReceived:) name:NOTIFICATION_DATA_RECEIVED object:nil];

And the selector that will be performed when notification received:

- (void) updateReceived:(NSNotification *)notification
{
    [self performSelectorOnMainThread:@selector(updateData:) withObject:nil waitUntilDone:NO];
}

updateData need to be performed on the main thread because it changes the entities in the core data and it cannot be done on a different threat unless we use some specific libraries. I dont want to change that.

My problem:

updateData is taking a while and it is freezing the UI since it is on the main thread. I need to display a "Loading Data..." Overlay while this is done.

I have 2 methods in the view controller that will display the overlay : showLoadingOverlay and hideLoadingOverlay

I need to call showLoadingOverlay when the updateData is called and hideLoadingOverlay when it is done.

The problem is that since it is peformed on the main thread I dont know how to make the overlay appear while updating the data. I tried to show it directly before sending the notification and hide it at the end of the updateData method but it is not working.

Any help is greatly appreciated.

Thanks

Y2theZ
  • 10,162
  • 38
  • 131
  • 200
  • since you are performing a heavy process on the main thread , so it is blocking the app and the overlay is not being shown , so in this case you must perform the heavy process ie update data on background thread and add overlay method on main thread .hope it helps – Singh Feb 14 '13 at 08:38
  • hello, thanks for answering, but I need to do the data update on the main thread. I cannot change that. – Y2theZ Feb 14 '13 at 08:45
  • then you can perform the add overlay on the background thread as [self performSelectorInBackground:@selector() withObject:nil]; . hope this helps – Singh Feb 14 '13 at 08:53

2 Answers2

0

Maybe, just maybe, you are using animations that are also scheduled on main thread but after the updateData is executed. In that case try to be sure that animation starts before updateData is called. For instance, you could do something like:

- (void)updateReceived:(NSNotification*)notification {
    [self startAnimationOnComplete: ^{
        [self performSelectorOnMainThread:@selector(updateData:) withObject:nil waitUntilDone:NO];
    }]
} 
Darko Pavlovic
  • 218
  • 2
  • 6
0

I found a way to do it. I ended up using NSTimer to run the updateReceived method after 1 millisecond of showing the overlay.

- (void) updateReceived:(NSNotification *)notification
{
    [self showLoadingOverlay];
    [NSTimer scheduledTimerWithTimeInterval:0.001 target:self selector:@selector(updateDataOnMainThread:) userInfo:nil repeats:NO];
}

- (void) updateDataOnMainThread:(NSTimer *)timer
{
    [self performSelectorOnMainThread:@selector(updateData:) withObject:nil waitUntilDone:NO];
}
Y2theZ
  • 10,162
  • 38
  • 131
  • 200