Поиск…
Добавить MKMapView
стриж
let mapView = MKMapView(frame: CGRect(x: 0, y: 0, width: 320, height: 500))
Рекомендуется хранить mapView как свойство содержащего ViewController
так как вы можете захотеть получить к нему доступ в более сложных реализациях.
Цель C
self.map = [[MKMapView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
[self.view addSubview:self.map];
Изменить тип карты
Существует 5 различных типов ( MKMapType
), MKMapView
может отображать.
.satelliteFlyover
Отображает изображение спутника области с данными эстакады, если таковые имеются.
Swift 2
mapView.mapType = .SatelliteFlyover
Swift 3
mapView.mapType = .satelliteFlyover
Objective-C
_mapView.mapType = MKMapTypeSatelliteFlyover;
.hybridFlyover
Отображает гибридное изображение спутника с данными эстакады, если таковые имеются.
Swift 2
mapView.mapType = .HybridFlyover
Swift 3
mapView.mapType = .hybridFlyover
Objective-C
_mapView.mapType = MKMapTypeHybridFlyover;
Установить масштаб / регион для карты
Чтобы установить некоторый уровень масштабирования, скажем, мы хотим увеличить местоположение пользователя с местоположением пользователя в центре и 2 км от площади в радиусе. Затем мы используем следующий код
MKUserLocation *userLocation = _mapView.userLocation;
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance (userLocation.location.coordinate, 2000, 2000);
[_mapView setRegion:region animated:NO];
Реализация локального поиска с использованием MKLocalSearch
MKLocalSearch позволяет пользователям искать местоположение, используя строки естественного языка, такие как «тренажерный зал». Как только поиск будет завершен, класс возвращает список местоположений в пределах указанной области, которая соответствует строке поиска.
Результаты поиска в форме MKMapItem в объекте MKLocalSearchResponse.
попробуем попробовать
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
В некоторых случаях вы, возможно, не захотите использовать карты по умолчанию, предоставляемые Apple.
Вы можете добавить наложение в свой mapView
который содержит пользовательские плитки, например, из OpenStreetMap .
Предположим, self.mapView
- это ваш MKMapView
который вы уже добавили в свой ViewController
.
Сначала ваш ViewController
должен соответствовать протоколу MKMapViewDelegate
.
class MyViewController: UIViewController, MKMapViewDelegate
Затем вы должны установить ViewController
качестве делегата mapView
mapView.delegate = self
Затем вы настраиваете наложение для карты. Для этого вам понадобится шаблон URL. URL-адрес должен быть похож на это на всех серверах tile-серверов, и даже если вы сохраните данные карты в автономном режиме: 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
После настройки наложения вы должны добавить его в свой mapView
.
mapView.add(overlay, level: .aboveLabels)
Чтобы использовать пользовательские карты, рекомендуется использовать .aboveLabels
для level
. В противном случае метки по умолчанию будут видны на вашей пользовательской карте. Если вы хотите увидеть метки по умолчанию, вы можете выбрать здесь .aboveRoads
.
Если вы сейчас запустите свой проект, вы поймете, что ваша карта по-прежнему будет отображать карту по умолчанию:
Это потому, что мы еще не сказали mapView
, как визуализировать наложение. Вот почему вы должны были установить делегат раньше. Теперь вы можете добавить 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()
}
}
Это вернет правильный MKOverlayRenderer
в ваш mapView
. Если вы запустите свой проект сейчас, вы должны увидеть такую карту:
Если вы хотите отобразить другую карту, вам просто нужно изменить шаблон URL. В Wiki OSM есть список tile-серверов .
Показать пример UserLocation и UserTracking
Это покажет местоположение пользователя на карте
Objective-C
[self.map setShowsUserLocation:YES];
стриж
self.map?.showsUserLocation = true
Это позволит отслеживать местоположение пользователя на карте, обновлять регионы согласно
Objective-C
[self.map setUserTrackingMode:MKUserTrackingModeFollow];
стриж
self.map?.userTrackingMode = .follow
Добавление Pin / Point Annotation на карте
Для аннотации некоторой интересующей нас точки на карте мы используем pin-аннотацию. Теперь сначала создайте объект аннотации.
MKPointAnnotation *pointAnnotation = [[MKPointAnnotation alloc] init];
Теперь предоставим координату pointAnnotation, так как
CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(23.054625,72.534562);
pointAnnotation.coordinate = coordinate;
Теперь укажите заголовок и субтитры для аннотации,
pointAnnotation.title = @"XYZ Point";
pointAnnotation.subtitle = @"Ahmedabad Area";
Теперь добавьте эту аннотацию к карте.
[self.mapView addAnnotation:pointAnnotation];
Да ... Ура. Ты сделал это. Теперь вы можете увидеть аннотацию точки (красный цветной контакт) при заданной координате.
Но теперь, если вы хотите изменить цвет штифта (3 доступных цвета - фиолетовый, красный и зеленый). Затем следуйте этому шагу.
назначить делегата mapview самому себе,
self.mapView.delegate = self;
Добавьте реализацию MKMapViewDelegate. Теперь добавьте следующий метод,
- (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;
}
Имитировать настраиваемое местоположение
Шаг 1: В Xcode: Файл -> Создать -> Файл -> Ресурс -> Файл GPX -> Далее -> Дайте GPX-файлу имя (это в этом примере Taipei
) -> Создать
Шаг 2. Редактирование файла 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>
Шаг 3: Когда симулятор запущен:
Вы можете повторить этот процесс для создания нескольких местоположений.
Выделите координаты и масштаб
Когда вы показываете местоположение своим пользователям, вы можете захотеть, чтобы MKMapView
отображал координату на уровне масштабирования, а не настраивал регион для отображения. Эта функциональность не реализована по умолчанию, поэтому вам необходимо расширить MKMapView
с помощью методов, которые выполняют комплексный расчет с координаты и уровня масштабирования до 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)
}
}
}
(Оригинальную версию Swift 2 от Mylene Bayan можно найти на GitHub )
После того, как вы внесете это extension
, вы можете установить центральную координату следующим образом:
let centerCoordinate = CLLocationCoordinate2DMake(48.136315, 11.5752901) //latitude, longitude
mapView?.setCenter(centerCoordinate, zoomLevel: 15, animated: true)
zoomLevel
- это Double
значение, обычно от 0
до 21
(что является очень высоким уровнем масштабирования), но допустимы значения до 28
.
Работа с аннотацией
Получить всю аннотацию
//following method returns all annotations object added on map
NSArray *allAnnotations = mapView.annotations;
Просмотр аннотаций
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"];
}
}
Удалить все аннотации
[mapView removeAnnotations:mapView.annotations]
Удалить отдельную аннотацию
//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];
}
Отрегулируйте видимый прямоугольник вида карты, чтобы отобразить все аннотации
Swift:
mapView.showAnnotations(mapView.annotations, animated: true)
Objective-C:
[mapView showAnnotations:mapView.annotations animated:YES];
Демо-версия: