Продолжаем разбираться в картах - MapKit.
Видео к этому уроку находится здесь.
Добавляем к всплывающему облачку над Pin справа кнопку информации. Для этого в метод
добавляем
Для поиска владельца кнопки создаем рекурсивную функцию в категории:
Для получения адреса по координатам создаем проперти:
и инициализируем его в viewDidLoad:
Пишем обработчик кнопки:
UIAlertView используемый в данном уроке для вывода адреса или ошибки устарел Deprecated, поэтому используем UIAlertController:
Добавляем еще одну кнопку в облачко Pin для отображения пути от текущей геопозиции до Pin. В функцию
добавляем
Добавляем обработчик этой кнопки
Домашнее задание к этому уроку:
По ходу выполнения домашнего задания завис на 5 пункте, т.к. картинки для Pin не отображались.
Оказывается с IOS 9 для класса MKPinAnnotationView отображаются только стандартные картинки для Пина. Можно только менять цвета.
Пришлось для кастомных картинок использовать родительский класс MKAnnotationView который не имеет свойств таких как анимированное падение и цвет пина.
Вот такая получилась функция для 5 задания:
Ученик.
1. Создайте массив из 10 - 30 рандомных студентов, прямо как раньше, только в этот раз пусть у них наряду с именем и фамилией будет еще и координата. Можете использовать структуру координаты, а можете просто два дабла - лонгитюд и латитюд.
2. Координату генерируйте так, установите центр например в вашем городе и просто генерируйте небольшие отрицательные либо положительные числа, чтобы рандомно получалась координата от центра в пределах установленного радиуса.
(Ну а если совсем не получается генерировать координату, то просто ставьте им заготовленные координаты - это не главное)
3. После того, как вы сгенерировали своих студентов, покажите их всех на карте, причем в титуле пусть будет Имя и Фамилия а в сабтитуле год рождения. Можете для каждого студента создать свою аннотацию, а можете студентов подписать на протокол аннотаций и добавить их на карту напрямую - как хотите :)
Студент.
4. Добавьте кнопочку, которая покажет всех студентов на экране.
5. Вместо пинов на карте используйте свои кастомные картинки, причем если студент мужского пола, то картинка должна быть одна, а для девушек другая.
Мастер
6. У каждого колаута (этого облачка над пином) сделайте кнопочку информации справа так, что когда я на нее нажимаю вылазит поповер, в котором в виде статической таблицы находится имя и фамилия студента, год рождения, пол и самое главное адрес.
7. В случае если это телефон, то вместо поповера контроллер должен вылазить модально.
Супермен
8. Создайте аннотацию для места встречи и показывайте его на карте новымой соответствующей картинкой
9. Место встречи можно перемещать по карте, а студентов нет
10. Когда место встречи бросается на карту, то вокруг него надо рисовать 3 круга, с радиусами 5 км, 10 км и 15 км (используйте оверлеи)
11. На какой-то полупрозрачной вьюхе в одном из углов вам надо показать сколько студентов попадают в какой круг. Суть такая, чем дальше студент живет, тем меньше вероятность что он придет на встречу. Расстояние от студента до места встречи рассчитывайте используя функцию для расчета расстояния между точками, поищите ее в фреймворке :)
12. Сделайте на навигейшине кнопочку, по нажатию на которую, от рандомных студентов до нее будут проложены маршруты (типо студенты идут на сходку), притом вероятности генератора разные, зависит от круга, в котором они находятся, если он близко, то 90%, а если далеко - то 10%
Видео к этому уроку находится здесь.
Добавляем к всплывающему облачку над Pin справа кнопку информации. Для этого в метод
- (nullable MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
добавляем
UIButton *descriptionButton=[UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[descriptionButton addTarget:self action:@selector(actionDescription:) forControlEvents:UIControlEventTouchUpInside];
pin.rightCalloutAccessoryView=descriptionButton;
Для того, чтобы узнать на каком Pin была нажата кнопка (для правильной обработки событий) применим ранее используемый метод с расширением категории UIView.
Создаем новую категорию для UIView с именем MKAnnotationView:
File->New File->Objective C File
выбираем из списка категория и вводим имя.
Для поиска владельца кнопки создаем рекурсивную функцию в категории:
#import "UIView+MKAnnotationView.h"
#import <MapKit/MapKit.h>
@implementation UIView (MKAnnotationView)
- (MKAnnotationView*) superAnnotationView{
if ([self isKindOfClass:[MKAnnotationView class]]) {
return (MKAnnotationView*) self;
}
if (!self.subviews) {
return nil;
}
return [self.superview superAnnotationView];
}
@end
Для получения адреса по координатам создаем проперти:
@property(nonatomic,strong) CLGeocoder *geoCoder;
self.geoCoder=[[CLGeocoder alloc] init];
Пишем обработчик кнопки:
-(void) actionDescription: (UIButton *) sender{
//определяем владельца кнопки с помощью нашей функции
MKAnnotationView* annotationView = [sender superAnnotationView];
if (!annotationView) {
return;
}
//сохраняем координаты аннотации
CLLocationCoordinate2D coordinate = annotationView.annotation.coordinate;
//используя широту и долготу инициализируем объект типа CLLocation
CLLocation* location = [[CLLocation alloc] initWithLatitude:coordinate.latitude
longitude:coordinate.longitude];
//Если Геокодер что-то делает, то мы отменяем это действие
if ([self.geoCoder isGeocoding]) {
[self.geoCoder cancelGeocode];
}
//Делаем запрос к геокодеру по нашим координатам
[self.geoCoder
reverseGeocodeLocation:location
completionHandler:^(NSArray *placemarks, NSError *error) {
NSString* message = nil;
//если произошла ошибка - выводим в сообщении
if (error) {
message = [error localizedDescription];
} else {
//если массив с адресом не пустой, выводим в сообщение
if ([placemarks count] > 0) {
MKPlacemark* placeMark = [placemarks firstObject];
message = [placeMark.addressDictionary description];
//если пустой массив, сообщаем об этом
} else {
message = @"No Placemarks Found";
}
}
//Выводим сообщение с помощью AlerController (для этого создали функцию showAlertWithTitle)
[self showAlertWithTitle:@"Location" andMessage:message];
}];
}
-(void) showAlertWithTitle:(NSString*) title andMessage:(NSString*) message{
UIAlertController* alert = [UIAlertController alertControllerWithTitle:title
message:message
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {}];
[alert addAction:defaultAction];
[self presentViewController:alert animated:YES completion:nil];
}
- (nullable MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
добавляем
UIButton *wayButton=[UIButton buttonWithType:UIButtonTypeContactAdd];
[descriptionButton addTarget:self action:@selector(actionWayDirection:) forControlEvents:UIControlEventTouchUpInside];
pin.leftCalloutAccessoryView=wayButton;
Добавляем проперти MKDirections, чтобы переменная не уничтожилась раньше времени
@property (nonatomic,strong) MKDirections *directions;
Добавляем обработчик этой кнопки
-(void) actionWayDirection: (UIButton *) sender{
MKAnnotationView* annotationView = [sender superAnnotationView];
if (!annotationView) {
return;
}
//Если происходит вычисление пути, отменяем вычисление
if ([self.directions isCalculating]) {
[self.directions cancel];
}
//Заполняем запрос полученным destination
request.destination = destination;
//Тип транспорта на котором можно передвигаться - автомобиль
//Запускаем на вычисление - поиски маршрутов
//Если направлений 0 - выводим сообщение об этом
else if ([response.routes count]==0){
else{
//Удаляем старые нарисованные маршруты
[self.mapView removeOverlays:[self.mapView overlays]];
NSMutableArray *arrayRoute=[NSMutableArray array];
for (MKRoute *route in response.routes) {
[arrayRoute addObject:route.polyline];
}
}
}];
}
Исходный текст проекта находится здесь.
//Ищем аннотацию - владельца нажатой кнопки с помощью нашей рекурсивной функции
MKAnnotationView* annotationView = [sender superAnnotationView];
return;
}
//Если происходит вычисление пути, отменяем вычисление
if ([self.directions isCalculating]) {
[self.directions cancel];
}
// Получаем координаты из аннотации
CLLocationCoordinate2D coordinate = annotationView.annotation.coordinate;
// Создаем запрос
MKDirectionsRequest *request=[[MKDirectionsRequest alloc]init];
//Заполняем запрос из текущего местоположения
request.source = [MKMapItem mapItemForCurrentLocation];
//Создаем MKPlacemark из координат аннотации
MKPlacemark *placemark=[[MKPlacemark alloc]initWithCoordinate:coordinate addressDictionary:nil];
//Создаем MKMapItem из полученной placemark
MKMapItem *destination = [[MKMapItem alloc] initWithPlacemark:placemark];//Заполняем запрос полученным destination
request.destination = destination;
//Тип транспорта на котором можно передвигаться - автомобиль
request.transportType= MKDirectionsTransportTypeAutomobile;
//Для показа альтернативных путей
request.requestsAlternateRoutes=YES;
//Инициализируем нашу property c помощью сформированного запроса
self.directions = [[MKDirections alloc] initWithRequest:request];//Запускаем на вычисление - поиски маршрутов
[self.directions calculateDirectionsWithCompletionHandler:^(MKDirectionsResponse * _Nullable response, NSError * _Nullable error) {
//Если существует ошибка, выводим её
if (error) {
[self showAlertWithTitle:@"Error" andMessage:[error localizedDescription]];
}//Если направлений 0 - выводим сообщение об этом
else if ([response.routes count]==0){
[self showAlertWithTitle:@"Error" andMessage:@"No routes found"];
}else{
//Удаляем старые нарисованные маршруты
[self.mapView removeOverlays:[self.mapView overlays]];
//Формируем массив с маршрутами для прорисовки
for (MKRoute *route in response.routes) {
[arrayRoute addObject:route.polyline];
}
//Рисуем на карте наши маршруты
[self.mapView addOverlays:arrayRoute level:MKOverlayLevelAboveRoads];
}
Домашнее задание к этому уроку:
По ходу выполнения домашнего задания завис на 5 пункте, т.к. картинки для Pin не отображались.
Оказывается с IOS 9 для класса MKPinAnnotationView отображаются только стандартные картинки для Пина. Можно только менять цвета.
Пришлось для кастомных картинок использовать родительский класс MKAnnotationView который не имеет свойств таких как анимированное падение и цвет пина.
Вот такая получилась функция для 5 задания:
- ( MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation{
if ([annotation isKindOfClass:[MKUserLocation class]]) {
return nil;
}
static NSString *pinIdentifier=@"AnnotationStudent";
MKAnnotationView *pin=(MKAnnotationView *) [self.mapView dequeueReusableAnnotationViewWithIdentifier:pinIdentifier];
if (!pin) {
pin=[[MKAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:pinIdentifier];
pin.canShowCallout=YES;
pin.draggable=YES;
}
else{
pin.annotation=annotation;
}
if ([annotation isKindOfClass:[TAStudent class]]) {
TAStudent *student=(TAStudent*) annotation;
NSString *imageName=student.isMen?@"man_pin":@"woman_pin";
UIImage *imagePin=[UIImage imageNamed:imageName];
pin.image = imagePin;
}
return pin;
}
Выполнил все задания кроме супермена (нужно следующие уроки разбирать).
Исходник с домашним заданием здесь.
Выполнил все задания кроме супермена (нужно следующие уроки разбирать).
Исходник с домашним заданием здесь.
Ученик.
1. Создайте массив из 10 - 30 рандомных студентов, прямо как раньше, только в этот раз пусть у них наряду с именем и фамилией будет еще и координата. Можете использовать структуру координаты, а можете просто два дабла - лонгитюд и латитюд.
2. Координату генерируйте так, установите центр например в вашем городе и просто генерируйте небольшие отрицательные либо положительные числа, чтобы рандомно получалась координата от центра в пределах установленного радиуса.
(Ну а если совсем не получается генерировать координату, то просто ставьте им заготовленные координаты - это не главное)
3. После того, как вы сгенерировали своих студентов, покажите их всех на карте, причем в титуле пусть будет Имя и Фамилия а в сабтитуле год рождения. Можете для каждого студента создать свою аннотацию, а можете студентов подписать на протокол аннотаций и добавить их на карту напрямую - как хотите :)
Студент.
4. Добавьте кнопочку, которая покажет всех студентов на экране.
5. Вместо пинов на карте используйте свои кастомные картинки, причем если студент мужского пола, то картинка должна быть одна, а для девушек другая.
Мастер
6. У каждого колаута (этого облачка над пином) сделайте кнопочку информации справа так, что когда я на нее нажимаю вылазит поповер, в котором в виде статической таблицы находится имя и фамилия студента, год рождения, пол и самое главное адрес.
7. В случае если это телефон, то вместо поповера контроллер должен вылазить модально.
Супермен
8. Создайте аннотацию для места встречи и показывайте его на карте новымой соответствующей картинкой
9. Место встречи можно перемещать по карте, а студентов нет
10. Когда место встречи бросается на карту, то вокруг него надо рисовать 3 круга, с радиусами 5 км, 10 км и 15 км (используйте оверлеи)
11. На какой-то полупрозрачной вьюхе в одном из углов вам надо показать сколько студентов попадают в какой круг. Суть такая, чем дальше студент живет, тем меньше вероятность что он придет на встречу. Расстояние от студента до места встречи рассчитывайте используя функцию для расчета расстояния между точками, поищите ее в фреймворке :)
12. Сделайте на навигейшине кнопочку, по нажатию на которую, от рандомных студентов до нее будут проложены маршруты (типо студенты идут на сходку), притом вероятности генератора разные, зависит от круга, в котором они находятся, если он близко, то 90%, а если далеко - то 10%
Комментариев нет:
Отправить комментарий