2015-05-17 18 views
8

Ich konnte nicht herausfinden, wie mit einem Szenario umzugehen, in dem das Telefon bereits in einer Region ist, wenn startMonitoringForRegion aufgerufen wird? Andere Fragen haben vorgeschlagen, requestStateForRegion innerhalb didStartMonitoringForRegion aufzurufen, dies ruft dann die Methode didDetermineState: forRegion: auf. So sieht der Code so etwas wie dieses:iOS Geofence, wie geht es beim Start der Überwachung in der Region?

- (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]; 
    } 
} 

Jetzt offensichtlich die Methode geofenceRegion mein eigenes ist und es funktioniert gut, und die Objekte enthält Dinge wie lat lange und Radius und dass alles in Ordnung so gut funktioniert, so dass nicht der Problem hier.

Wie auch immer, das Problem mit dem obigen Code ist, dass es funktioniert, wenn der Benutzer bereits in der Region ist, wenn es die Region zu ihrem Gerät hinzufügt (dh. DidEnterRegion ist fertig). Doch das Problem ist, dass das Verfahren didDetermineState: forRegion: wird auch nach dem Apfel jedes Mal eine der Randbereiche überqueren docs genannt wird:

Der Standort-Manager diese Methode aufruft, wann immer es ein Grenzübergang für eine Region ist. Sie ruft diese Methode zusätzlich zum Aufruf des locationManagers auf: didEnterRegion: und locationManager: didExitRegion: methods. Der Standortmanager ruft diese Methode auch als Reaktion auf einen Aufruf seiner requestStateForRegion: -Methode auf, die asynchron ausgeführt wird.

Jetzt dies, weil jedes Mal, wenn eine Region eingegeben wird, wird didEnterRegion automatisch aufgerufen, aber dann wird es wieder genannt, weil didDetermineState: forRegion: auch nach dem Apfel docs automatisch aufgerufen wird, und dies führt zu didEnterRegion wieder genannt wird, so ist die Region zweimal eingegeben, wenn ich es nur einmal eingeben möchte. Wie kann ich das vermeiden?

Danke für Ihre Hilfe.

SOLUTION

Die Lösung wirklich so einfach ist, war ich, wenn ich nur gehen in die falsche Richtung. Ich musste wählen, entweder die 2 Methoden didEnterRegion: und didExitRegion zu verwenden oder didDetermineState: forRegion zu verwenden und meine eigenen Methoden für das Betreten und Verlassen der Region zu erstellen, beide sollten nicht verwendet werden.

So habe ich gewählt, nur die didDetermineState: forRegion Methode zu verwenden, und mein Code sieht nun wie folgt aus:

Bitte beachten Sie, dass mit diesem Austrittsbereich Methode wird für die Region genannt werden, wenn nicht innerhalb und wenn, wie ich, Sie möchten nur, dass der Exit nach einer Eingabe erfolgt. Sie müssen eine Art der Überprüfung durchführen, ob die Region bereits eingegeben wurde (ich habe selbst Core-Daten verwendet, da ich diese bereits verwendet habe, um andere Aspekte der Regionen zu speichern).

- (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 
} 
+0

Gegenstand dieser [Metapost] (https://meta.stackoverflow.com/q/262806/5175709). Es ist besser, die Antwort nicht in die Frage selbst aufzunehmen. Entweder schreibe eine separate Antwort oder akzeptiere einfach eine gegebene Antwort oder schreibe einen Kommentar. – Honey

Antwort

4

einfach nicht verwenden Locationmanager: didEnterRegion: überhaupt, wie Locationmanager: didDetermineState: forRegion: gibt Ihnen alle Informationen, die Sie benötigen, die On-Zugangscode zu triggern, die, nebenbei bemerkt , sollte nicht der locationManager: didEnterRegion: sein, verwenden Sie Ihren eigenen Selektor, der nicht Teil von CLLocationManagerDelegate Protokoll ist.

Ein anderer Ansatz besteht darin, innerhalb einer Regionsposition zu testen, wenn mit der Überwachung einer Region begonnen wird.Diese Lösung ist nicht so trivial wie es sich anhört: Sie müssen zuerst den aktuellen Standort aktualisieren, indem Sie startUpdatingLocation aufrufen, da nur das Lesen der Standorteigenschaft von locationManager Ihnen wahrscheinlich veraltetes oder extrem ungenaues Lesen liefert.

+0

Was ist der Punkt der API, wenn ich es selbst verfolgen muss? das scheint einfach nicht logisch zu sein? –

+0

Die API-Beschreibung besagt eindeutig, dass sie Eintritts- und Austrittsereignisse überwacht. Sie möchten mehr bekommen als die API, nämlich das Eintreten eines Ereignisses beim Starten der Überwachung aus einer Region heraus. Dafür gibt es einen API-Callback auf niedrigerer Ebene, den locationManager: didDetermineState: forRegion: und du kannst ihn verwenden, aber wenn du versuchst, ihn mit Dingen auf höherer Ebene zu kombinieren, fragst du nach einem Problem. –

+0

Aber wie ich in meiner Frage erwähnt habe, wird didDetermineState auch ausgelöst, wenn eine Region eingegeben oder beendet wird. Also was Sie sagen, ist, dass ich manuell den aktuellen Standort abrufen muss, wenn ich anfange, eine Region zu überwachen, und wenn dieser aktuelle Standort innerhalb der Region ist, handle ich es selbst. Ignorieren der requestStateForRegion ?. Ich spreche ich kann einfach nicht denken, was Sie sonst requestStateForRegion für verwenden würden, wenn keine Region Überwachung –