Я пытаюсь создать приложение для watchOS, которое должно отображать позицию, когда пройдено указанное расстояние. Я полностью осознаю, что такое поведение может быть достигнуто благодаря свойству distanceFilter
CLLocationManager
. Во всяком случае, несмотря на это, мое приложение занимает все больше места, время от времени делая приложение «sh». Я не перемещал свое устройство в течение этого периода времени.
Я хочу отметить, что мой distanceFilter
составляет примерно 15 метров, но приложение по-прежнему определяет положение в большинстве случаев.
Для Ради ясности я кратко расскажу о функциональности: имея определенную область, я должен время от времени искать свое местоположение и проверять, содержит ли область его. Если я покину регион, я отправлю уведомление. Вот соответствующий код:
//Premise: Forget Class is a class which contains a region I should monitor.
enum ScanningMode {
case Precise
case Normal
//new
case Inactive
}
class LocationManager : NSObject, CLLocationManagerDelegate, UNUserNotificationCenterDelegate, ObservableObject {
let LocMng = CLLocationManager()
let NotMng = UNUserNotificationCenter.current()
var modeOfScanning: ScanningMode!
var forgets = [Forget]()
private var actualLocation: CLLocation!
private var actualForget: Forget!
private var previousForget: Forget!
override init() {
super.init()
modeOfScanning = ScanningMode.Precise
//temporary
let latitude = SomeLatitude
let longitude = SomeLongitude //for privacy reasons
let radius : Double = 10.0
let name = "owo"
let test = [Forget(latitude: latitude, longitude: longitude, radius: radius, name: name, items: ["item"])]
do {
let priorArchiver = try JSONEncoder().encode(test)
UserDefaults.standard.set(priorArchiver, forKey: "frgts")
} catch {
print("Can't archive: \(error)")
}
if let archive = UserDefaults.standard.object(forKey: "frgts") as? Data {
let decoder = JSONDecoder()
if let frgts = try? decoder.decode([Forget].self, from: archive) {
forgets = frgts
}
}
actualForget = nil
previousForget = nil
actualLocation = nil
resume()
}
private func startLocalization(){
switch modeOfScanning!{
case ScanningMode.Precise:
LocMng.desiredAccuracy = kCLLocationAccuracyBest
LocMng.distanceFilter = 15.0
case ScanningMode.Normal:
LocMng.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
LocMng.distanceFilter = 80.0
case ScanningMode.Inactive:
LocMng.desiredAccuracy = kCLLocationAccuracyThreeKilometers
LocMng.distanceFilter = 9999.0
}
LocMng.startUpdatingLocation()
}
private func setupManager(){
LocMng.delegate = self
LocMng.requestAlwaysAuthorization()
}
func resume(){
setupManager()
//setupNotification()
startLocalization()
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
if status == CLAuthorizationStatus.authorizedAlways{
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
// 1. Block further updates instantly
updateScanningMode(.Inactive)
//2. Allow Background Updates
LocMng.allowsBackgroundLocationUpdates = true
//3. Grep last location
let length = locations.count
actualLocation = locations[length-1]
//4. Verify if region contains location
actualForget = checkIfContains()
//5. Given Previous and Actual Location, compare them
//Case a: actualLocation is nil and previousLocation is nil
if actualForget == nil && previousForget == nil{
// I was out of any location and I'm still out of any location
updateScanningMode(.Normal)
print("No updates on location. Out of every region.")
}
//Case b: actualForget is nil and previousLocation is not nil
else if actualForget == nil {
// I am out of any location but was in a location
updateScanningMode(.Normal)
print("I just exited region: \(previousForget.name!).")
scheduleNotification(forget: previousForget!)
}
//Case c: actualForget is not nil and previousLocation is nil
else if actualForget != nil && previousForget == nil{
// I was out of a location and I'm now in a location
updateScanningMode(.Precise)
print("I just entered region: \(actualForget.name!).")
}
//Case d: both not nil (happens rarely)
else if actualForget != nil && previousForget != nil && actualForget == previousForget{
updateScanningMode(.Precise)
print("I just abruptly entered region: \(actualForget.name!).")
scheduleNotification(forget: previousForget!)
}
//Case f: both not nil but equal
else{
print("I am still in the region: \(actualForget.name!).")
}
//6. Update previousForget
previousForget = actualForget
}
private func checkIfContains() -> Forget? {
//get all forgets and check if contained in region
print(actualLocation!)
for f in forgets{
let region = f.region
print(region)
print(f.name!)
if region.contains(actualLocation!.coordinate) {
return f
}
}
return nil
}
private func updateScanningMode(_ scan: ScanningMode){
if scan == .Precise && modeOfScanning != .Precise {
modeOfScanning = .Precise
LocMng.desiredAccuracy = kCLLocationAccuracyBest
LocMng.distanceFilter = 15.0
}
else if scan == .Normal && modeOfScanning != .Normal {
modeOfScanning = .Normal
LocMng.desiredAccuracy = kCLLocationAccuracyHundredMeters
LocMng.distanceFilter = 80.0
}
else if scan == .Inactive && modeOfScanning != .Inactive {
modeOfScanning = .Normal
LocMng.desiredAccuracy = kCLLocationAccuracyThreeKilometers
LocMng.distanceFilter = 9999.0
}
}
}
Результаты консоли:
<+someloc,+someloc> +/- 65.00m (speed -1.00 mps / course -1.00) @ 19/01/2020, 23:22:22 Central European Standard Time
CLCircularRegion (identifier:'owo', center:<+someloc,+someloc>, radius:10.00m)
owo
No updates on location. Out of every region.
<+someloc,+someloc> +/- 65.00m (speed -1.00 mps / course -1.00) @ 19/01/2020, 23:22:31 Central European Standard Time
CLCircularRegion (identifier:'owo', center:<+someloc,+someloc>, radius:10.00m)
owo
No updates on location. Out of every region.
<+someloc,+someloc> +/- 165.00m (speed -1.00 mps / course -1.00) @ 19/01/2020, 23:24:19 Central European Standard Time
CLCircularRegion (identifier:'owo', center:<+someloc,+someloc>, radius:10.00m)
owo
I just entered region: owo.
//I got other 10+ location in less than 1 minute and half WITHOUT MOVING MY WATCH
Заранее спасибо.