iOS - Наложение MKMapView не будет отображаться при переносе методов в другой класс

Работая над очисткой своего кода, чтобы я мог отображать различные наложения трасс на карте Apple MKMapView, в зависимости от...

В настоящее время у меня появляется карта яблока, и я могу получить определенное изображение следа наложения (поверх объекта MKMapView), когда я использую два метода -addOverlayTo: и mapView:rendererForOverlay - в моем классе контроллера представления "ParkMapVC". Когда я перемещаю эти два метода в другой, более общий класс "ParkMapOverlay" - класс, наследующий NSObject, я могу получить сообщение "addOverlayTo:", которое я посылаю напрямую, но не метод mapView: rendererForOverlay.

Я не сообщал напрямую mapView: rendererForOverlay в исходной (рабочей) версии, но из-за того, что следовал отладчику, мне показалось, что он был вызван моим addOverlayTo: метод - я думаю, что возвращаемый объект - хотя я не совсем ясен или уверен об этом.

Это работает:

    //  ParkMapVC.h

#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import "ParkMap.h"
#import "ParkMapVC.h"
@interface ParkMapVC : UIViewController <MKMapViewDelegate>{
}
@property (strong, nonatomic) IBOutlet MKMapView *hikeMap;
@property (weak, nonatomic) IBOutlet MKMapView *mapView;
@property (nonatomic, strong) ParkMap *park;
+ (ParkMapVC *) sharedParkMapVC;
- (void)addOverlayTo :(ParkMap*) thePark;
@end
#import "ParkMapVC.h"
#import "ParkMap.h"
#import "ParkMapOverlay.h"
#import "ParkMapOverlayView.h"
@interface ParkMapVC ()
@end
//*************
@implementation ParkMapVC
+ (ParkMapVC *) sharedParkMapVC {
    static ParkMapVC *sharedParkMapVC;
    @synchronized (self) {
        if (!sharedParkMapVC) {
            sharedParkMapVC = [[ParkMapVC alloc] init ];

        }
    return sharedParkMapVC;
    }

}
 - (void)viewDidLoad
{
    [super viewDidLoad];
    self.park = [[ParkMap alloc] initWithFilename:@"EdgewoodVer2"]; // plist
    // define region for apple map
     self.mapView.region = [self.park defineMapRegion:self.park];
    [self addOverlayTo:_park];
}
#pragma mark - Add methods
- (void)addOverlayTo :(ParkMap*) thePark{
    ParkMapOverlay *overlay = [[ParkMapOverlay alloc]          
                                       initWithPark:self.park];
    [self.mapView addOverlay:overlay];
}
#pragma mark - Map View delegate
// This should go to ParkMapOverlay 8.5.15
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay {

        UIImage *overlayEdgewoodImage = [UIImage
            imageNamed:@"EDGEoverlay_park_Cropped"];

        ParkMapOverlayView *overlayView = [[ParkMapOverlayView alloc] initWithOverlay:overlay overlayImage:overlayEdgewoodImage];

        return overlayView;

  }

@end

Что не работает:

В этот момент я переместил два метода - addOverlayTo: и mapView:rendererForOverlay - в класс "ParkMapOverlay". Я изменил способ отправки сообщений addOverlayTo, и он выполняется из класса "ParkMapOverlay". Однако, основываясь на точках останова отладчика, я вижу, что метод mapView: rendererForOverlay не передается по сообщениям, и на самом деле наложение не отображается. Я просто вижу свою карту яблока, отображенную на виде.

Вот код: // Внутри ParkMapVC я изменил оверлей, чтобы сообщить новый класс ParkMapOverlay

  [super viewDidLoad];
    self.park = [[ParkMap alloc] initWithFilename:@"EdgewoodVer2"]; 
    ParkMapOverlay *theOverlay = [[ParkMapOverlay alloc]init];

    self.mapView.region = [self.park defineMapRegion:self.park];
    self.mapView = [theOverlay addOverlayTo:_park ];

// Then I commented out the original two methods, moving the code to ParkMapOverlay 

//  ParkMapOverlay.h
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
@class ParkMap;
@interface ParkMapOverlay : NSObject <MKOverlay, MKMapViewDelegate>
- (instancetype)initWithPark:(ParkMap *)park;
- (MKMapView *)addOverlayTo :(ParkMap*) thePark;
@end

//  ParkMapOverlay.m
#import "ParkMapOverlay.h"
#import "ParkMapOverlayView.h" 
#import "ParkMap.h"
@implementation ParkMapOverlay
@synthesize coordinate;
@synthesize boundingMapRect;
- (instancetype)initWithPark:(ParkMap *)park {
    self = [super init];
    if (self) {
        boundingMapRect = park.overlayBoundingMapRect;
        coordinate = park.midCoordinate;
    }

    return self;
}
- (MKMapView *)addOverlayTo :(ParkMap*) thePark
{
     ParkMapOverlay *overlay = [[ParkMapOverlay alloc]      initWithPark:thePark];
     MKMapView *mapView = [[MKMapView alloc] init];
    [mapView addOverlay:overlay];

    return mapView;

}
#pragma mark - Map View delegate


- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay {
           UIImage *overlayEdgewoodImage = [UIImage
                                      imageNamed:@"EDGEoverlay_park_Cropped"];

        ParkMapOverlayView *overlayView = [[ParkMapOverlayView alloc] initWithOverlay:overlay overlayImage:overlayEdgewoodImage];

        return overlayView;

    }
@end

Что мне интересно -

  1. Методы изначально были в классе ViewController, теперь они находятся в классе, который является дочерним элементом NSObject.
  2. Поскольку я не совсем понимаю, как первоначально вызывается MKOverlayRenderer, мне нужно кое-что знать о том, что нужно сделать, чтобы вызвать это сейчас
  3. Что-то о том, как я теперь сообщаю addOverlayTo: метод в моем методе viewDidLoad в ParkMapVC, сбивает меня с толку
  4. Я нашел ссылку на Xamarin в рецепте "Добавить наложение на карту", ​​в которой говорится, что "метод OverlayRenderer должен быть назначен до добавления MKOverlay в MkMapView". Я не уверен, что это значит - разве это не связано с объектом, который объект ParkMapOverlay я выделяю init перед тем, как отправить сообщение addOverlayTo: метод?

Спасибо. LRS

1 ответ

Решение

mapView:rendererForOverlay: это метод <MKMapViewDelegate> протокол.

В вашем новом addOverlayTo: метод, который вы инициализируете новый объект MKMapView, но не устанавливаете ваш объект ParkMapOverlay как делегат этого представления карты. Вот почему mapView:rendererForOverlay: не называется.

Попробуйте установить это как mapView.delegate = self,

Также будьте осторожны с управлением памятью: MKMapView delegate это слабое свойство, т.е. оно не сохраняет свой делегат, поэтому вы должны быть уверены, что ваш объект ParkMapOverlay сохранен.

В настоящее время сохранение должно происходить правильно, потому что у вас есть как mapView:rendererForOverlay: метод в одном классе, так что добавление этого класса в качестве наложения через -[MKMapView addOverlay:] гарантирует, что объект сохраняется, но это побочный эффект вашего дизайна, так что имейте это в виду.

Другие вопросы по тегам