3

it's my first question here as I have a problem developing my first iOS app. It is one of the thousands of flashlight apps, however I'm trying to put as many features as possible to it. One of them is saving the state of the app when it goes to background or terminates. After going to foreground (iOS 4 or higher) or relaunching, I'm loading the settings from file and reapplying them. One of the settings is, obviously, the AVCaptureDevice.torchMode. However, I encounter the problem with this. I'm reapplying these settings in the applicationDidBecomeActive method. It all seems to work, but when I very quickly tap the home button followed by relaunching an app, the app will do the following (I delayed the applicationDidBecomeActive method to observe it):

1. shows black screen (loading)
2. executes applicationDidBecomeActive and turns on the LED (I put my delay here)
3. shows my current UIViewController and at the same moment turns off the LED

It only happens after calling an app from background right after it was sent there. I know it's not the realistic use-case scenario, but I like to think that bugs often "stack up" and due to this (possibly) bad design I might encounter other problems in future. I am absolutely sure this is not my code turning the LED off since I NSLog whenever my code modifies the AVCaptureDevice.torchMode property. So, to be exact, my question is:
What method is called after applicationDidBecomeActive, possibly related to the UIViewController, that could turn my torch off? And is there any possible solution or work-around to it?

Bartek Eborn
  • 524
  • 5
  • 12

2 Answers2

5

According to the iOS App Programming guide:

Returning to the foreground is your app’s chance to restart the tasks that it stopped when it moved to the background. The steps that occur when moving to the foreground are shown in Figure 3-6. The applicationWillEnterForeground: method should undo anything that was done in your applicationDidEnterBackground: method, and the applicationDidBecomeActive: method should continue to perform the same activation tasks that it would at launch time.

Have you tried re-applying your settings in the applicationDidBecomeActive: method instead of the applicationWillEnterForeground: ?

Another thing to consider is working with notifications:

In the applicationDidBecomeActive: or applicationDidBecomeActive: methods of the AppDelegate, you can tell your app delegate to dispatch notifications to your controllers:

- (void)applicationDidBecomeActive:(UIApplication *)application {
    /*
     Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
     */

    // Dispatch notification to controllers
    [[NSNotificationCenter defaultCenter] postNotificationName: @"didBecomeActive" 
                                                        object: nil 
                                                      userInfo: nil];
}

Once you have this, the view controller can register for these notifications (in their init method, for example) like so:

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

This way, your controller is aware that the app just became active and can execute any method you want.

In this example, you are telling your view controller to execute the loadSettings method when it receives the didBecomeActive notification (which was posted by the app delegate).

Mutix
  • 4,196
  • 1
  • 27
  • 39
  • Yes, you are obviously right that `applicationDidBecomeActive` will be called after `applicationWillEnterForeground`. I actually meant it, but tested both methods and result was the same, sorry for that. Already edited my question. And regarding notification center: just tested it, and it does not fix the problem. Actually, since I "notify" the `UIViewController` in `applicationDidBecomeActive`, isn't it the same as directly loading settings in `applicationDidBecomeActive` like I currently do? My debugging showed there's something happening **after** `applicationDidBecomeActive`... – Bartek Eborn Dec 05 '11 at 16:42
3

I only have an answer as to why a quick stop start of the App will display a black screen, I have no reference only personal experience and observation.

When the App is sent to the background the OS attempts to take a screen shot to use instead of the Default.png. If you start the App before a screenshot is taken and you don't have a Default.png in your project then you will get that.

Still thinking about your actual question.

Thomas Nadin
  • 1,167
  • 10
  • 22
  • Even though it is not an answer to my question, I'm upvoting since I didn't know about this screenshot-taking part. Will using the `Default.png` disable it at all? Maybe avoiding one operation happening on close could at least make the situation from my question less common? EDIT: Well, I guess I need more reputation to upvote. If I don't forget I'll do it when I'm able to. – Bartek Eborn Dec 06 '11 at 00:38
  • Thank you. Sadly no, The `Default.png` is only used when the screenshot could not be taken. – Thomas Nadin Dec 06 '11 at 10:33