2009-09-17 15 views
19

Moja aplikacja zna aktualną pozycję użytkownika (CoreLocation.framework). Gdy tylko użytkownik otworzy nowy MapView, jego iPhone ponownie rozpoczyna szukanie aktualnej pozycji. Czy można go pominąć lub zmienić pierwszą pozycję użytkownika dla mkMapView?Jak zainicjować MKMapView z określoną lokalizacją użytkownika?

Edit:

Czy możliwe jest zastąpienie MKMapView i użyć innego LocationManager?

Odpowiedz

42

Tak, możliwe jest posiadanie oddzielnego obiektu zarządzania lokalizacjami i przypisanie jego wartości do widoku mapy (BTW, używam "=" poniżej jako prefiksu listy, aby zapobiec borkowaniu formaterów kodu SO).

= W swojej UIViewController zachowaj dwie oddzielne właściwości: jedną na MKMapView i jedną na CLLocationManager.

= Utwórz plik XIB za pomocą MKMapView i dowolnego innego żądanego okna. Połącz gniazda z propetami kontrolera. Upewnij się, że MKMapView NIE podąża za lokalizacją użytkownika.

= Niech kontroler UIViewController implementuje protokół CLLocationManagerDelegate - szczególnie metodę locationManager:didUpdateToLocation:fromLocation:, która będzie wywoływana za każdym razem, gdy dostępna będzie nowa wartość lokalizacji. Ustawimy kontroler jako delegata dla menedżera lokalizacji.

= W metodzie viewController's loadView załaduj NIB z MKMapView w nim. Aby przekazać opinię użytkownika, możesz ustawić pokrętło UIActivityIndicatorView i ustawić je na startAnimating. Następnie zacząć:

self.locationManager = [[CLLocationManager alloc] init]; 
self.locationManager.delegate = self; 
self.locationManager.desiredAccuracy = kCLLocationAccuracyKilometer; 
self.locationManager.distanceFilter = 10; // or whatever 
[self.locationManager startUpdatingLocation]; 

= W locationManager:didUpdateToLocation:fromLocation: sprawdzić, czy zdarzenie zostało zaktualizowane od ostatnich N sekund.Następnie powiedz menadżerowi lokalizacji, aby przestał aktualizować, spinner przestał animować i uzyskał dane długie/długie i przypisać je do widoku mapy wraz z zasięgiem widoku i regionem, aby powiększyć i wyśrodkować w odpowiednie miejsce.

= Teraz jest trudna część: niebieski marmurowy "throbber" jest cechą lokalizacji użytkownika śledzenia mapview. Będziesz musiał na chwilę "sfingować", dopóki prawdziwy kopniak (lub po prostu użyć oddzielnego znacznika dla bieżącej lokalizacji i zachować swoją pozycję samemu). Osobiście pójdę z niebieskim marmurem, który zna użytkownik.

= Aby było tak, aby był wyświetlany zaraz po uruchomieniu, musisz utworzyć niestandardowy widok MKAnnotationView z niebieską marmurową grafiką dodaną w lokalizacji zwróconej przez menedżera lokalizacji. Oznacza to zrobienie migawki mapy z widoczną lokalizacją, a następnie zdjęcie tylko niebieskiego marmuru i użycie go jako obrazu dla niestandardowego widoku adnotacji.

= Jeśli chcesz aktywnie podążać za mapą, możesz włączyć śledzenie lokalizacji użytkownika w widoku mapy, a gdy pobierze on rzeczywiste dane, ukryjesz uprzednio ustawiony znacznik i zezwolisz widokowi mapy na aktualizację. Drugą opcją jest umożliwienie istniejącemu menedżerowi lokalizacji ciągłego otrzymywania aktualizacji co sekundę i aktualizowanie pozycji niebieskiej adnotacji z marmuru.

= pozwolić MapView własnej userLocation zrobić aktualizację dodać do viewDidLoad:

[self.map.userLocation addObserver:self 
forKeyPath:@"location" 
options:(NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld) 
context:NULL]; 
self.map.showsUserLocation = YES; // starts updating user location 

= Wdrożenie observeValueForKeyPath. To jest wywoływana gdy atrybut MapView na userlocationlocation ma wartość:

-(void)observeValueForKeyPath:(NSString *)keyPath 
     ofObject:(id)object 
     change:(NSDictionary *)change 
     context:(void *)context 
{ 
    if ([self.map isUserLocationVisible]) { 
     [self.locationManager stopUpdatingLocation]; 
     self.ownBlueMarble.hidden = YES; 
    } 
    // The current location is in self.map.userLocation.coordinate 
} 

= Aby uniknąć nagrzewania opóźnienie pokazujący aktualną lokalizację, zachować odniesienie do viewController zawierający mapę i kierownik lokalizacji, tak to nie odejdzie (to jest trochę pamięci, ale jeśli ją zwolnisz, będziesz musiał poczekać, aż MapView załaduje płytki i będzie gotowy do pracy).

