iOS - 当我将方法移动到另一个方法时,MKMapView 覆盖不会呈现 class
iOS - MKMapView Overlay won't render when I move methods to another class
正在清理我的代码,以便我可以在 MKMapView 苹果地图上呈现不同的轨迹叠加层,具体取决于...
目前我有一张苹果地图,当我在我的视图控制器中使用两种方法 -addOverlayTo: 和 mapView:rendererForOverlay 时,我可以获得渲染的特定叠加轨迹图像(在 MKMapView 对象上)class "ParkMapVC"。当我将这两个方法移动到另一个更通用的 class "ParkMapOverlay" - 一个继承 class 的 NSObject 时,我 can 得到 "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- 移到了 class "ParkMapOverlay"。我改变了发送消息 addOverlayTo 的方式,它 从 "ParkMapOverlay" class 中执行 。但是,根据调试器断点,我可以看到 mapView:rendererForOverlay 方法未收到消息 ,并且确实未呈现覆盖。我刚刚看到我的苹果地图显示在视图中。
代码如下:
//在 ParkMapVC 中,我更改了叠加层以向新的 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
我想知道的是 -
- 这些方法最初在 ViewController class 中,现在它们在 class 中,它是一个 NSObject child
- 因为我不完全理解 MKOverlayRenderer 最初是如何被调用的,所以我需要知道现在必须完成一些事情才能触发它
- 关于我现在在 ParkMapVC 的 viewDidLoad 方法中向 addOverlayTo: 方法发送消息的方式让我感到困惑
- 我在 Xamarin 的 "Add an Overlay to a Map" 配方中找到了一个参考,上面写着 "The OverlayRenderer method must be assigned to prior to adding the MKOverlay to the MkMapView"。我不确定这意味着什么 - 除非它与我在向 addOverlayTo: 方法发送消息之前分配初始化的 ParkMapOverlay 对象有关?
谢谢。
LRS
mapView:rendererForOverlay:
是<MKMapViewDelegate>
协议的一种方法。
在您的新 addOverlayTo:
方法中,您正在初始化新的 MKMapView 对象,但没有将您的 ParkMapOverlay 对象设置为该地图视图的委托。这就是 mapView:rendererForOverlay:
没有被调用的原因。
尝试设置成mapView.delegate = self
。
还要注意内存管理:MKMapView 的 delegate
是一个弱 属性 即它不保留其委托,因此您必须确保保留您的 ParkMapOverlay 对象。
目前保留应该正确发生,因为您在一个 class 中同时具有覆盖功能和 mapView:rendererForOverlay:
方法,因此通过 -[MKMapView addOverlay:]
添加 class 作为覆盖可确保对象已保留,但这是您设计的副作用,因此请注意。
正在清理我的代码,以便我可以在 MKMapView 苹果地图上呈现不同的轨迹叠加层,具体取决于...
目前我有一张苹果地图,当我在我的视图控制器中使用两种方法 -addOverlayTo: 和 mapView:rendererForOverlay 时,我可以获得渲染的特定叠加轨迹图像(在 MKMapView 对象上)class "ParkMapVC"。当我将这两个方法移动到另一个更通用的 class "ParkMapOverlay" - 一个继承 class 的 NSObject 时,我 can 得到 "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- 移到了 class "ParkMapOverlay"。我改变了发送消息 addOverlayTo 的方式,它 从 "ParkMapOverlay" class 中执行 。但是,根据调试器断点,我可以看到 mapView:rendererForOverlay 方法未收到消息 ,并且确实未呈现覆盖。我刚刚看到我的苹果地图显示在视图中。
代码如下: //在 ParkMapVC 中,我更改了叠加层以向新的 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
我想知道的是 -
- 这些方法最初在 ViewController class 中,现在它们在 class 中,它是一个 NSObject child
- 因为我不完全理解 MKOverlayRenderer 最初是如何被调用的,所以我需要知道现在必须完成一些事情才能触发它
- 关于我现在在 ParkMapVC 的 viewDidLoad 方法中向 addOverlayTo: 方法发送消息的方式让我感到困惑
- 我在 Xamarin 的 "Add an Overlay to a Map" 配方中找到了一个参考,上面写着 "The OverlayRenderer method must be assigned to prior to adding the MKOverlay to the MkMapView"。我不确定这意味着什么 - 除非它与我在向 addOverlayTo: 方法发送消息之前分配初始化的 ParkMapOverlay 对象有关?
谢谢。 LRS
mapView:rendererForOverlay:
是<MKMapViewDelegate>
协议的一种方法。
在您的新 addOverlayTo:
方法中,您正在初始化新的 MKMapView 对象,但没有将您的 ParkMapOverlay 对象设置为该地图视图的委托。这就是 mapView:rendererForOverlay:
没有被调用的原因。
尝试设置成mapView.delegate = self
。
还要注意内存管理:MKMapView 的 delegate
是一个弱 属性 即它不保留其委托,因此您必须确保保留您的 ParkMapOverlay 对象。
目前保留应该正确发生,因为您在一个 class 中同时具有覆盖功能和 mapView:rendererForOverlay:
方法,因此通过 -[MKMapView addOverlay:]
添加 class 作为覆盖可确保对象已保留,但这是您设计的副作用,因此请注意。