Working on cleaning up my code so I can render different overlays of trails atop an MKMapView apple map, depending...
Currently I have an apple map coming up and I can get a specific overlay trail image rendered (over an MKMapView object) when I use two methods -addOverlayTo: and mapView:rendererForOverlay - within my view controller class "ParkMapVC". When I move those two methods to another more generic class "ParkMapOverlay" - an NSObject inheriting class, I can get the "addOverlayTo:" method I message directly to execute, but not the mapView:rendererForOverlay method.
I didn't directly message mapView:rendererForOverlay in the original (working) version, but from following the debugger, it seemed it was triggered by my addOverlayTo: method - I think by the object returned - though I'm not entirely clear or sure about that.
This works:
// 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
What does not work :
At this point - I moved the two methods - addOverlayTo: and mapView:rendererForOverlay- out to the class "ParkMapOverlay". I changed the way I was messaging addOverlayTo and it does execute from within the "ParkMapOverlay" class. However, based on debugger breakpoints, I can see that the mapView:rendererForOverlay method is not messaged , and indeed the overlay is not rendered. I just see my apple map displayed in the view.
Here is the code: //Within ParkMapVC I altered overlay to message the new class 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
What I wonder about -
Thank you. LRS
mapView:rendererForOverlay:
is a method of <MKMapViewDelegate>
protocol.
In your new addOverlayTo:
method you are initializing new MKMapView object but are not setting your ParkMapOverlay object as that map view's delegate. This is why mapView:rendererForOverlay:
is not called.
Try to set it like mapView.delegate = self
.
Also be careful with memory management: MKMapView's delegate
is a weak property ie it does not retain its delegate so you must be sure to keep your ParkMapOverlay object retained.
Currently retain should happen correctly because you have both overlay functionality and mapView:rendererForOverlay:
method in one class so that adding that class as overlay via -[MKMapView addOverlay:]
ensures that object is retained but that is a side-effect of your design so be aware of it.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.