0

My application performs a series of processing methods once a day or when a local notification is received to perform the series of tasks and is working as expected.

I tried adding an ActivityIndicator to a view that begins animating when a notification sent from the AppDelegate to perform the tasks is received. However all that happens is the screen darkens and none of the processing is done and the activity indicator doesn't appear. The indicator and subview that darkens the screen is used elsewhere in the app and is definitely working. I think it must be something to do with the notifications causing the app to hang and not proceed to call any of the other methods so it never completes.

This is the notification in the app delegate which is called just before the daily processing methods are called to start the activity indicator in a view controller, and the second one notifies the view controller to remove the subviews.

This method is in the AppDelegate;

- (void)GoForRankingAndSMProcessing{

    [[NSNotificationCenter defaultCenter] postNotificationName:@"ranking" object:self];

    RankingAndSMProcess *process = [RankingAndSMProcess alloc];

    [process DoRankingAndSocialMediaProcessing];

    [process release];

    [[NSNotificationCenter defaultCenter] postNotificationName:@"rankingDone" object:self];


}

Which is picked up in another view, with the notifications setup in viewDidLoad.

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(workingWhileRanking:) name:@"ranking" object:nil];

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(workingFinishedRanking:) name:@"rankingDone" object:nil];

And those call these methods in that view.

-(void)workingWhileRanking:(NSNotification *) notification{

    loading = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)]; 

    loading.opaque = NO;
    loading.backgroundColor = [UIColor colorWithWhite:0.0f alpha:0.6f];

    indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
    [indicator setHidesWhenStopped:YES];
    indicator.center = self.view.center;

    [indicator startAnimating];
    [self.view addSubview:loading];
    [self.view addSubview:indicator];

}

-(void)workingFinishedRanking:(NSNotification *) notification{

    [indicator stopAnimating];
    [indicator removeFromSuperview];
    [indicator release];
    [loading removeFromSuperview];
    [loading release];

}

The notifications must be sent as the translucent subview appears, however none of the processing methods seem to be called so the view is permanently locked out until I force close the app.

Does sending the notification change the current flow of the applications launch sequence thereby ceasing to continue executing code in a class? Or have I gone about trying to add an activity indicator to show during some behind the scenes processing the complete wrong way?

Jace
  • 145
  • 2
  • 11
  • So the App Delegate is calling the processing methods? And you are positive that `workingWhileRanking:` is getting called and not some other area that is creating the overlay? – Justin Paulson Jul 24 '12 at 14:49
  • Yep, I added all the code above to a working daily processing routine and the problems have appeared and those methods are definitely the ones being called when the notification occurs. – Jace Jul 24 '12 at 14:51
  • Is the process completely hanging up and never calling `workingFinishedRanking:`? – Justin Paulson Jul 24 '12 at 15:06
  • Yes, none of the processes that are usually called are being called after the notification is posted, including the method to stop the activity indicator. – Jace Jul 24 '12 at 15:09
  • Have you tried adding the `object` to the `NSNotification` (not sure if this will help much)? – Justin Paulson Jul 24 '12 at 15:18
  • But the method to start the activity indicator is starting and hanging up the entire app forcing me to close it. I'm testing on a device. – Jace Jul 24 '12 at 15:19
  • Not sure what the object would be here, it's just a notification that some processes will be conducted. – Jace Jul 24 '12 at 15:22
  • The `object` of an `NSNotification` is always the `object` that is sending the notification. So here it would be `self` in the call and `AppDelegate` in the catch. – Justin Paulson Jul 24 '12 at 15:23
  • Ahh I see, I'll add it and have a look. – Jace Jul 24 '12 at 15:28
  • I've missed out something possibly quite important that may be affecting it. The AppDelegate posts the notification but invokes another class to handle all the methods that are performing all the daily processing. Could that possibly cause this problem? I updated my question with more code. – Jace Jul 24 '12 at 16:01

1 Answers1

2

If I am not interpreting incorrectly your code:

- (void)GoForRankingAndSMProcessing{

  [[NSNotificationCenter defaultCenter] postNotificationName:@"ranking" object:self];
  RankingAndSMProcess *process = [RankingAndSMProcess alloc];
  [process DoRankingAndSocialMediaProcessing];
  [process release];
  [[NSNotificationCenter defaultCenter] postNotificationName:@"rankingDone" object:self];
}

your DoRankingAndSocialMediaProcessing is the task you would like to execute while the activity indicator is showing.

I assume that all processing happens on the same thread (UI thread), and this means that when you execute DoRankingAndSocialMediaProcessing basically your run loop (and hence, the UI) blocks and it is not updated any more. This should explain your issue.

You have several options to change this behavior, depending on what you do in DoRankingAndSocialMediaProcessing.

If you do not do anything related with the UI, it would be very easy to execute that method on a background thread by replacing the direct call to DoRankingAndSocialMediaProcessing with:

[process performSelectorInBackground:@selector(DoRankingAndSocialMediaProcessing) withObject:nil];

Of course you would then send the rankingDone notification from within DoRankingAndSocialMediaProcessing to make things work correctly.

If you can afford a background thread (i.e., you are not updating the UI from within DoRankingAndSocialMediaProcessing) this is the best option, because it will not block the UI at all.

sergio
  • 68,819
  • 11
  • 102
  • 123
  • definitely this should be the issue I bet the most. Can you please post the code of `DoRankingAndSocialMediaProcessing`. Do you run this asynchronously or synchronously? In a separate thread or with GCD in a separate "thread"? If running on the main thread, you are blocking your UI, when running synchronously. If performing on another tread and asynchronous, I don't know if it is good to release process before you know if the other thread finished the task. – Fab1n Jul 24 '12 at 16:20
  • Ye that is exactly what is happening. This sounds like it could be the solution. Performing the processes off the main thread would let the UI update freely with the animating indicator and allow me to prevent the user from progressing through the app until the data is ready, which is the aim of the daily update. I'll have to test this all out tomorrow since I'm done today at work but thanks for the help. – Jace Jul 24 '12 at 16:25
  • That seems to have solved the issue and reduced the time it takes to complete the daily processing which is a very welcome bonus! Thanks for looking at the issue. – Jace Jul 25 '12 at 08:52