Ответ 1
Я понимаю, что вам нужен булавка с настраиваемой выноской.
Мы не можем создать настраиваемую выноску, но мы можем создать аннотацию с полностью настроенным представлением. Таким образом, трюк заключается в том, чтобы добавить вторую аннотацию, когда первый выбран, и сделать второй аннотационный вид похожим на пузырь выноски.
Это решение опубликовано пользователями djibouti33 и jacob-jennings в ответе: MKAnnotationView - заблокировать пользовательский аннотационный просмотр для привязки к обновлениям местоположения, который, в свою очередь, основан на блоге от решений Asynchrony. Для объяснения целей, вот некоторые UML из раздвоенного проекта:
Это большой взлом, но также и самый чистый способ, с помощью которого я реализовал пользовательские аннотации.
Начните с класса NSObject "Content", который имеет координату, класс используемого вида выноски (в UML есть AnnotationView, но вы можете создать больше и установить их здесь) и словарь случайных значений с помощью title, photo url и т.д. Используйте этот класс для инициализации объекта "Аннотации" MKAnnotation.
#import <MapKit/MapKit.h>
@interface Content : NSObject
@property (nonatomic,assign) CLLocationCoordinate2D coordinate;
// ...
@interface Annotation : NSObject <MKAnnotation, AnnotationProtocol>
-(id) initWithContent:(Content*)content;
// ...
Annotation реализует AnnotationProtocol, чтобы объявить, что хочет обработать создание своего собственного MKAnnotationView. То есть ваш MKMapViewDelegate должен иметь такой код:
- (MKAnnotationView *)mapView:(MKMapView *)aMapView viewForAnnotation:(id<MKAnnotation>)annotation
{
// if this is a custom annotation, delegate the implementation of the view
if ([annotation conformsToProtocol:@protocol(AnnotationProtocol)]) {
return [((NSObject<AnnotationProtocol>*)annotation) annotationViewInMap:mapView];
} else {
// else, return a standard annotation view
// ...
}
}
Возвращаемое представление будет иметь тип AnnotationView, который реализует AnnotationViewProtocol, чтобы объявить, что он хочет обрабатывать выбор/отмена выбора. Поэтому в вашем контроллере просмотра карты методы mapView: didSelectAnnotationView: и mapView: didDeselectAnnotationView: должен делегировать аналогично тому, что мы видели раньше.
При выборе аннотации добавляется вторая аннотация (CalloutAnnotation), которая следует за тем же поведением, но на этот раз возвращенный вид (CalloutView) инициализируется из XIB и содержит код Core Graphics (в BaseCalloutView) для анимации и скопируйте выноску.
Инициализатор класса CalloutView:
- (id)initWithAnnotation:(CalloutAnnotation*)annotation
{
NSString *identifier = NSStringFromClass([self class]);
self = [super initWithAnnotation:annotation reuseIdentifier:identifier];
if (self!=nil){
[[NSBundle mainBundle] loadNibNamed:identifier owner:self options:nil];
// prevent the tap and double tap from reaching views underneath
UITapGestureRecognizer *tapGestureRecognizer = ...
}
return self;
}
Чтобы иметь возможность нажать другой контроллер вида из представления выноска, я использовал уведомления.
Ответ SO, на который я связан сверху, содержит два полных проекта, реализующих этот код (имена классов могут отличаться). У меня есть другой проект с использованием UML выше в https://github.com/j4n0/callout.