web-dev-qa-db-ja.com

locationManager didUpdateLocationsは、デバイスで2回起動し、シミュレーターで1回だけ起動します

同じコードで、startUpdatingLocation()を1回だけ呼び出し、didUpdateLocations内でstopUpdatingLocations()を実行したにもかかわらず、デバイスが何らかの理由で実際に場所を2回更新していると想定しています。

func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    manager.stopUpdatingLocation()
    let loc: CLLocation = locations[locations.count - 1]
    let id = 0
    let type = 0
    let number = 0

    createNewDataPoint(id, loc: loc, type: type, number: number)
}

この場合、createNewDataPointは2回呼び出され、2つの新しいデータポイントが作成されます。シミュレーターで一度だけ発生するので、シミュレーターがその位置を偽造しているので、実際のデバイスとGPSに関係があると思います。

startUpdatingLocation()は、私のコードのボタンに1回だけあります。基本的に、ボタンをクリックして、manager.startUpdatingLocations()に移動し、didUpdateLocationsはシミュレーターで1回、デバイス(同一座標)で2回ヒットし、2つの新しいデータポイントを作成します。

関連するものについて言及している他のコードは、精度、フィルター、承認要求、および前述のstartUpdatingLocation()の設定だけです。必要な数の2倍のデータポイントを作成しないようにするためにできることはありますか?

13
sdouble

Location Managerのデリゲートメソッドは、非常に頻繁にいつでも呼び出すことができます。

ただし、次のアルゴリズムを適用して自分自身を保護することができます。

  1. グローバルbool say didFindLocationを作成します。
  2. didFindLocationを呼び出すときは、falsestartUpdatingLocationに設定します。
  3. 内部デリゲートコールバックdidUpdateLocations:didFindLocationfalseの場合、didFindLocationtrueに設定してから、stopUpdatingLocationを呼び出します。

お役に立てれば。

17
Abhinav

最善の方法は次のようにすることです。

func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    manager.stopUpdatingLocation()
    manager.delegate = nil
}
12
Andrey M.

IOS10.0以降に最適なソリューション

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations {
    [locationManager stopUpdatingLocation]; // stop location manager
    locationManager.delegate = nil;
    //Your logics... 
    //This will be called only one time now.
}

ただし、デリゲートを再度設定することを忘れないでください。

6
Zumry Mohamed

@ZumryMohamedのソリューションは正しい

私はこのようなコードを試します:

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {

   [self.locationManager stopUpdatingLocation];
   self.locationManager.delegate = nil;
   self.locationManager = nil; 
}

最後に、このデリゲートは1回だけ呼び出されます。マネージャーがstopUpdatingLocationmethodを呼び出したからといって、問題が発生した理由がわかりましたが、システムはデリゲートを無効にするのに役立たないため、場所ごとにコールバックを受け取ることができます。 desiredAccuracydistanceFilterおよびCLLocationManagerプロパティ設定による更新。したがって、最終的な解決策は@Zumry Mohamedが言ったのと同じであり、デリゲートを手動でnilに設定できます。私たちはstopUpdateLocation。これが問題を解決できる理由を理解するのに役立つことを願っています。

0
SevenJustin

シミュレーターに頻繁に乗ることはありません。そして、あなたが遠くに移動するとき、あなただけがdidUpdateLocationsを得るデバイス上で。オープンスペースを移動するだけで、GPSがデバイスの位置を識別できるため、最高の精度が得られます。

0
kalpesh

場所の更新を開始/終了してデリゲートをnilに設定する代わりに、 requestLocation というメソッドがあります。これは、アプリケーションでユーザーの場所をすばやく修正する必要がある場合に最適です。

ドキュメントから:

override func viewDidLoad() {
    // Create a location manager object
    self.locationManager = CLLocationManager()

    // Set the delegate
    self.locationManager.delegate = self
}

func getQuickLocationUpdate() {
    // Request location authorization
    self.locationManager.requestWhenInUseAuthorization()

    // Request a location update
    self.locationManager.requestLocation()
    // Note: requestLocation may timeout and produce an error if authorization has not yet been granted by the user
}

func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    // Process the received location update
}

この方法は、ユーザーの現在の場所が必要であるが、位置情報サービスを実行したままにする必要がない場合に使用します。

0
Whirlwind

locationManager.startUpdatingLocation()は場所を継続的にフェッチし、didUpdateLocationsメソッドは数回呼び出します。locationManager.startUpdatingLocation()を呼び出す前に、locationManager.distanceFilter値の値を設定するだけです。

私は200メートルを設定したので(あなたの要件に応じて変更できます)正常に動作します

    locationManager = CLLocationManager()
    locationManager.delegate = self
    locationManager.desiredAccuracy = kCLLocationAccuracyBest
    locationManager.distanceFilter = 200
    locationManager.requestWhenInUseAuthorization()
    locationManager.startUpdatingLocation()
0
Devendra Singh

目的の緯度と経度を取得したら、stopUpdatingLocation()を呼び出し、デリゲートをnilに設定します。

In Swift 3:

locationManager.stopUpdatingLocation() 
locationManager.delegate = nil

Objective-Cの場合:

[locationManager stopUpdatingLocation]
locationManager.delegate = nil

ここで、locationManagerCLLocationManagerのオブジェクトです。

0
iOSAnup