Возникла проблема с didEnterRegion в CLLocationManager - PullRequest
1 голос
/ 18 февраля 2020

Я пытаюсь определить, находится ли пользователь рядом или входит в мое нужное местоположение. Я использую CLLocationManager для мониторинга этого действия, но по какой-то причине оно не работает. Я нахожусь в текущем местоположении, но didEnterRegion не вызывается. Вот мой код:

class ViewController: UIViewController, CLLocationManagerDelegate {

    var locationManager = CLLocationManager()

    override func viewDidLoad() {
        super.viewDidLoad()

        locationManager.delegate = self
        locationManager.requestWhenInUseAuthorization()


        let center = CLLocationCoordinate2D(latitude: lat, longitude: long)
               if CLLocationManager.isMonitoringAvailable(for: CLCircularRegion.self) {
                   // Register the region.
                   let maxDistance = locationManager.maximumRegionMonitoringDistance
                   let region = CLCircularRegion(center: center,
                        radius: maxDistance, identifier: "identifier")
                   region.notifyOnEntry = true
                   region.notifyOnExit = false

                   locationManager.startMonitoring(for: region)

            }
    }


  func locationManager(_ manager: CLLocationManager, didEnterRegion region: CLRegion) {
    if region is CLCircularRegion {
            print("entered....")
        }
    }

Я также добавил описания конфиденциальности в plist-файле: enter image description here

Как я могу решить эту проблему?

Отредактировано :

requestState(for region:) и didDetermineState:for: работают сейчас, но как я могу проверить, находится ли пользователь рядом или в этом месте? например, если пользователь находится рядом или в регионе, что-то сделать, а если нет, сделать что-то еще.

Отредактировано 2

let center = CLLocationCoordinate2D(latitude: lat, longitude: long)
            let region = CLCircularRegion(center: center, radius: 1000, identifier: "Store")
            let controller = LocationController()

               controller.requestWhenInUseAuthorization()

               controller.requestState(for: region) { (state) in

                   switch state {
               case .inside:
                   print("inside region")
               case .outside:
                   print("outside region")
               case .unknown:
                   print("unknown")

                   }

               }

Ответы [ 3 ]

1 голос
/ 26 февраля 2020

Если вы запускаете это на симуляторе, вы можете увидеть результаты, отличные от тех, которые вы запускаете на устройстве. Например, если вы уже находитесь в определенном регионе, и вы используете симулятор для тестирования. Вы не всегда можете получить желаемые результаты. По какой-то причине симулятору не нравится, если вы находитесь внутри региона, который вы хотите обнаружить при включении.

Более того, после многих моих собственных испытаний с использованием маяков выяснилось, что расстояние от региона НЕ является точным, когда на симуляторе. Это часто было неправильно при использовании симулятора. На него также сильно влияют любые физические помехи между вашим компьютером и маяком. Множество других устройств в этом районе и металл могут сильно повлиять на ваш симулятор, предоставив правильные данные. Я рекомендую протестировать весь ваш код на физическом устройстве. При загрузке устройства с приложением. Отключите устройство от компьютера и включите приложение за пределами области маяка.

Для дальнейшего и лучшего тестирования вы можете создать собственный локальный «отладчик» в приложении, чтобы при использовании устройства вы могли видеть нужную информацию, не подключаясь к компьютеру.

1 голос
/ 26 февраля 2020

изменить

  locationManager.requestWhenInUseAuthorization()

на

  locationManager.requestAlwaysAuthorization()

также проверьте ваш файл gpx

1 голос
/ 24 февраля 2020

Для одноразовой проверки requestState(for:) - это то, что вам нужно.

Затем CoreLocation определит состояние и затем вызовет функцию locationManager(_:didDetermineState:for:) на вашего делегата, давая вам CLRegionState перечисление, которое вы можете проверить для == .inside

Пример:

import CoreLocation

class LocationController: CLLocationManagerDelegate {
    typealias RegionMonitoringClosure = (CLRegion, Bool) -> Void
    typealias RegionStateClosure = (CLRegion, CLRegionState) -> Void

    private let manager = CLLocationManager()
    private let stateClosure: RegionStateClosure
    private let monitoringClosure: RegionMonitoringClosure

    init(stateClosure: RegionStateClosure, monitoringClosure: RegionMonitoringClosure) {
        manager.delegate = self
        self.stateClosure = stateClosure
        self.monitoringClosure = monitoringClosure
    }

    func addMonitoredRegion(_ region: CLRegion) {
        manager.startMonitoring(for: region)
    }

    func remove(monitoredRegion region: CLRegion) {
        manager.stopMonitoring(for: region)
    }

    func requestState(for region: CLRegion) {
        manager.requestState(for: region)
    }

    // MARK: CLLocationManagerDelegate

    func locationManager(_ manager: CLLocationManager, didEnterRegion region: CLRegion) {
        print("Entered \(region)")

        self.monitoringClosure(region, true)
    }

    func locationManager(_ manager: CLLocationManager, didExitRegion region: CLRegion) {
        print("Exited \(region)")

        self.monitoringClosure(region, false)
    }

    func locationManager(_ manager: CLLocationManager, didStartMonitoringFor region: CLRegion) {
        print("Started monitoring region \(region)")
    }

    func locationManager(_ manager: CLLocationManager, didDetermineState state: CLRegionState, for region: CLRegion) {
        print("Determined state \(state) for region \(region)")

        self.stateClosure(region, state)
    }
}

Использование:

let regionToTest: CLRegion = ... // your desired region.
let controller = LocationController(stateClosure: { region, state in 
    switch state {
    case .inside:
        print("inside region \(region)")
    case .outside:
        print("outside region \(region)")
    }
}, monitoringClosure: { region, entered in 
    if entered == true {
       print("Entered \(region)")
       //...
    }
})

controller.requestState(for: regionToTest)
...