Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIApplication.didBecomeActiveNotification Gets Called One-time Unexpectedly When User Swipe Down the Notification Center Screen on iOS Device

like the title says, I found this unexpected behavior in iOS 11 & 12.
Does anyone know why this event gets called and, more importantly, is there any workaround to prevent system from firing this UIApplication.didBecomeActiveNotification event out?

Here are the steps to reproduce this behavior:

  1. Run the application.
  2. Access the Notification Center Screen on iPhone or iPad(by swiping downward from the very top of the device's screen).
  3. At the time when the Notification Center Screen gets to the bottom of the device's screen, a UIApplication.didBecomeActiveNotification event gets fired.

You can simply add a log in AppDelegate.swift file for testing, like:

func applicationDidBecomeActive(_ application: UIApplication) {
        print("applicationDidBecomeActive")
}

I call it unexpected because when the Notification Center Screen appears, the application literally should turn to (at least semi-)background-mode and not turn back to foreground-mode unless the Notification Center Screen disappears(e.g. by swiping up to the upper-most top of the screen).
I also observed that the event did not get fired when the Control Center Screen shows up.

In my app, I'm trying the control the status of a video player when the app goes to the background(or semi-background). The unexpected .didBecomeActiveNotification event annoys the status-controlling workflow.

I searched on the Open Radar and here and googled for a while and no such related topic appeared.

Any suggestion would be appreciated. Thank you.

like image 828
inexcii Avatar asked Nov 17 '22 08:11

inexcii


1 Answers

I had the same problem. I have a workaround, but you cannot prevent the extra applicationDidBecomeActive. At least not that I could find. So basically what I found out was that a few milliseconds after applicationDidBecomeActive gets called, applicationWillResignActive also gets called. So if it doesn't matter that code will be executed some milliseconds later this is what I am doing:

    private var firstDidBecomeActive = true
    private var appDidBecomeActiveWorkItem: DispatchWorkItem?

    func applicationDidBecomeActive(_ application: UIApplication) {
        //Skip first time, because that is start of the app
        if self.firstDidBecomeActive {
            self.firstDidBecomeActive = false
            return
        }

        self.appDidBecomeActiveWorkItem = DispatchWorkItem {
            //Do what you want here
        }

        //Make sure there is a small delay because when user opens notification center, it becomes active again and then after a few milliseconds resigns active
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.02, execute: self.appDidBecomeActiveWorkItem!)
    }
    
    func applicationWillResignActive(_ application: UIApplication) {
        self.appDidBecomeActiveWorkItem?.cancel()
        self.appDidBecomeActiveWorkItem = nil
    }
like image 96
Kevin van Mierlo Avatar answered Dec 21 '22 08:12

Kevin van Mierlo