J'ai créé une application simple qui suit l'emplacement de l'utilisateur et crée une notification locale pour chaque mise à jour de l'emplacement.
J'ai activé les modes d'arrière-plan ci-dessous,
let locationManager = CLLocationManager()
open override func viewDidLoad() {
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
locationManager.distanceFilter = 10
locationManager.allowsBackgroundLocationUpdates = true
locationManager.startUpdatingLocation()
}
open func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let notification = UILocalNotification()
notification.alertBody = "location updated"
notification.fireDate = Date()
UIApplication.shared.scheduleLocalNotification(notification)
}
J'ai mis la chaîne pour NSLocationAlwaysUsageDescription
et demande la permission. L'utilisateur accorde une autorisation pour toujours l'utiliser lors du premier chargement de l'application.
Cela fonctionne bien lorsque l'application est au premier plan, lorsqu'elle passe en arrière-plan fonctionne toujours au moins dans une plage de temps de 5-40 minutes qui peut être modifiée par la batterie ou autre applications ouvertes.
Le problème est pourquoi il cesse de fonctionner, ne devrait-il pas continuer à fonctionner?
Je n'ai jamais vu de limite de temps dans Apple docs.
Passez à des mises à jour de localisation importantes lorsque l'application passe en arrière-plan. iOS déchargera l'application si elle reste en vie indéfiniment en arrière-plan.
locationManager.pausesLocationUpdatesAutomatically = false
Définissez la propriété desiredAccuracy
de l'objet gestionnaire d'emplacement
self.locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation
Vous pouvez utiliser l'une des constantes CLLocationAccuracy
IMPORTANT
Par défaut, les mises à jour d'emplacement standard sur les appareils iOS s'exécutent avec un niveau de précision optimal. Modifiez ces paramètres en fonction des besoins de votre application. Sinon, votre application gaspillera inutilement de l'énergie.
Définissez la propriété pausesLocationUpdatesAutomatically
de l'objet gestionnaire d'emplacement sur true
self.locationManager.pausesLocationUpdatesAutomatically = true
IMPORTANT
Pour les applications qui ont une autorisation d'utilisation, une pause dans les mises à jour d'emplacement met fin à l'accès aux changements d'emplacement jusqu'à ce que l'application soit relancée et puisse redémarrer ces mises à jour. Si vous ne souhaitez pas que les mises à jour de localisation s'arrêtent complètement, envisagez de désactiver cette propriété et de modifier la précision de la localisation sur
kCLLocationAccuracyThreeKilometers
lorsque votre application passe en arrière-plan. Cela vous permet de continuer à recevoir les mises à jour de position d'une manière économe en énergie.
Définissez la propriété allowsBackgroundLocationUpdates
de l'objet gestionnaire d'emplacement sur true
self.locationManager.allowsBackgroundLocationUpdates = true
Les applications qui souhaitent recevoir des mises à jour d'emplacement lorsqu'elles sont suspendues doivent inclure la clé UIBackgroundModes (avec la valeur d'emplacement) dans le fichier Info.plist de leur application et définir la valeur de cette propriété sur true. La présence de la clé UIBackgroundModes avec la valeur d'emplacement est requise pour les mises à jour en arrière-plan
Définissez la propriété activityType
pour indiquer à Core Location quel type d'activité de localisation votre application effectue à un moment donné
self.locationManager.activityType = .automotiveNavigation
Vous pouvez utiliser l'un des cas CLActivityType
Sur les appareils pris en charge avec du matériel GPS, vous pouvez laisser le gestionnaire de localisation différer la livraison des mises à jour de localisation lorsque votre application est en arrière-plan. Par exemple, une application de fitness qui suit la position de l'utilisateur sur un sentier de randonnée peut différer les mises à jour jusqu'à ce que l'utilisateur ait parcouru une certaine distance ou une certaine période de temps.
Après avoir recherché des références (parler de toute limitation), je suppose que Apple Core Location Best Practices session vidéo pourrait être utile! À 06:53
parler de l'emplacement standard en arrière-plan:
en outre, Core Location n'entreprendra aucune action pour garantir que votre application continue de fonctionner, donc si vous avez exécuté en arrière-plan pour une raison quelconque et que vous décidez de démarrer une session de localisation, vous pouvez obtenir des mises à jour, mais vous pouvez également être suspendu avant de recevoir toutes les informations que vous espérez recevoir ...
En fait, j'ai déjà rencontré ce problème, - comme solution de contournement - l'emplacement principal a été utilisé pour garder un suivi de l'emplacement de l'utilisateur pour effectuer des fonctionnalités non liées à son emplacement - qui télécharge des fichiers -, mais cette solution de contournement n'a pas fonctionné depuis iOS 9 est sorti; J'ai même posté une question faisant référence à ce problème.
Cependant, il semble que votre cas ne soit pas identique à celui auquel j'ai été confronté, si vous visez à:
... crée une notification locale pour chaque mise à jour de l'emplacement.
alors vous devrez peut-être suivre l'approche d'intégration avec Framework de notification utilisateur - NLocationNotificationTrigger :
L'emplacement géographique que l'utilisateur doit atteindre pour permettre la remise d'une notification locale.
Il est également mentionné dans la session vidéo (08:59
).
Probablement, ce n'est peut-être pas ce que vous recherchez, mais comme nous n'avons aucune garantie que l'exécution en arrière-plan continuera de s'exécuter, vous pourrez peut-être trouver un moyen de l'intégrer dans votre application pour obtenir la fonctionnalité souhaitée.
Mise à jour pour iOS 11:
Vous devrez peut-être vérifier cette réponse pour savoir comment demander l'accès à l'emplacement.
Par le son, l'application est tuée en raison de contraintes de mémoire. Il doit cependant être relancé lorsqu'un nouvel emplacement devient disponible, comme décrit ici: https://developer.Apple.com/documentation/uikit/uiapplicationlaunchoptionskey/1623101-location
Vous devriez voir application(_:didFinishLaunchingWithOptions:)
être appelé, et la touche 'location' devrait être présente dans les options de lancement. Vous pourrez ensuite recréer ce qui consomme les emplacements et continuer l'enregistrement.
S'il n'est pas relancé, il pourrait être trop gourmand en mémoire. Vérifiez la consommation de mémoire de l'application et voyez si applicationDidReceiveMemoryWarning(_:)
est appelée.
Je suppose que vous n'avez pas implémenté la tâche d'arrière-plan. Vous pouvez lire ici .
Dans le lien ci-dessus sous la section "Implémentation de tâches de longue durée" point no. 3 est votre situation, il est donc valide que vous pouvez utiliser la mise à jour de l'emplacement en arrière-plan dans votre projet et pour cela, vous devez également implémenter une tâche en arrière-plan.
Il existe trois façons de suivre l'emplacement de l'utilisateur (comme indiqué ci-dessus dans la section "Suivi de l'emplacement de l'utilisateur" ): -
Services de localisation en arrière-plan (je pense que vous essayez pour cela) et la solution consiste à ajouter une tâche en arrière-plan.
Voici un exemple de tâche en arrière-plan et vous pouvez modifier selon vos besoins, cela fonctionne pour moi depuis les 2 dernières heures et mon application met toujours à jour l'emplacement en arrière-plan.
. Dans votre classe AppDelegate, veuillez mettre à jour la fonction ci-dessous, puis exécutez votre application en arrière-plan.
func applicationDidEnterBackground(_ application: UIApplication) {
application.beginBackgroundTask(withName: "") {}
}
Et ci-dessous est ma classe ViewController
import UIKit
import CoreLocation
class ViewController: UIViewController, CLLocationManagerDelegate {
let locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
locationManager.delegate = self;
locationManager.requestAlwaysAuthorization()
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
locationManager.allowsBackgroundLocationUpdates = true
locationManager.distanceFilter = kCLDistanceFilterNone
Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { (timer) in
self.locationManager.startUpdatingLocation()
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
print("didUpdateLocations \(Date())")
self.locationManager.stopUpdatingLocation()
}
}