= W viewWillLoad możesz umieścić ostatnie znane miejsce w niestandardowej adnotacji bluemarble i pokazać to. Włącz/wyłącz śledzenie lokalizacji użytkownika, a gdy otrzymasz powiadomienie, będzie działać ta sama sztuczka z ukrytymi komentarzami. Zostaje uruchomiony menedżer lokalizacji, który przegląda mapę, a kiedy ma dane, możesz zlikwidować znacznik adnotacji.

= Możesz zaimplementować metodę viewController's viewWillDisappear i ręcznie wyłączyć śledzenie userLocation w widoku mapy, aby domyślnie wyłączyć się przy następnym wyświetleniu widoku. Będziesz także chciał uzyskać ostatni znany userLocation i zapisać go do następnego uruchomienia. W ten sposób możesz wykonać wszystkie żonglerki znaczników pozycjonowania w metodzie viewWillAppear i nie musisz się martwić o ingerencję UserLocation, dopóki nie będziesz na to gotowy.

Powodzenia.

+1

Dzięki Ramin. Nie jest to oczekiwane rozwiązanie, ale myślę, że jest najbliższy istniejący. – jantimon

+0

Tak, byłoby o wiele łatwiej, gdyby pozwoliły nam ustawić userLocation na widok mapy na wartość początkową ... lub jeszcze lepiej zezwolić na użycie istniejącej instancji klasy CLLocationManager zamiast tworzyć własne ... ale niestety nie t. – Ramin

27

W kontrolerze:

- (void)viewWillAppear:(BOOL)animated { 
    [super viewWillAppear:animated]; 
    CLLocationCoordinate2D coord = {latitude: 37.423617, longitude: -122.220154}; 
    MKCoordinateSpan span = {latitudeDelta: 1, longitudeDelta: 1}; 
    MKCoordinateRegion region = {coord, span}; 
    [mapView setRegion:region]; 
} 

Kiedy pojawia się mapa to będzie się koncentrować w pobliżu Palo Alto

+0

to nie jest to, czego potrzebuję. Chcę zmienić pozycję niebieskiego wskaźnika położenia ("aktualna lokalizacja"). – jantimon

+1

userLocation jest właściwością readonly, wątpię, czy możesz coś z tym zrobić. Jedynym legalnym sposobem jest wyłączenie niebieskiego wskaźnika, który Apple dostarcza i pisze, co jest bezsensowne. – zakovyrya

+1

Ustaw region 500m x 500 m [mapView setRegion: MKCoordinateRegionMakeWithDistance (CLLocationCoordinate2DMake (54.233498f, 1.99375f), 500, 500) ]; –

0

Spróbuj ustawić właściwość showUserLocation false na inicjalizacji, a następnie przywrócić region widok mapy poprzednio miał (oczywiście będziesz musiał to zapisać, zanim zniszczona zostanie poprzednia mapa).

Czy tego właśnie chcesz?

+0

nie chodzi o region, ale o wskaźnik pozycji – jantimon

0

Nie musisz używać innego Menedżera lokalizacji, możesz dodawać do mapy dowolne punkty i aktualizować je za pomocą dowolnej innej logiki.

Załóżmy, że masz połączenie z gniazdem do samochodu zdalnie sterowanego, a ten samochód odsyła dane z gniazda zawierające dane geolokalizacyjne w polu danych. Możesz je przeanalizować i zaktualizować położenie miniatury na mapie w czasie rzeczywistym. Właściwość "userLocation" nie jest do tego potrzebna, ale możesz ją wyświetlić, jeśli chcesz.

Lokalizacja użytkownika jest tylko do odczytu, możesz go użyć lub nie. Nie oznacza to, że potrzebujesz innego menedżera lokalizacji, aby zrobił cokolwiek, co musisz zrobić. Wygląda na to, że Twoja aplikacja naprawdę nie potrzebuje tej funkcji, ale mógłbym nie zrozumieć twojego pytania.

+0

Chodzi o to, że pozycja użytkownika nie jest wyświetlana lub jest wyświetlana nieprawidłowo przez pierwsze 10 sekund, gdy wyświetlany jest nowy widok MKMapView. Po tych 10 sekundach wszystko jest w porządku. Jednak jak znam pozycję, chciałbym pominąć te 10 sekund. – jantimon

+1

może stary, ale jeśli ktoś to przeczyta, powinien uzyskać lokalizację użytkownika podczas uruchamiania aplikacji, która uruchomi GPS, aby zlokalizować użytkownika. W ten sposób do czasu, gdy użytkownik otworzy mapę, już się znajduje. pS: to normalne przez 10 sekund, nawet aplikacja mapy google zajmuje kilka sekund po włączeniu lokalizacji – renevdkooi

Powiązane problemy