Szukaj…
Dodaj MKMapView
Szybki
let mapView = MKMapView(frame: CGRect(x: 0, y: 0, width: 320, height: 500))
Zaleca się przechowywać mapView jako właściwość zawierającego ViewController
ponieważ możesz chcieć uzyskać do niego dostęp w bardziej złożonych implementacjach.
Cel C
self.map = [[MKMapView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
[self.view addSubview:self.map];
Zmień typ mapy
Istnieje 5 różnych typów ( MKMapType
), MKMapView
może wyświetlać MKMapView
.
.satelliteFlyover
Wyświetla zdjęcie satelitarne obszaru z danymi estakady, jeśli są dostępne.
Swift 2
mapView.mapType = .SatelliteFlyover
Szybki 3
mapView.mapType = .satelliteFlyover
Cel C
_mapView.mapType = MKMapTypeSatelliteFlyover;
.hybridFlyover
Wyświetla hybrydowy obraz satelitarny z danymi estakady, jeśli są dostępne.
Swift 2
mapView.mapType = .HybridFlyover
Szybki 3
mapView.mapType = .hybridFlyover
Cel C
_mapView.mapType = MKMapTypeHybridFlyover;
Ustaw Zoom / Region dla mapy
Aby ustawić poziom powiększenia, powiedzmy, że chcemy powiększyć lokalizację użytkownika z lokalizacją użytkownika jako centrum i 2 km obszaru jako promieniem. Następnie używamy następującego kodu
MKUserLocation *userLocation = _mapView.userLocation;
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance (userLocation.location.coordinate, 2000, 2000);
[_mapView setRegion:region animated:NO];
Lokalna implementacja wyszukiwania przy użyciu MKLocalSearch
MKLocalSearch umożliwia użytkownikom wyszukiwanie lokalizacji przy użyciu ciągów języka naturalnego, takich jak „siłownia”. Po zakończeniu wyszukiwania klasa zwraca listę lokalizacji w określonym regionie pasujących do wyszukiwanego ciągu.
Wyniki wyszukiwania mają postać MKMapItem w obiekcie MKLocalSearchResponse.
spróbujmy przez przykład
MKLocalSearchRequest *request =
[[MKLocalSearchRequest alloc] init];//initialising search request
request.naturalLanguageQuery = @”Gym”; // adding query
request.region = _mapView.region; //setting region
MKLocalSearch *search =
[[MKLocalSearch alloc]initWithRequest:request];//initiate search
[search startWithCompletionHandler:^(MKLocalSearchResponse
*response, NSError *error)
{
if (response.mapItems.count == 0)
NSLog(@"No Matches");
else
for (MKMapItem *item in response.mapItems)
{
NSLog(@"name = %@", item.name);
NSLog(@"Phone = %@", item.phoneNumber);
}
}];
OpenStreetMap nakładka kafelkowa
W niektórych przypadkach możesz nie chcieć używać domyślnych map, zapewnia Apple.
Możesz dodać do mapView
która zawiera niestandardowe kafelki, na przykład z OpenStreetMap .
Załóżmy, że self.mapView
to twój MKMapView
, który już dodałeś do swojego ViewController
.
Najpierw ViewController
musi być zgodny z protokołem MKMapViewDelegate
.
class MyViewController: UIViewController, MKMapViewDelegate
Następnie musisz ustawić ViewController
jako delegata mapView
mapView.delegate = self
Następnie skonfigurujesz nakładkę dla mapy. W tym celu potrzebujesz szablonu adresu URL. Adres URL powinien być podobny do tego na wszystkich serwerach kafelków, a nawet gdyby dane map były przechowywane offline: http://tile.openstreetmap.org/{z}/{x}/{y}.png
let urlTeplate = "http://tile.openstreetmap.org/{z}/{x}/{y}.png"
let overlay = MKTileOverlay(urlTemplate: urlTeplate)
overlay.canReplaceMapContent = true
Po skonfigurowaniu nakładki musisz dodać ją do mapView
.
mapView.add(overlay, level: .aboveLabels)
Aby użyć niestandardowych map, zaleca się użycie .aboveLabels
dla level
. W przeciwnym razie domyślne etykiety byłyby widoczne na Twojej mapie niestandardowej. Jeśli chcesz zobaczyć domyślne etykiety, możesz wybrać .aboveRoads
tutaj.
Gdybyś teraz uruchomił swój projekt, rozpoznałbyś, że twoja mapa nadal pokazuje domyślną mapę:
To dlatego, że nie powiedzieliśmy jeszcze mapView
, jak renderować nakładkę. To jest powód, dla którego musiałeś wcześniej ustawić delegata. Teraz możesz dodać func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer
do kontrolera widoku:
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
if overlay is MKTileOverlay {
let renderer = MKTileOverlayRenderer(overlay: overlay)
return renderer
} else {
return MKTileOverlayRenderer()
}
}
Spowoduje to zwrócenie prawidłowego MKOverlayRenderer
do mapView
. Jeśli teraz uruchomisz projekt, powinieneś zobaczyć mapę taką jak ta:
Jeśli chcesz wyświetlić inną mapę, wystarczy zmienić szablon adresu URL. Na Wiki OSM znajduje się lista serwerów kafelków .
Pokaż przykład UserLocation i UserTracking
Spowoduje to wyświetlenie lokalizacji użytkownika na mapie
Cel C
[self.map setShowsUserLocation:YES];
Szybki
self.map?.showsUserLocation = true
Będzie to śledzić lokalizację użytkownika na mapie, aktualizując regiony zgodnie
Cel C
[self.map setUserTrackingMode:MKUserTrackingModeFollow];
Szybki
self.map?.userTrackingMode = .follow
Dodawanie opisu pin / point na mapie
Aby dodać adnotację do jakiegoś interesującego miejsca na mapie, używamy adnotacji pinezką. Teraz zacznij od utworzenia obiektu adnotacji w pierwszej kolejności.
MKPointAnnotation *pointAnnotation = [[MKPointAnnotation alloc] init];
Teraz podaj współrzędną do pointAnnotation, as
CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(23.054625,72.534562);
pointAnnotation.coordinate = coordinate;
Teraz podaj tytuł i podtytuły adnotacji,
pointAnnotation.title = @"XYZ Point";
pointAnnotation.subtitle = @"Ahmedabad Area";
Dodaj tę adnotację do mapy.
[self.mapView addAnnotation:pointAnnotation];
Tak .. Hurra ... wykonałeś robotę. Teraz możesz zobaczyć adnotację punktową (czerwona szpilka) na danej współrzędnej.
Ale teraz, co jeśli chcesz zmienić kolor pinezki (3 dostępne kolory to - Fioletowy, czerwony i zielony). Następnie wykonaj ten krok.
ustaw delegata mapview na siebie,
self.mapView.delegate = self;
Dodaj implementację MKMapViewDelegate. Teraz dodaj następującą metodę,
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
// If it's the user location, just return nil, because it have user location's own annotation, if you want to change that, then use this object;
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
if ([annotation isKindOfClass:[MKPointAnnotation class]])
{
//Use dequed pin if available
MKAnnotationView *pinView = [mapView dequeueReusableAnnotationViewWithIdentifier:@"PinAnnotationView"];
if (!pinView)
{
// If not dequed, then create new.
pinView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"PinAnnotationView"];
pinView.canShowCallout = YES;
pinView.image = [UIImage imageNamed:@"abc.png"];
pinView.calloutOffset = CGPointMake(0, 32);
} else {
pinView.annotation = annotation;
}
return pinView;
}
return nil;
}
Symuluj niestandardową lokalizację
Krok 1: W Xcode: Plik -> Nowy -> Plik -> Zasób -> Plik GPX -> Dalej -> Nadaj nazwę plikowi GPX (w tym przykładzie jest to Taipei
) -> Utwórz
Krok 2: Edytuj plik GPX
<?xml version="1.0"?>
<gpx version="1.1" creator="Xcode">
<wpt lat="25.041865" lon="121.551361"> // Edit the latitude and longitude
<name>Taipei</name> // Edit the name of the location
<time>2014-09-24T14:55:37Z</time>
</wpt>
</gpx>
Krok 3: Gdy symulator jest uruchomiony:
Możesz powtórzyć ten proces, aby utworzyć wiele lokalizacji.
Przewiń do współrzędnych i poziomu powiększenia
Kiedy wyświetlasz lokalizację użytkownikom, możesz chcieć, aby MKMapView
wyświetlał współrzędną na poziomie powiększenia zamiast ustawiać region do pokazywania. Ta funkcja nie jest domyślnie implementowana, dlatego należy rozszerzyć MKMapView
o metody, które wykonują złożone obliczenia od współrzędnej i poziomu powiększenia do MKCoordinateRegion
.
let MERCATOR_OFFSET = 268435456.0
let MERCATOR_RADIUS = 85445659.44705395
let DEGREES = 180.0
public extension MKMapView {
//MARK: Map Conversion Methods
private func longitudeToPixelSpaceX(longitude:Double)->Double{
return round(MERCATOR_OFFSET + MERCATOR_RADIUS * longitude * M_PI / DEGREES)
}
private func latitudeToPixelSpaceY(latitude:Double)->Double{
return round(MERCATOR_OFFSET - MERCATOR_RADIUS * log((1 + sin(latitude * M_PI / DEGREES)) / (1 - sin(latitude * M_PI / DEGREES))) / 2.0)
}
private func pixelSpaceXToLongitude(pixelX:Double)->Double{
return ((round(pixelX) - MERCATOR_OFFSET) / MERCATOR_RADIUS) * DEGREES / M_PI
}
private func pixelSpaceYToLatitude(pixelY:Double)->Double{
return (M_PI / 2.0 - 2.0 * atan(exp((round(pixelY) - MERCATOR_OFFSET) / MERCATOR_RADIUS))) * DEGREES / M_PI
}
private func coordinateSpanWithCenterCoordinate(centerCoordinate:CLLocationCoordinate2D, zoomLevel:Double)->MKCoordinateSpan{
// convert center coordiate to pixel space
let centerPixelX = longitudeToPixelSpaceX(longitude: centerCoordinate.longitude)
let centerPixelY = latitudeToPixelSpaceY(latitude: centerCoordinate.latitude)
print(centerCoordinate)
// determine the scale value from the zoom level
let zoomExponent:Double = 20.0 - zoomLevel
let zoomScale:Double = pow(2.0, zoomExponent)
// scale the map’s size in pixel space
let mapSizeInPixels = self.bounds.size
let scaledMapWidth = Double(mapSizeInPixels.width) * zoomScale
let scaledMapHeight = Double(mapSizeInPixels.height) * zoomScale
// figure out the position of the top-left pixel
let topLeftPixelX = centerPixelX - (scaledMapWidth / 2.0)
let topLeftPixelY = centerPixelY - (scaledMapHeight / 2.0)
// find delta between left and right longitudes
let minLng = pixelSpaceXToLongitude(pixelX: topLeftPixelX)
let maxLng = pixelSpaceXToLongitude(pixelX: topLeftPixelX + scaledMapWidth)
let longitudeDelta = maxLng - minLng
let minLat = pixelSpaceYToLatitude(pixelY: topLeftPixelY)
let maxLat = pixelSpaceYToLatitude(pixelY: topLeftPixelY + scaledMapHeight)
let latitudeDelta = -1.0 * (maxLat - minLat)
return MKCoordinateSpan(latitudeDelta: latitudeDelta, longitudeDelta: longitudeDelta)
}
/**
Sets the center of the `MKMapView` to a `CLLocationCoordinate2D` with a custom zoom-level. There is no nee to set a region manually. :-)
- author: Mylene Bayan (on GitHub)
*/
public func setCenter(_ coordinate:CLLocationCoordinate2D, zoomLevel:Double, animated:Bool){
// clamp large numbers to 28
var zoomLevel = zoomLevel
zoomLevel = min(zoomLevel, 28)
// use the zoom level to compute the region
print(coordinate)
let span = self.coordinateSpanWithCenterCoordinate(centerCoordinate: coordinate, zoomLevel: zoomLevel)
let region = MKCoordinateRegionMake(coordinate, span)
if region.center.longitude == -180.00000000{
print("Invalid Region")
}
else{
self.setRegion(region, animated: animated)
}
}
}
(Oryginalną wersję Swift 2 autorstwa Mylene Bayan można znaleźć na GitHub )
Po zaimplementowaniu tego extension
możesz ustawić współrzędną środkową w następujący sposób:
let centerCoordinate = CLLocationCoordinate2DMake(48.136315, 11.5752901) //latitude, longitude
mapView?.setCenter(centerCoordinate, zoomLevel: 15, animated: true)
zoomLevel
jest wartością Double
, zwykle pomiędzy 0
a 21
(co jest bardzo wysokim poziomem powiększenia), ale dopuszczalne są wartości do 28
.
Praca z adnotacjami
Uzyskaj wszystkie adnotacje
//following method returns all annotations object added on map
NSArray *allAnnotations = mapView.annotations;
Uzyskaj widok adnotacji
for (id<MKAnnotation> annotation in mapView.annotations)
{
MKAnnotationView* annotationView = [mapView viewForAnnotation:annotation];
if (annotationView)
{
// Do something with annotation view
// for e.g change image of annotation view
annotationView.image = [UIImage imageNamed:@"SelectedPin.png"];
}
}
Usuń wszystkie adnotacje
[mapView removeAnnotations:mapView.annotations]
Usuń pojedynczą adnotację
//getting all Annotation
NSArray *allAnnotations = self.myMapView.annotations;
if (allAnnotations.count > 0)
{
//getting first annoation
id <MKAnnotation> annotation=[allAnnotations firstObject];
//removing annotation
[mapView removeAnnotation:annotation];
}
Dostosuj widoczny prostokąt widoku mapy, aby wyświetlić wszystkie adnotacje
Szybki:
mapView.showAnnotations(mapView.annotations, animated: true)
Cel C:
[mapView showAnnotations:mapView.annotations animated:YES];
Próbny: