同じコードで、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倍のデータポイントを作成しないようにするためにできることはありますか?
Location Managerのデリゲートメソッドは、非常に頻繁にいつでも呼び出すことができます。
ただし、次のアルゴリズムを適用して自分自身を保護することができます。
bool
say didFindLocation
を作成します。didFindLocation
を呼び出すときは、false
をstartUpdatingLocation
に設定します。didUpdateLocations:
、didFindLocation
がfalse
の場合、didFindLocation
をtrue
に設定してから、stopUpdatingLocation
を呼び出します。お役に立てれば。
最善の方法は次のようにすることです。
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
manager.stopUpdatingLocation()
manager.delegate = nil
}
- (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.
}
ただし、デリゲートを再度設定することを忘れないでください。
@ZumryMohamedのソリューションは正しい
私はこのようなコードを試します:
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
[self.locationManager stopUpdatingLocation];
self.locationManager.delegate = nil;
self.locationManager = nil;
}
最後に、このデリゲートは1回だけ呼び出されます。マネージャーがstopUpdatingLocation
methodを呼び出したからといって、問題が発生した理由がわかりましたが、システムはデリゲートを無効にするのに役立たないため、場所ごとにコールバックを受け取ることができます。 desiredAccuracy
のdistanceFilter
およびCLLocationManager
プロパティ設定による更新。したがって、最終的な解決策は@Zumry Mohamedが言ったのと同じであり、デリゲートを手動でnilに設定できます。私たちはstopUpdateLocation
。これが問題を解決できる理由を理解するのに役立つことを願っています。
シミュレーターに頻繁に乗ることはありません。そして、あなたが遠くに移動するとき、あなただけがdidUpdateLocations
を得るデバイス上で。オープンスペースを移動するだけで、GPSがデバイスの位置を識別できるため、最高の精度が得られます。
場所の更新を開始/終了してデリゲートを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
}
この方法は、ユーザーの現在の場所が必要であるが、位置情報サービスを実行したままにする必要がない場合に使用します。
locationManager.startUpdatingLocation()は場所を継続的にフェッチし、didUpdateLocationsメソッドは数回呼び出します。locationManager.startUpdatingLocation()を呼び出す前に、locationManager.distanceFilter値の値を設定するだけです。
私は200メートルを設定したので(あなたの要件に応じて変更できます)正常に動作します
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.distanceFilter = 200
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
目的の緯度と経度を取得したら、stopUpdatingLocation()
を呼び出し、デリゲートをnil
に設定します。
In Swift 3:
locationManager.stopUpdatingLocation()
locationManager.delegate = nil
Objective-Cの場合:
[locationManager stopUpdatingLocation]
locationManager.delegate = nil
ここで、locationManager
はCLLocationManager
のオブジェクトです。