10

が呼び出されたときに電話がすでに地域内にあるシナリオを処理する方法を理解できませんでしたstartMonitoringForRegionか? 他の質問は、 thisrequestStateForRegion内で呼び出すことを提案してから、 method を呼び出します。したがって、コードは次のようになります。didStartMonitoringForRegiondidDetermineState: forRegion:

- (void)viewDidLoad {
    //location manager set up etc...
    for (Object *object in allObjects){

        CLRegion *region = [self geofenceRegion:object];
        [locationManager startMonitoringForRegion:region];
     }
}

- (void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(CLRegion *)region {

    [self.locationManager requestStateForRegion:region];
    [self.locationManager performSelector:@selector(requestStateForRegion:) withObject:region afterDelay:5];
 }

- (void)locationManager:(CLLocationManager *)manager
  didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region {

    if (state == CLRegionStateInside){
        [self locationManager:locationManager didEnterRegion:region];
    }  
}

明らかに、メソッド geofenceRegion は私自身のものであり、正常に動作し、オブジェクトには lat long や radius などのものが含まれており、すべて正常に動作するため、ここでは問題ありません。

とにかく、上記のコードの問題は、デバイスにリージョンを追加するときに、ユーザーがすでにリージョン内にいる場合に機能することです (つまり、didEnterRegion が実行されます)。ただし、問題はdidDetermineState: forRegion:、アップルのドキュメントに従って、境界領域の1つが交差するたびにメソッドも呼び出されることです。

ロケーション マネージャーは、リージョンの境界遷移があるたびにこのメソッドを呼び出します。locationManager:didEnterRegion: および locationManager:didExitRegion: メソッドの呼び出しに加えて、このメソッドを呼び出します。ロケーション マネージャーは、非同期で実行される requestStateForRegion: メソッドへの呼び出しに応答して、このメソッドも呼び出します。

これにより、リージョンが入力されるたびにdidEnterRegion自動的didDetermineState: forRegion:に呼び出されますが、アップルのドキュメントに従って自動的に呼び出されるdidEnterRegionため、再び呼び出されます。これにより、リージョンが2回入力されるだけです一度入った。どうすればこれを回避できますか?

ご協力いただきありがとうございます。

解決

解決策は本当に簡単なので、間違った方法で進めていました。didEnterRegion:2 つの方法を使用するか、領域に出入りするための独自の方法をdidExitRegion使用して作成するかを選択する必要がありましたが、両方を使用するべきではありませんdidDetermineState: forRegion

したがって、didDetermineState: forRegionメソッドのみを使用することを選択したため、コードは次のようになります。

このメソッドを使用すると、領域内にない場合は領域に対して exit 領域が呼び出されることに注意してください。私のように、領域に既に入っているかどうかを確認する何らかの方法が必要になります。 (私はすでにこれを使用してリージョンの他の側面を保存していたので、私自身はコアデータを使用しました)。

- (void)viewDidLoad {
    //location manager set up etc...
    for (Object *object in allObjects){

        CLRegion *region = [self geofenceRegion:object];
        [locationManager startMonitoringForRegion:region];
     }
}

- (void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(CLRegion *)region {

    [self.locationManager performSelector:@selector(requestStateForRegion:) withObject:region afterDelay:5];
}

- (void)locationManager:(CLLocationManager *)manager
  didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region {

    if (state == CLRegionStateInside){

        [self enterGeofence:region];

    } else if (state == CLRegionStateOutside){

        [self exitGeofence:region];

    } else if (state == CLRegionStateUnknown){
        NSLog(@"Unknown state for geofence: %@", region);
        return;
    }
}

- (void)enterGeofence:(CLRegion *)geofence {

    //whatever is required when entered
}

- (void)exitGeofence:(CLRegion *)geofence {

    //whatever is required when exit
}
4

1 に答える 1

6

locationManager:didEnterRegion:はまったく使用しないでください。 locationManager:didDetermineState:forRegion:は、エントリコードをトリガーするために必要なすべての情報を提供します。ちなみに、これはlocationManager:didEnterRegion:であってはなりません。 CLLocationManagerDelegateプロトコルの一部ではない独自のセレクター。

もう 1 つの方法は、リージョンの監視を開始するときに、リージョン内の場所をテストすることです。ただし、この解決策はそれほど簡単ではありません。最初にstartUpdatingLocationを呼び出して現在の場所を更新する必要があります。これは、locationManager の場所のプロパティを読み取るだけでは、おそらく古くなったり、非常に不正確な読み取りが行われる可能性があるためです。

于 2015-05-17T02:15:57.660 に答える