我正在构建一个国家追踪应用程序。用户安装应用程序,通过多个API应用程序获取用户所在国家/地区并将其保存在核心数据中。问题是 BGTask 不可靠。在过去的三天里,我没有看到它执行一次。是否可以采取不同的做法?
我想添加第三个解决方案到我的
BGTaskScheduler.shared.register(forTaskWithIdentifier: "///", using: nil) { task in
self.handleLocationFetch(task: task as! BGAppRefreshTask) }
private func scheduleAppRefresh() {
let request = BGAppRefreshTaskRequest(identifier: "///")
request.earliestBeginDate = Date(timeIntervalSinceNow: 1800) // 30 minutes
do {
try BGTaskScheduler.shared.submit(request)
} catch {
print("Could not schedule app refresh: \(error)")
}
}
和
init() {
BGTaskScheduler.shared.register(forTaskWithIdentifier: "com.pinborg.countryTracker.locationfetch", using: nil) { task in
self.handleLocationFetch(task: task as! BGAppRefreshTask) }
}
,无论如何,永远有效的一个。预先感谢您。
编辑:
private func handleLocationFetch(task: BGAppRefreshTask) {
scheduleAppRefresh()
let locationManager = LocationManager()
let entryStore = EntryStore()
let openCageVM = OpenCageVM()
task.expirationHandler = {
locationManager.locationManager.stopMonitoringSignificantLocationChanges()
}
locationManager.locationManager.startMonitoringSignificantLocationChanges()
// Fetch the "app storage" toggle setting from UserDefaults (or another storage)
let allowTrackingDuringFlight = UserDefaults.standard.bool(forKey: "allowTrackingDuringFlight")
DispatchQueue.main.asyncAfter(deadline: .now() + 1, execute: {
guard let location = locationManager.locationManager.location else {
print("Failed to fetch location.")
task.setTaskCompleted(success: false)
return
}
let altitude = location.altitude
// If app storage is enabled, check the altitude; otherwise, ignore altitude
if !allowTrackingDuringFlight && altitude > 5000 {
print("Location altitude is too high. Task aborted.")
task.setTaskCompleted(success: false)
return
}
let lat = location.coordinate.latitude
let lng = location.coordinate.longitude
// Call the API to fetch location information
openCageVM.fetchLocationInfo(lat: lat, lng: lng) {
print("Location info fetched")
self.sendLocationNotification(location: location)
// Use fetched data to add an entry to the store
entryStore.addNewEntryHistory(
date: Date(),
iso2: openCageVM.info?.results?.first?.components?.iso31661Alpha2 ?? "",
iso3: openCageVM.info?.results?.first?.components?.iso31661Alpha3 ?? "",
name: openCageVM.info?.results?.first?.components?.country ?? ""
)
task.setTaskCompleted(success: true)
}
})
task.setTaskCompleted(success: true)
}
对你的问题的简短回答是否。 正如 Rob Napier 所提到的,苹果明确禁止应用程序在后台无限期运行,只有少数例外。
鉴于您的用例是跟踪用户在国家/地区之间的旅行,您应该使用 Core Location 的
startMonitoringSignificantLocationChanges
,再次按照 Rob Napier 在评论中的建议。
GPS 非常耗电,保持它“亮着”会很快耗尽用户的电池。重要的位置更改 API 允许系统仅偶尔打开 GPS,并且仅在检测到用户移动了有意义的距离时才调用应用程序的代码,从而限制电量使用。 (文档说,当用户从之前的位置移动 500 米时,您会收到通知,并且您不应该期望比每 5 分钟更频繁地接到电话。我不知道如何将这两件事平方,因为有人乘坐汽车/公共汽车/火车肯定会在 5 分钟内行驶超过 500 米。)