Search code examples
iosswiftbackgroundalamofire

How to get data from Alamofire in the "performFetchWithCompletionHandler" function in the App Delegate?


Alright, so I've been trying really hard to get the answer to this but I still can't get Alamofire to do its magic when I simulate a background refresh via Xcode.

This is what my said function in app delegate looks like

func application(_ application: UIApplication, performFetchWithCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { 

    let vc = ViewController()
    vc.fetchData()
    vc.sendNoti(currentFlightRules: currentFlightRules)
    completionHandler(.newData)
        print("Background Fetch Complete! UP")
}

fetchData() is the one that has the API request via Alamofire and it doesn't run whereas the sendNoti() does. I know that this implementation is running as when I simulate the background refresh the print statement executes.

I'd really appreciate some help with this as I'm not familiar with how to do tasks in the background and especially networking tasks in the background. Thanks in advance.


Solution

  • Your problem is that fetchData will complete asynchronously. This means that sendNotification and the completionHandler will be called before the network operation has been completed.

    You need your fetchData function to accept and invoke a completion handler when it has the data. You then invoke the notification method and the background fetch completionHandler from that closure:

    func application(_ application: UIApplication, performFetchWithCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { 
    
        let vc = ViewController()
        vc.fetchData { (error, data) in 
            guard error == nil else {
                print("There was an error \(error!.localizedDescription)")
                completionHandler(.failed)
                return
            }
    
            if let newData = data {
                vc.sendNoti(currentFlightRules: newData)
                completionHandler(.newData)
            } else {
                completionHandler(.noData)
            }
        }
    }
    

    I would also suggest that you refactor so that your fetch and notification operations are not included in a view controller; they should be separated out into their own classes.