1

Is there a way to tell if an iOS app enters the foreground from fast-app switching or manually? I need to know by the time applicationWillEnterForeground is called, so some specific code can be executed (or not executed) depending on the condition in which the app entered the foreground.

EDIT: It turned out that this was more of a design issue for me. I moved my code to applicationDidBecomeActive. I also added a BOOL property to the appDelegate called fastAppSwitching (probably the wrong name for it). I set this to YES in application:handleOpenURL and application:openURL:sourceApplication:annotation. Then I added the following code to application:didFinishLaunchingWithOptions:

        if (launchOptions) {
            self.fastAppSwitching = YES;
        }
        else {
            self.fastAppSwitching = NO;
        }

In applicationDidBecomeActive, I used the following code:

    if (fastAppSwitching == YES) {
        self.fastAppSwitching = NO; //stop, don't go any further
    }
    else {
       ...
    }

EDIT2: MaxGabriel makes a good point below: "Just a warning to others taking the solution described here, applicationDidBecomeActive: is called when the user e.g. ignores a phone call or text message, unlike applicationWillEnterForeground". This is actually also true for in-app purchases and Facebook in-app authorization (new in iOS 6). So, with some further testing, this is the current solution:

Add a new Bool called passedThroughWillEnterForeground.

In applicationWillResignActive:

self.passedThroughWillEnterForeground = NO;

In applicationDidEnterBackground:

self.passedThroughWillEnterForeground = NO;

In applicationWillEnterForeground:

self.passedThroughWillEnterForeground = YES;

In applicationDidBecomeActive:

    if (passedThroughWillEnterForeground) {
        //we are NOT returning from 6.0 (in-app) authorization dialog or in-app purchase dialog, etc
        //do nothing with this BOOL - just reset it
        self.passedThroughWillEnterForeground = NO;
    }
    else {
        //we ARE returning from 6.0 (in-app) authorization dialog or in-app purchase dialog - IE
        //This is the same as fast-app switching in our book, so let's keep it simple and use this to set that
        self.fastAppSwitching = YES;
    }

    if (fastAppSwitching == YES) {

        self.fastAppSwitching = NO;
    }
    else {
        ...
    }

EDIT3: I think we also need a bool to tell if app was launched from terminated.

SAHM
  • 4,078
  • 7
  • 41
  • 77
  • What do you mean by 'manually'? Isn't fast app switching done manually as well? –  Nov 16 '12 at 23:08
  • I may not have the terminology correct, but I understood that Facebook, Dropbox and other 3rd parties often implement fast-app-switching for sign-on within an app. – SAHM Nov 16 '12 at 23:10
  • Oh, I see. So you mean you want to know whether your app was launched by another app or the user, right? –  Nov 16 '12 at 23:11
  • Yes, exactly. I know I can find that out in application:openURL:sourceApplication:annotation:(id)annotation, but the problem is that that method isn't called until AFTER applicationWillEnterForeground, which is too late. – SAHM Nov 16 '12 at 23:14
  • Or if you know how to tell if *leaving* the app was launched by the user or another app, that would help too. I could store it as a bool. – SAHM Nov 16 '12 at 23:16
  • 1
    I was going to point you to that method... Well, IDK in this case. But why do you need that in `applicationWillEnterForeground;`? I smell a design problem here. –  Nov 16 '12 at 23:19
  • You're probably right. Let me revisit my code. Otherwise I will post a good reason later. Thanks for your help. – SAHM Nov 16 '12 at 23:25
  • H2CO3 if you will post your comments as an answer, including applicationWillEnterForeground and design problem I will accept it. I keep learning in iOS that when things seem too complicated, I am usually trying to do something I shouldn't be doing. – SAHM Nov 17 '12 at 00:34
  • 1
    Just a warning to others taking the solution described here, `applicationDidBecomeActive:` is called when the user e.g. ignores a phone call or text message, unlike `applicationWillEnterForeground` – MaxGabriel Nov 17 '12 at 01:47
  • And making an in-app purchases, and doing in-app validation for Facebook... I may need to modify answer again.. – SAHM Nov 17 '12 at 02:36
  • @JPK So I posted this as an answer, thank you! –  Nov 17 '12 at 07:03
  • I too would like a good answer to this. For now, when I do Facebook fast-app switching I set a BOOL property on my app delegate so it can know to ignore `willEnterForeground` code. Hopefully someone has a better approach. – MaxGabriel Nov 17 '12 at 00:10
  • I am learning that Apple usually does have some logic to the way they do things. As H2CO3 said above, there may be a design problem if you need to know this before willEnterForeground. I went through my code closely and found that, with some wrangling, I could move my code to applicationDidEnter Background. I will post the code that helped me above. – SAHM Nov 17 '12 at 00:37
  • Thanks for the comment above. You are right. I am trying to stay away from specific bools (i.e. for Facebook, dropbox, in-app purchases, phone calls etc), because there are so many reasons an app can become inactive. So I was just playing around and found that setting an additional non-specific bool in the app delegate functions does take care of this. I will post the code above. Let me know what you think - or if this is what you are already doing. – SAHM Nov 17 '12 at 03:19
  • JPK, I don't fully understand your solution so I'm unsure how it differentiates fast-app switching from manually entering the app. However, I trust you that it works, in which case your solution is far more generic and reliable. Nice work – MaxGabriel Nov 17 '12 at 04:47
  • I'm getting there... but just found I'm not quite there yet. Think I also need to add a bool to tell if the app was launched from terminated, and that should do it. Yeah, I think Apple fell a bit short on this one, especially considering that Facebook integration alone demands that we handle fast-app switching and in-app authorization. We really need a better way than these bools to tell what is going on. – SAHM Nov 17 '12 at 04:53

2 Answers2

3

If your application is launched by another application, the

- (BOOL)application:(UIApplication *)app
            openURL:(NSURL *)url
  sourceApplicarion:(NSString *)bundleID
         annotation:(id)info;

method is called on your app delegate. You can use this method to e. g. set a Boolean switch to true that indicates whether the app was launched by another program.

The peoblem is that this method is called after applicationWillEnterForeground:, so you can't tell in that method whether your app was launched manually or automatically.

However, I suspect that if you need this to be detected in a particular method, you may have a design problem and you should probably reorganize your code.

  • I think this is basically a good answer, but I learned more after the fact, as seen in my comments in the original question. I would still like to find a more simple way that bools set all over the app delegate to tell if an app is coming back from authorizing another app, either via fast-switching or in-app authorization – SAHM Nov 30 '12 at 14:57
1

In the case where your app is opened from another app, application:openURL:sourceApplication:annotation will be called on your app delegate.

Michael Mior
  • 28,107
  • 9
  • 89
  • 113
  • As per his comment above, "Yes, exactly. I know I can find that out in `application:openURL:sourceApplication:annotation:(id)annotation`, but the problem is that that method isn't called until AFTER applicationWillEnterForeground, which is too late.". So he is looking for a delegate method which will be called even before this. – iDev Nov 17 '12 at 00:10
  • Apologies. I missed the comment about this. – Michael Mior Nov 17 '12 at 00:28
  • @MichaelMior No problem, that is where I ended up going anyway. I am giving H2CO3 the chance to add his comments as an answer since he helped to guide me in the right direction early. Thanks for your answer. – SAHM Nov 17 '12 at 00:38