Emit socket event in applicationWillTerminate

657 views Asked by At

I am trying to emit a socket event in applicationWillTerminate in AppDelegate. I have used socket.io.

I believe I am able to successfully emit the event. Following are the logs I get in the console :

2018-10-08 20:29:45.663856+0530 SOCKET_POC[4718:303986] LOG SocketIOClient{/}: Emitting: 23["device-disconnect","{\"QrcodeID\":\"2a758b00-314f-d69d-a10b-24fca56693ed\",\"UniqueID\":\"E15C087D-626F-4F10-B0B3-7567DA76EF51\"}"], Ack: false 2018-10-08 20:29:49.561608+0530 SOCKET_POC[4718:304214] LOG SocketEngine: Writing ws: 23["device-disconnect","{\"QrcodeID\":\"123\",\"UniqueID\":\"123\"}"] has data: false 2018-10-08 20:29:49.561675+0530 SOCKET_POC[4718:304214] LOG SocketEngineWebSocket: Sending ws: 23["device-disconnect","{\"QrcodeID\":\"123\",\"UniqueID\":\"123\"}"] as type: 4

Please find the code below :

 func applicationWillTerminate(_ application: UIApplication) {
    print(SocketHandler.instance?.socket.status)
    if let uniqueId = UserDefaults.standard.value(forKey: Constants.USER_DEFAULT_KEYS.UINQUE_ID) as? String {

        CommonFunctions().emitResultOnDeviceDisconnect(qrcode: "\(Variables.QRCodeID)", uniqueId: uniqueId)
        print(SocketHandler.sharedInstance().socket.status)
}

I have even printed the status of my socket which always prints connected.

But when I see the logs at the server(backend), they don't receive my emitted socket event at all.

2

There are 2 answers

0
Chankya Hirapra On

In your AppDelegate.Swift, change your "applicationDidEnterBackground(_ application: UIApplication)" to Following code ==>

func applicationDidEnterBackground(_ application: UIApplication) {
    var bgTask: UIBackgroundTaskIdentifier = 0;
    bgTask = application.beginBackgroundTask(withName:"MyBackgroundTask", expirationHandler: {() -> Void in
        print("The task has started")
        application.endBackgroundTask(bgTask)
        bgTask = UIBackgroundTaskInvalid
    })
}

And keep your logic of "applicationWillTerminate" as it is.

0
Ankush Bhatia On

If you want to fire socket event as soon as you kill the application, you need to create a background task as from the apple's developer documentation.

optional func applicationWillTerminate(_ application: UIApplication)

You should use this method to perform any final clean-up tasks for your app, such as freeing shared resources, saving user data, and invalidating timers. Your implementation of this method has approximately five seconds to perform any tasks and return. If the method does not return before time expires, the system may kill the process altogether.

What you can do is create a background task to fire the socket event so that if we are supposed to receive a callback, we can get in time.

Please follow the following code to resolve the problem you are facing:

Add this property in your Appdelegate

var taskIdentifier: UIBackgroundTaskIdentifier = UIBackgroundTaskInvalid

Add the following methods

func startBackgroundTask() {
  taskIdentifier = UIApplication.shared.beginBackgroundTask(expirationHandler: { [weak self] in
        self?.endBackgroundTask()
    })
    // Only to check if the task is in invalid state or not for debugging.
    assert(task != UIBackgroundTaskInvalid)
}

func endBackgroundTask() {
    UIApplication.shared.endBackgroundTask(taskIdentifier)
    taskIdentifier = UIBackgroundTaskInvalid
}

func applicationWillTerminate(_ application: UIApplication) {
    if let uniqueId = UserDefaults.standard.value(forKey: Constants.USER_DEFAULT_KEYS.UINQUE_ID) as? String {
       CommonFunctions().emitResultOnDeviceDisconnect(qrcode: "\(Variables.QRCodeID)", uniqueId: uniqueId)
    }
    self.startBackgroundTask()
}

I hope this will solve your problem. In case of any issues please feel free to as in loop.

Thanks.