| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332 |
- //
- // ApexMapView.m
- // OpenStreetMap
- //
- // Created by Jack on 2019/1/18.
- // Copyright © 2019 Jack Template. All rights reserved.
- //
- #import "ApexMapView.h"
- #import "UIView+RAConstraint.h"
- static NSString * const kTileSource = @"https://map.apexshipping.com/osm_tiles/{z}/{x}/{y}.png";
- static NSString * const kOpenStreetMapURL = @"https://www.openstreetmap.org/copyright";
- static NSString * const kCopyright = @"OpenStreetMap";
- @interface ApexMapView () <MKMapViewDelegate>
- @property (nonatomic,strong) UIButton *legalBtn;
- @property (nonatomic,strong) MKTileOverlay *tileOverlay;
- @property (nonatomic,weak) id<MKMapViewDelegate> internalDelegate;
- @end
- @implementation ApexMapView
- #pragma mark - Initial
- - (instancetype)initWithFrame:(CGRect)frame {
- if (self = [super initWithFrame:frame]) {
- [self setupMapView];
- }
- return self;
- }
- - (void)awakeFromNib {
- [super awakeFromNib];
- [self setupMapView];
- }
- - (void)setupMapView {
-
- self.rotateEnabled = NO;
- [self apex_setDelegate:self];
-
- [self addOverlay:self.tileOverlay];
- }
- - (void)layoutSubviews {
- [super layoutSubviews];
-
- NSArray<UIView *> *subViews = self.subviews;
- for (UIView *subView in subViews) {
-
- if ([subView isMemberOfClass:NSClassFromString(@"MKAttributionLabel")]) {
- [subView removeFromSuperview];
- } else if ([subView isMemberOfClass:[UIImageView class]]) {
- [subView removeFromSuperview];
- }
- }
- if (![subViews containsObject:self.legalBtn]) {
- [self setupLegalView];
- }
- }
- - (void)setupLegalView {
-
- [self addSubview:self.legalBtn];
-
- [self.legalBtn ra_applyConstraints:^(RAConstraintMaker *maker) {
-
- maker.left.ra_equalTo(self.left).ra_offset(5.0f);
- maker.bottom.ra_equalTo(self.bottom).ra_offset(-5.0f);
- }];
-
- }
- #pragma mark - Override
- - (void)setDelegate:(id<MKMapViewDelegate>)delegate {
- if (delegate) {
- __weak typeof(delegate) weakDelegate = delegate;
- _internalDelegate = weakDelegate;
- } else {
- _internalDelegate = nil;
- }
- }
- - (void)apex_setDelegate:(id<MKMapViewDelegate>)delegate {
- [super setDelegate:delegate];
- }
- #pragma mark - Getter
- - (MKTileOverlay *)tileOverlay {
- if (!_tileOverlay) {
- _tileOverlay = [[MKTileOverlay alloc] initWithURLTemplate:kTileSource];
- _tileOverlay.canReplaceMapContent = YES;
- _tileOverlay.minimumZ = 1;
- _tileOverlay.maximumZ = 18;
- }
- return _tileOverlay;
- }
- - (UIButton *)legalBtn {
- if (!_legalBtn) {
- _legalBtn = [UIButton buttonWithType:UIButtonTypeSystem];
- _legalBtn.titleLabel.font = [UIFont systemFontOfSize:12.0f];
- [_legalBtn setTitle:kCopyright forState:UIControlStateNormal];
- [_legalBtn addTarget:self action:@selector(legalButtonDidClick:) forControlEvents:UIControlEventTouchUpInside];
- }
- return _legalBtn;
- }
- #pragma mark - User Action
- - (void)legalButtonDidClick:(id)sender {
-
- NSURL *url = [NSURL URLWithString:kOpenStreetMapURL];
- if ([[UIApplication sharedApplication] canOpenURL:url]) {
- if (@available(iOS 10, *)) {
- [[UIApplication sharedApplication] openURL:url options:@{UIApplicationOpenURLOptionsSourceApplicationKey: @YES} completionHandler:^(BOOL success) {
-
- }];
- } else{
- [[UIApplication sharedApplication] openURL:url];
- }
- }
- }
- #pragma mark - MKMapViewDelegate
- - (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated {
-
- if (_internalDelegate && [_internalDelegate respondsToSelector:@selector(mapView:regionWillChangeAnimated:)]) {
- [_internalDelegate mapView:mapView regionWillChangeAnimated:animated];
- }
- }
- - (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
-
- if (_internalDelegate && [_internalDelegate respondsToSelector:@selector(mapView:regionDidChangeAnimated:)]) {
- [_internalDelegate mapView:mapView regionDidChangeAnimated:animated];
- }
- }
- - (void)mapViewDidChangeVisibleRegion:(MKMapView *)mapView {
-
- if (_internalDelegate && [_internalDelegate respondsToSelector:@selector(mapViewDidChangeVisibleRegion:)]) {
- [_internalDelegate mapViewDidChangeVisibleRegion:mapView];
- }
- }
- - (void)mapViewWillStartLoadingMap:(MKMapView *)mapView {
-
- if (_internalDelegate && [_internalDelegate respondsToSelector:@selector(mapViewWillStartLoadingMap:)]) {
- [_internalDelegate mapViewWillStartLoadingMap:mapView];
- }
- }
- - (void)mapViewDidFinishLoadingMap:(MKMapView *)mapView {
-
- if (_internalDelegate && [_internalDelegate respondsToSelector:@selector(mapViewDidFinishLoadingMap:)]) {
- [_internalDelegate mapViewDidFinishLoadingMap:mapView];
- }
- }
- - (void)mapViewDidFailLoadingMap:(MKMapView *)mapView withError:(NSError *)error {
-
- if (_internalDelegate && [_internalDelegate respondsToSelector:@selector(mapViewDidFailLoadingMap:withError:)]) {
- [_internalDelegate mapViewDidFailLoadingMap:mapView withError:error];
- }
- }
- - (void)mapViewWillStartRenderingMap:(MKMapView *)mapView {
-
- if (_internalDelegate && [_internalDelegate respondsToSelector:@selector(mapViewWillStartRenderingMap:)]) {
- [_internalDelegate mapViewWillStartRenderingMap:mapView];
- }
- }
- - (void)mapViewDidFinishRenderingMap:(MKMapView *)mapView fullyRendered:(BOOL)fullyRendered {
-
- if (_internalDelegate && [_internalDelegate respondsToSelector:@selector(mapViewDidFinishRenderingMap:fullyRendered:)]) {
- [_internalDelegate mapViewDidFinishRenderingMap:mapView fullyRendered:fullyRendered];
- }
- }
- // mapView:viewForAnnotation: provides the view for each annotation.
- // This method may be called for all or some of the added annotations.
- // For MapKit provided annotations (eg. MKUserLocation) return nil to use the MapKit provided annotation view.
- - (nullable MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {
-
- if (_internalDelegate && [_internalDelegate respondsToSelector:@selector(mapView:viewForAnnotation:)]) {
- return [_internalDelegate mapView:mapView viewForAnnotation:annotation];
- }
- return nil;
- }
- // mapView:didAddAnnotationViews: is called after the annotation views have been added and positioned in the map.
- // The delegate can implement this method to animate the adding of the annotations views.
- // Use the current positions of the annotation views as the destinations of the animation.
- - (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray<MKAnnotationView *> *)views {
-
- if (_internalDelegate && [_internalDelegate respondsToSelector:@selector(mapView:didAddAnnotationViews:)]) {
- [_internalDelegate mapView:mapView didAddAnnotationViews:views];
- }
- }
- #if TARGET_OS_IPHONE
- // mapView:annotationView:calloutAccessoryControlTapped: is called when the user taps on left & right callout accessory UIControls.
- - (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control {
-
- if (_internalDelegate && [_internalDelegate respondsToSelector:@selector(mapView:annotationView:calloutAccessoryControlTapped:)]) {
- [_internalDelegate mapView:mapView annotationView:view calloutAccessoryControlTapped:control];
- }
- }
- #endif
- - (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view {
-
- if (_internalDelegate && [_internalDelegate respondsToSelector:@selector(mapView:didSelectAnnotationView:)]) {
- [_internalDelegate mapView:mapView didSelectAnnotationView:view];
- }
- }
- - (void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)view {
-
- if (_internalDelegate && [_internalDelegate respondsToSelector:@selector(mapView:didDeselectAnnotationView:)]) {
- [_internalDelegate mapView:mapView didDeselectAnnotationView:view];
- }
- }
- - (void)mapViewWillStartLocatingUser:(MKMapView *)mapView {
-
- if (_internalDelegate && [_internalDelegate respondsToSelector:@selector(mapViewWillStartLocatingUser:)]) {
- [_internalDelegate mapViewWillStartLocatingUser:mapView];
- }
- }
- - (void)mapViewDidStopLocatingUser:(MKMapView *)mapView {
-
- if (_internalDelegate && [_internalDelegate respondsToSelector:@selector(mapViewDidStopLocatingUser:)]) {
- [_internalDelegate mapViewDidStopLocatingUser:mapView];
- }
- }
- - (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation {
-
- if (_internalDelegate && [_internalDelegate respondsToSelector:@selector(mapView:didUpdateUserLocation:)]) {
- [_internalDelegate mapView:mapView didUpdateUserLocation:userLocation];
- }
- }
- - (void)mapView:(MKMapView *)mapView didFailToLocateUserWithError:(NSError *)error {
-
- if (_internalDelegate && [_internalDelegate respondsToSelector:@selector(mapView:didFailToLocateUserWithError:)]) {
- [_internalDelegate mapView:mapView didFailToLocateUserWithError:error];
- }
- }
- - (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view didChangeDragState:(MKAnnotationViewDragState)newState
- fromOldState:(MKAnnotationViewDragState)oldState {
-
- if (_internalDelegate && [_internalDelegate respondsToSelector:@selector(mapView:annotationView:didChangeDragState:fromOldState:)]) {
- [_internalDelegate mapView:mapView annotationView:view didChangeDragState:newState fromOldState:oldState];
- }
- }
- #if TARGET_OS_IPHONE
- - (void)mapView:(MKMapView *)mapView didChangeUserTrackingMode:(MKUserTrackingMode)mode animated:(BOOL)animated {
-
- if (_internalDelegate && [_internalDelegate respondsToSelector:@selector(mapView:didChangeUserTrackingMode:animated:)]) {
- [_internalDelegate mapView:mapView didChangeUserTrackingMode:mode animated:animated];
- }
- }
- #endif
- - (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id <MKOverlay>)overlay {
-
- if (overlay == self.tileOverlay) {
-
- return [[MKTileOverlayRenderer alloc] initWithTileOverlay:overlay];
- } else {
- if (_internalDelegate && [_internalDelegate respondsToSelector:@selector(mapView:rendererForOverlay:)]) {
- return [_internalDelegate mapView:mapView rendererForOverlay:overlay];
- } else {
- return nil;
- }
- }
- }
- - (void)mapView:(MKMapView *)mapView didAddOverlayRenderers:(NSArray<MKOverlayRenderer *> *)renderers {
-
- if (_internalDelegate && [_internalDelegate respondsToSelector:@selector(mapView:didAddOverlayRenderers:)]) {
- [_internalDelegate mapView:mapView didAddOverlayRenderers:renderers];
- }
- }
- #if TARGET_OS_IPHONE
- // Prefer -mapView:rendererForOverlay:
- - (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay {
-
- if (overlay == self.tileOverlay) {
-
- return [[MKOverlayView alloc] initWithOverlay:overlay];
- } else {
- if (_internalDelegate && [_internalDelegate respondsToSelector:@selector(mapView:viewForOverlay:)]) {
- return [_internalDelegate mapView:mapView viewForOverlay:overlay];
- } else {
- return nil;
- }
- }
- }
- // Called after the provided overlay views have been added and positioned in the map.
- // Prefer -mapView:didAddOverlayRenderers:
- - (void)mapView:(MKMapView *)mapView didAddOverlayViews:(NSArray *)overlayViews {
-
- if (_internalDelegate && [_internalDelegate respondsToSelector:@selector(mapView:didAddOverlayViews:)]) {
- [_internalDelegate mapView:mapView didAddOverlayViews:overlayViews];
- }
- }
- #endif
- // Return nil for default MKClusterAnnotation, it is illegal to return a cluster annotation not containing the identical array of member annotations given.
- - (MKClusterAnnotation *)mapView:(MKMapView *)mapView clusterAnnotationForMemberAnnotations:(NSArray<id<MKAnnotation>>*)memberAnnotations {
-
- if (_internalDelegate && [_internalDelegate respondsToSelector:@selector(mapView:clusterAnnotationForMemberAnnotations:)]) {
- return [_internalDelegate mapView:mapView clusterAnnotationForMemberAnnotations:memberAnnotations];
- }
- return nil;
- }
- @end
|