Ricerca…
Aggiungi MKMapView
veloce
let mapView = MKMapView(frame: CGRect(x: 0, y: 0, width: 320, height: 500))
Si consiglia di memorizzare i MapView come una proprietà della contenente ViewController
dal momento che si potrebbe desiderare di accedervi nelle implementazioni più complesse.
Obiettivo C
self.map = [[MKMapView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
[self.view addSubview:self.map];
Cambia il tipo di mappa
Esistono 5 tipi diversi ( MKMapType
), MKMapView
può essere visualizzato.
.satelliteFlyover
Visualizza un'immagine satellitare dell'area con dati cavalcavia ove disponibili.
Swift 2
mapView.mapType = .SatelliteFlyover
Swift 3
mapView.mapType = .satelliteFlyover
Objective-C
_mapView.mapType = MKMapTypeSatelliteFlyover;
.hybridFlyover
Visualizza un'immagine satellitare ibrida con dati cavalcavia ove disponibili.
Swift 2
mapView.mapType = .HybridFlyover
Swift 3
mapView.mapType = .hybridFlyover
Objective-C
_mapView.mapType = MKMapTypeHybridFlyover;
Imposta zoom / regione per mappa
Per impostare un livello di zoom, diciamo che vogliamo ingrandire la posizione dell'utente con la posizione dell'utente come centro e 2 km di area come raggio. Quindi, usiamo il seguente codice
MKUserLocation *userLocation = _mapView.userLocation;
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance (userLocation.location.coordinate, 2000, 2000);
[_mapView setRegion:region animated:NO];
Implementazione della ricerca locale usando MKLocalSearch
MKLocalSearch consente agli utenti di cercare la posizione utilizzando stringhe di linguaggio naturale come "palestra". Una volta completata la ricerca, la classe restituisce un elenco di posizioni all'interno di una regione specificata che corrisponde alla stringa di ricerca.
I risultati della ricerca sono in forma di MKMapItem all'interno dell'oggetto MKLocalSearchResponse.
proviamo con l'esempio
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);
}
}];
Tile-Overlay OpenStreetMap
In alcuni casi, potresti non voler utilizzare le mappe predefinite, fornisce Apple.
Puoi aggiungere una sovrapposizione al tuo mapView
che contiene tessere personalizzate, ad esempio da OpenStreetMap .
Supponiamo che self.mapView
sia il tuo MKMapView
che hai già aggiunto al ViewController
.
All'inizio, ViewController
deve essere conforme al protocollo MKMapViewDelegate
.
class MyViewController: UIViewController, MKMapViewDelegate
Quindi devi impostare ViewController
come delegato di mapView
mapView.delegate = self
Successivamente, si configura l'overlay per la mappa. Avrai bisogno di un modello di URL per questo. L'URL dovrebbe essere simile a questo su tutti i server tile e anche se si memorizzassero i dati della mappa 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
Dopo aver configurato l'overlay, devi aggiungerlo a mapView
.
mapView.add(overlay, level: .aboveLabels)
Per utilizzare mappe personalizzate, si consiglia di utilizzare .aboveLabels
per il level
. Altrimenti, le etichette predefinite saranno visibili sulla tua mappa personalizzata. Se vuoi vedere le etichette predefinite, puoi scegliere qui .aboveRoads
.
Se eseguissi il tuo progetto ora, riconoscerai che la tua mappa mostrerà comunque la mappa predefinita:
Questo perché non abbiamo ancora detto mapView
, come renderizzare l'overlay. Questo è il motivo per cui è stato necessario impostare il delegato in precedenza. Ora puoi aggiungere func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer
al tuo controller di visualizzazione:
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
if overlay is MKTileOverlay {
let renderer = MKTileOverlayRenderer(overlay: overlay)
return renderer
} else {
return MKTileOverlayRenderer()
}
}
Ciò restituirà il corretto MKOverlayRenderer
al tuo mapView
. Se esegui il tuo progetto ora, dovresti vedere una mappa come questa:
Se vuoi visualizzare un'altra mappa, devi solo cambiare il modello di URL. C'è un elenco di server di tile nel Wiki OSM.
Mostra esempio UserLocation e UserTracking
Questo mostrerà la posizione dell'utente sulla mappa
Objective-C
[self.map setShowsUserLocation:YES];
veloce
self.map?.showsUserLocation = true
In questo modo verrà tracciata la posizione dell'utente sulla mappa, aggiornando le regioni in base
Objective-C
[self.map setUserTrackingMode:MKUserTrackingModeFollow];
veloce
self.map?.userTrackingMode = .follow
Aggiunta di Pin / Point Annotation sulla mappa
Per annotare alcuni punti di interesse sulla mappa, utilizziamo l'annotazione dei pin. Ora, inizia creando prima l'oggetto annotazione.
MKPointAnnotation *pointAnnotation = [[MKPointAnnotation alloc] init];
Ora fornire coordinate a pointAnnotation, come
CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(23.054625,72.534562);
pointAnnotation.coordinate = coordinate;
Ora, fornisci titolo e sottotitolo alle annotazioni,
pointAnnotation.title = @"XYZ Point";
pointAnnotation.subtitle = @"Ahmedabad Area";
Ora aggiungi questa annotazione alla mappa.
[self.mapView addAnnotation:pointAnnotation];
Yeaah .. Evviva .. hai fatto il lavoro. Ora puoi vedere l'annotazione del punto (pin di colore rosso) a una determinata coordinata.
Ma ora, cosa succede se si desidera cambiare il colore del pin (3 colori disponibili sono: viola, rosso e verde). Quindi segui questo passaggio.
imposta il delegato di mapview a se stesso,
self.mapView.delegate = self;
Aggiungi l'implementazione MKMapViewDelegate. Ora aggiungi il seguente metodo, quindi
- (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;
}
Simula una posizione personalizzata
Passo 1: In Xcode: File -> Nuovo -> File -> Risorsa -> File GPX -> Avanti -> Assegna un nome al file GPX (in questo esempio Taipei
) -> Crea
Passaggio 2: modifica il file 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>
Passaggio 3: quando il simulatore è in esecuzione:
È possibile ripetere questo processo per creare più posizioni.
Scorri fino a coordinate e livello di zoom
Quando mostri una posizione ai tuoi utenti, potresti volere che MKMapView
visualizzi una coordinata a livello di zoom invece di impostare una regione da mostrare. Questa funzionalità non è implementata per impostazione predefinita, quindi è necessario estendere MKMapView
con metodi che eseguono il calcolo complesso da una coordinata e un livello di zoom a una 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)
}
}
}
(La versione originale di Swift 2 di Mylene Bayan è disponibile su GitHub )
Dopo aver implementato questa extension
, puoi impostare le coordinate centrali come segue:
let centerCoordinate = CLLocationCoordinate2DMake(48.136315, 11.5752901) //latitude, longitude
mapView?.setCenter(centerCoordinate, zoomLevel: 15, animated: true)
zoomLevel
è un valore Double
, solitamente compreso tra 0
e 21
(che è un livello di zoom molto elevato), ma sono consentiti valori fino a 28
.
Lavorando con annotazione
Ottieni tutte le annotazioni
//following method returns all annotations object added on map
NSArray *allAnnotations = mapView.annotations;
Ottieni la vista di annotazione
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"];
}
}
Rimuovi tutte le annotazioni
[mapView removeAnnotations:mapView.annotations]
Rimuovi annotazione singola
//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];
}
Regola il rect visibile della vista mappa per visualizzare tutte le annotazioni
Swift:
mapView.showAnnotations(mapView.annotations, animated: true)
Objective-C:
[mapView showAnnotations:mapView.annotations animated:YES];
demo: