Невозможно выполнить HTTP-вызовы, если приложение разбудило событие геозоны - PullRequest
1 голос
/ 09 января 2020

Мы реализовали геозону в нашем приложении. Кажется, это работает нормально, пока приложение не убито (удалено пользователем)

Если принудительное закрытие, геозоны срабатывают, как я вижу в моем входе в систему func locationManager(_ manager: CLLocationManager, didEnterRegion region: CLRegion), но когда я пытаюсь чтобы сделать http traffi c, независимо от того, использую ли я alamofire или другой подход (см. ниже), он, похоже, застрял.

Это код

private func beginBackgroundUpdateTask() -> UIBackgroundTaskIdentifier {
    return UIApplication.shared.beginBackgroundTask(expirationHandler: {
        log.error("#geofence expiration handler was executed")            
    })
}

private func endBackgroundUpdateTask(taskID: UIBackgroundTaskIdentifier) {
    UIApplication.shared.endBackgroundTask(taskID)
}    


func sendEvent(eventType: EventType, id: String) {
    let taskID = beginBackgroundUpdateTask()        

    log.info("#geofence sending event: \(eventType.rawValue) id: \(id) with background task id: \(taskID)")

   //... stripped out

    sendRequest(url: personUrlWithParameters, params: params, taskID: taskID, eventType: eventType)

}


func sendRequest(url: String, params: [String : Any], taskID: UIBackgroundTaskIdentifier, eventType: EventType) {        

    let url = URL(string: url)

    let request = NSMutableURLRequest(url: url!)

    let session = URLSession.shared
    request.httpMethod = "PUT"

    log.debug("#geofence params: \(params)")

    do {
        request.httpBody = try JSONSerialization.data(withJSONObject: params, options: [])
    } catch let error as NSError {
        log.error(error.localizedFailureReason!)
        request.httpBody = nil
        return
    }
    request.addValue("application/json", forHTTPHeaderField: "Content-Type")
    request.addValue("application/json", forHTTPHeaderField: "Accept")
    request.addValue("Something", forHTTPHeaderField: "Authorization")

    let task = session.dataTask(with: request as URLRequest, completionHandler: {data, response, error -> Void in
        if let resp = response as? HTTPURLResponse {

//// THIS LINE is never reached ///

            log.debug("#geofence PUT responseCode \(resp.statusCode)")                       

            if resp.statusCode == 200 {
                log.info("#geofence event: \(eventType.rawValue) id: \(taskID.rawValue) succeeded")

            } else {
                log.error("#geofence error occured - must notify user about it: \(eventType.rawValue) id: \(taskID.rawValue) failed with response code: \(resp.statusCode)")
            }

            log.info("#geofence stop task with id: \(taskID)")
            UIApplication.shared.endBackgroundTask(taskID)

            return
        }

    })
    task.resume()
}

Как видите, мы запускаем backgroundTask и даже корректно завершаем его.

Обработчик завершения вызова http никогда не достигается, см. комментарий внутри кода. Интересно то, что обработчик истечения также не достигнут, независимо от того, как долго вы ждете. Поскольку я могу проверить это только при принудительном закрытии приложения, нет возможности отладить его в отладчике.

Что я делаю не так? Чем отличается обычный запуск приложения от запуска из-за .location? (см. код ниже) Почему я не могу использовать HTTP? Чтобы пояснить еще раз, приведенный выше код работает без сбоев, если приложение не убито! (edit: Нет, это не на 100% надежно. Быть открытым в переключателе задач не обязательно означает, что оно будет работать. Кажется, это зависит от времени, когда приложение не использовалось. Если слишком много, оно не будет работать хотя все еще открыт в переключателе задач) Помощь очень ценится

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

        initLogger()

        log.warning("#lifecycle didFinishLaunchingWithOptions")          

        if let keys = launchOptions?.keys {
            if keys.contains(.location) {                   
                    log.info("Started because of location!")                      
                }
            }
        }
        else {
            log.info("Regular App start (NOT because of location)")
        }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...