2011-02-17 12 views
6

Chciałbym śledzić niebieską kropkę użytkownika w taki sam sposób, jak robią to Mapy Google. Oznacza to, że gdy lokalizacja się zmienia, mapa (lub jej środek) powinna płynnie podążać za nią. Ale gdy używam standardowego sposobu z delegatem:Płynna obserwacja lokalizacji użytkownika w MKMapView

- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation 
{ 
    [map setCenterCoordinate:map.userLocation.coordinate animated:YES]; 
} 

lub keyvalue obserwatora na mapview.userLocation następnie przenieść na mapie jest dość „niepewny”, to szybko „przeskakuje” do nowej lokalizacji, nawet jeśli używam animated parametr.

Ponadto uważam, że sama niebieska kropka nie porusza się tak płynnie, jak w natywnej aplikacji Google Maps i często przeskakuje do nowej lokalizacji zamiast tam się poruszać.

Dzięki za pomoc.

+0

iOS 5 dodaje tę funkcję w trybie śledzenia. Wreszcie! – d0n13

Odpowiedz

3

„hi Jak

Próbowałem rozwiązać to jak dobrze, ale wygląda na to, MKMapView może być za pomocą wymyślnej rzeczy między aktualizacjach przewidzieć następną pozycję, a ruch gładsza.

Jeśli patrzysz na sposób, w jaki obsługują kompas, robią dużo filtrowania, ponieważ surowe dane kompasu nie są strasznie stabilne, dzięki czemu są naprawdę śliskie i gładkie.

Należy również zauważyć, że podczas śledzenia można powiększać, ale nie przesuwać. Nie udało mi się zreplikować tej funkcji w mojej aplikacji, nawet jeśli przewijanie jest wyłączone, nadal przewija się podczas powiększania, jeśli przesuniesz palce.

Chyba nie narażać wszystko, żeby zachować przed nami :) D

+0

Cóż, doszedłem do tego samego wniosku. ; o) Aplikacja Mapy musi używać prywatnych metod, których nie możemy. Próbowałem również wstawić 'setCenterCoordinate: animated:' do animacji UIView, ale bez efektu. – JakubM

0

Można też spróbować:

- (void)adjustRegion:(CLLocation*)location { 
    MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance(location.coordinate, 150.0, 150.0); 
    MKCoordinateRegion adjustedRegion = [self.mapView regionThatFits:viewRegion]; 
    [self.mapView setRegion:adjustedRegion animated:YES]; 
} 
+0

co to jest "CMModel"? – Raptor

+1

@ShivanRaptor Oh, to jest klasa singletona, w której zapisałem kilka paramów. Właśnie skopiowałem i wkleiłem tę linię. Sry, będę edytować moją odpowiedź. – borisdiakur

+0

@Lego nie zmusza użytkownika do użycia zdefiniowanego poziomu powiększenia?(Zamiast pozwolić im je definiować) – RonLugge

1

użyłem metody aktualizacji delegat CLLocationManager aby uzyskać prąd lokalizacja co sekundę, zapisana poprzednia lokalizacja i interpolowana między nimi. To trochę więcej wysiłku, ale t sprawia, że ​​śledzenie jest dużo bardziej płynne. Tu jest mój kodu:

#define zoomSpan MKCoordinateSpanMake(0.001f, 0.001f) 

@property (strong, nonatomic) CLLocation *lastLocation; 
@property (strong, nonatomic) MKMapView *mapView; 
@property (strong, nonatomic) CLLocationManager *locationManager; 

... 

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations 
{ 
    CLLocation *currentLocation = locations[locations.count - 1]; 
    // Set to last location, for faster setting to correct position 
    [self.mapView setRegion:MKCoordinateRegionMake(self.lastLocation.coordinate, zoomSpan) animated:NO]; 

    // Locations in-between coordinates for smooth tracking 
    CLLocationDegrees deltaLat = currentLocation.coordinate.latitude - self.lastLocation.coordinate.latitude; 
    CLLocationDegrees deltaLon = currentLocation.coordinate.longitude - self.lastLocation.coordinate.longitude; 
    NSArray *locationsArray = @[[[CLLocation alloc] initWithLatitude:(self.lastLocation.coordinate.latitude + deltaLat * 0.2) 
                  longitude:(self.lastLocation.coordinate.longitude + deltaLon * 0.2)], 
           [[CLLocation alloc] initWithLatitude:(self.lastLocation.coordinate.latitude + deltaLat * 0.4) 
                  longitude:(self.lastLocation.coordinate.longitude + deltaLon * 0.4)], 
           [[CLLocation alloc] initWithLatitude:(self.lastLocation.coordinate.latitude + deltaLat * 0.6) 
                  longitude:(self.lastLocation.coordinate.longitude + deltaLon * 0.6)], 
           [[CLLocation alloc] initWithLatitude:(self.lastLocation.coordinate.latitude + deltaLat * 0.8) 
                  longitude:(self.lastLocation.coordinate.longitude + deltaLon * 0.8)], 
           currentLocation]; 

    float timer = 0; 
    for (CLLocation *nextLocation in locationsArray) { 
     [self performSelector:@selector(updateMapCenterLocation:) withObject:nextLocation afterDelay:timer]; 
     timer += 0.2; 
    } 
    self.lastLocation = currentLocation; 
} 

- (void)updateMapCenterLocation:(CLLocation *)location 
{ 
    [self.mapView setRegion:MKCoordinateRegionMake(location.coordinate, zoomSpan) animated:YES]; 
} 

Upewnij się, że klasa używasz tego w (zazwyczaj kontroler widoku, który uważa, MAP) jest ustawiony na delegata i wdrożenie protokołu CLLocationManagerDelegateCLLocationManager „s.

Niektóre dodatkowe komentarze:

  • Zachowanie tej kod jest podobny do MKUserTracking, ale ten nie obsługuje niestandardowy zestaw poziomów powiększenia. Wygląda na to, że błąd resetuje poziom powiększenia podczas uruchamiania śledzenia, a zatem obejście tego problemu.
  • zoomSpan jest obecnie naprawiony, ale można również użyć zakresu bieżącego regionu z self.mapView.region.span.
Powiązane problemy