Suche…
MKMapView hinzufügen
Schnell
let mapView = MKMapView(frame: CGRect(x: 0, y: 0, width: 320, height: 500))
Es wird empfohlen, MapView als Eigenschaft des enthaltenen ViewController
zu speichern, da Sie in komplexeren Implementierungen darauf zugreifen möchten.
Ziel c
self.map = [[MKMapView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
[self.view addSubview:self.map];
Kartentyp ändern
Es gibt 5 verschiedene Typen ( MKMapType
), die MKMapView
anzeigen kann.
.satelliteFlyover
Zeigt ein Satellitenbild des Bereichs mit Überflugdaten an, sofern verfügbar.
Schnell 2
mapView.mapType = .SatelliteFlyover
Swift 3
mapView.mapType = .satelliteFlyover
Ziel c
_mapView.mapType = MKMapTypeSatelliteFlyover;
.hybridFlyover
Zeigt ein hybrides Satellitenbild mit Überflugdaten an, sofern verfügbar.
Schnell 2
mapView.mapType = .HybridFlyover
Swift 3
mapView.mapType = .hybridFlyover
Ziel c
_mapView.mapType = MKMapTypeHybridFlyover;
Stellen Sie Zoom / Region für die Karte ein
Wenn Sie eine Zoomstufe einstellen möchten, können Sie den Standort des Benutzers mit dem Standort des Benutzers als Zentrum und 2 km der Fläche als Radius vergrößern. Dann verwenden wir folgenden Code
MKUserLocation *userLocation = _mapView.userLocation;
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance (userLocation.location.coordinate, 2000, 2000);
[_mapView setRegion:region animated:NO];
Lokale Suchimplementierung mit MKLocalSearch
Mit MKLocalSearch können Benutzer nach Orten mit natürlichen Zeichenfolgen wie "Fitnessstudio" suchen. Sobald die Suche abgeschlossen ist, gibt die Klasse eine Liste von Orten innerhalb eines angegebenen Bereichs zurück, die der Suchzeichenfolge entsprechen.
Suchergebnisse sind in Form von MKMapItem innerhalb des MKLocalSearchResponse-Objekts.
Versuchen wir es mit Beispiel
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 Tile-Overlay
In einigen Fällen möchten Sie möglicherweise nicht die von Apple bereitgestellten Standardkarten verwenden.
Sie können Ihrer mapView
, die benutzerdefinierte Kacheln enthält, beispielsweise über OpenStreetMap eine Überlagerung hinzufügen.
Nehmen wir an, self.mapView
ist Ihre MKMapView
, die Sie bereits zu Ihrem ViewController
hinzugefügt ViewController
.
Zunächst muss Ihr ViewController
dem Protokoll MKMapViewDelegate
.
class MyViewController: UIViewController, MKMapViewDelegate
Dann muss der ViewController
als Delegierter von mapView
mapView.delegate = self
Als Nächstes konfigurieren Sie die Überlagerung für die Karte. Sie benötigen dazu eine URL-Vorlage. Die URL sollte auf allen Tile-Servern ähnlich sein und auch wenn Sie die Kartendaten offline speichern würden: 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
Nachdem Sie das Overlay konfiguriert haben, müssen Sie es zu Ihrer mapView
.
mapView.add(overlay, level: .aboveLabels)
Um benutzerdefinierte Karten zu verwenden, wird empfohlen, .aboveLabels
für level
. Andernfalls sind die Standardbeschriftungen auf Ihrer benutzerdefinierten Karte sichtbar. Wenn Sie die Standardbeschriftungen .aboveRoads
möchten, können .aboveRoads
hier .aboveRoads
auswählen.
Wenn Sie Ihr Projekt jetzt ausführen würden, würden Sie erkennen, dass Ihre Karte immer noch die Standardzuordnung anzeigen würde:
Das liegt daran, dass wir dem mapView
noch nicht gesagt mapView
, wie das Overlay mapView
. Dies ist der Grund, warum Sie den Delegierten zuvor einstellen mussten. Jetzt können Sie func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer
zu Ihrem View-Controller func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer
:
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
if overlay is MKTileOverlay {
let renderer = MKTileOverlayRenderer(overlay: overlay)
return renderer
} else {
return MKTileOverlayRenderer()
}
}
Dadurch wird der korrekte MKOverlayRenderer
an Ihre mapView
. Wenn Sie Ihr Projekt jetzt ausführen, sollten Sie eine Karte wie diese sehen:
Wenn Sie eine andere Karte anzeigen möchten, müssen Sie lediglich die URL-Vorlage ändern. Es gibt eine Liste von Tile-Servern im OSM-Wiki.
UserLocation und UserTracking-Beispiel anzeigen
Dadurch wird der Standort des Benutzers auf der Karte angezeigt
Ziel c
[self.map setShowsUserLocation:YES];
Schnell
self.map?.showsUserLocation = true
Dadurch wird der Standort des Benutzers auf der Karte verfolgt und die Regionen entsprechend aktualisiert
Ziel c
[self.map setUserTrackingMode:MKUserTrackingModeFollow];
Schnell
self.map?.userTrackingMode = .follow
Pin / Punkt-Anmerkung auf der Karte hinzufügen
Für das Annotieren eines interessanten Punktes auf der Karte verwenden wir die Pin-Annotation. Beginnen Sie mit dem Erstellen eines Anmerkungsobjekts.
MKPointAnnotation *pointAnnotation = [[MKPointAnnotation alloc] init];
Geben Sie jetzt die Koordinate für pointAnnotation als an
CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(23.054625,72.534562);
pointAnnotation.coordinate = coordinate;
Geben Sie nun den Titel und den Untertitel für die Anmerkung ein.
pointAnnotation.title = @"XYZ Point";
pointAnnotation.subtitle = @"Ahmedabad Area";
Fügen Sie diese Anmerkung jetzt zur Karte hinzu.
[self.mapView addAnnotation:pointAnnotation];
Yeaah .. Hurra .. Du hast die Arbeit erledigt. Sie können jetzt Punktannotation (rote Nadel) an der angegebenen Koordinate sehen.
Was aber, wenn Sie die Farbe des Pins ändern möchten (3 verfügbare Farben sind - Lila, Rot und Grün)? Dann folge diesem Schritt.
Setzen Sie den Delegierten von mapview auf sich selbst,
self.mapView.delegate = self;
Fügen Sie die MKMapViewDelegate-Implementierung hinzu. Fügen Sie nun folgende Methode hinzu,
- (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;
}
Simulieren Sie einen benutzerdefinierten Standort
Schritt 1: In Xcode: Datei -> Neu -> Datei -> Ressource -> GPX-Datei -> Weiter -> Geben Sie der GPX-Datei einen Namen (in diesem Beispiel Taipei
) -> Erstellen
Schritt 2: Bearbeiten Sie die GPX-Datei
<?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>
Schritt 3: Wenn der Simulator läuft:
Sie können diesen Vorgang wiederholen, um mehrere Standorte zu erstellen.
Blättern Sie zu Koordinate und Zoom-Ebene
Wenn Sie Ihren Benutzern einen Ort anzeigen, möchten Sie möglicherweise, dass MKMapView
eine Koordinate auf einer MKMapView
anzeigt, anstatt einen Bereich für die Anzeige MKMapView
. Diese Funktionalität ist nicht standardmäßig implementiert, so dass Sie erweitern müssen MKMapView
mit Methoden, die die komplexe Berechnung von einem Koordinaten und Zoom-Ebene zu einem tun 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)
}
}
}
(Die ursprüngliche Swift 2-Version von Mylene Bayan ist auf GitHub zu finden.)
Nachdem Sie diese extension
implementiert haben, können Sie die Mittelpunktskoordinate wie folgt festlegen:
let centerCoordinate = CLLocationCoordinate2DMake(48.136315, 11.5752901) //latitude, longitude
mapView?.setCenter(centerCoordinate, zoomLevel: 15, animated: true)
zoomLevel
ist ein Double
Wert, normalerweise zwischen 0
und 21
(was eine sehr hohe zoomLevel
ist), aber Werte bis 28
sind zulässig.
Mit Anmerkungen arbeiten
Erhalten Sie alle Anmerkungen
//following method returns all annotations object added on map
NSArray *allAnnotations = mapView.annotations;
Annotationsansicht abrufen
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"];
}
}
Alle Anmerkungen entfernen
[mapView removeAnnotations:mapView.annotations]
Einzelne Anmerkung entfernen
//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];
}
Passen Sie die Sichtbarkeit der Kartenansicht an, um alle Anmerkungen anzuzeigen
Schnell:
mapView.showAnnotations(mapView.annotations, animated: true)
Ziel c:
[mapView showAnnotations:mapView.annotations animated:YES];
Demo: