iOS - 当我将方法移动到另一个类时,MKMapView 覆盖不会呈现

Posted

技术标签:

【中文标题】iOS - 当我将方法移动到另一个类时,MKMapView 覆盖不会呈现【英文标题】:iOS - MKMapView Overlay won't render when I move methods to another class 【发布时间】:2015-08-05 19:52:43 【问题描述】:

正在清理我的代码,以便我可以在 MKMapView 苹果地图上呈现不同的轨迹叠加层,具体取决于...

目前我有一个苹果地图,当我在我的视图控制器类“ParkMapVC”中使用两种方法 -addOverlayTo: 和 mapView:rendererForOverlay 时,我可以获得一个特定的覆盖轨迹图像渲染(在 MKMapView 对象上)。当我将这两个方法移到另一个更通用的类“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”类中执行。但是,基于调试器断点,我可以看到 ma​​pView: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

我想知道什么 -

    这些方法最初位于 ViewController 类中,现在它们位于一个 NSObject 子类中 因为我不完全了解最初是如何调用 MKOverlayRenderer 的,所以现在我需要了解一些事情才能触发它 关于我现在在 ParkMapVC 中的 viewDidLoad 方法中向 addOverlayTo: 方法发送消息的方式让我感到困惑 我在 Xamarin 中的“将叠加层添加到地图”配方中找到了一个参考,其中说“在将 MKOverlay 添加到 MkMapView 之前必须分配 OverlayRenderer 方法”。我不确定这意味着什么 - 除非它与我在向 addOverlayTo: 方法发送消息之前分配初始化的 ParkMapOverlay 对象有关?

谢谢。 LRS

【问题讨论】:

【参考方案1】:

mapView:rendererForOverlay:&lt;MKMapViewDelegate&gt; 协议的一个方法。

在您的新 addOverlayTo: 方法中,您正在初始化新的 MKMapView 对象,但没有将 ParkMapOverlay 对象设置为该地图视图的委托。这就是为什么不调用 mapView:rendererForOverlay: 的原因。

尝试将其设置为mapView.delegate = self

还要注意内存管理:MKMapView 的delegate 是一个弱属性,即它不保留其委托,因此您必须确保保留您的 ParkMapOverlay 对象。

当前保留应该正确发生,因为您在一个类中同时具有覆盖功能和 mapView:rendererForOverlay: 方法,因此通过 -[MKMapView addOverlay:] 将该类添加为覆盖可确保保留对象,但这是您设计的副作用,所以意识到这一点。

【讨论】:

感谢斯坦尼斯劳。我正在研究如何整合你的想法。我想也许我需要向 addToOverlay 方法添加另一个参数 - 传入我在 ParkMapVC 中实例化的 MKMapView 对象 哦哇!那行得通!我确实更改了我的方法,以便将原始 MKMapView 对象作为称为“theMapView”的(新)第二个参数传递,然后我没有在 addOverlayTo:(etc) 方法中引用“mapView”,而是将所有这些对象更改为 theMapView 和我的轨迹覆盖再次显示在我的 MKMapView 对象上。所以现在我可以构建我所有的 if this-then that trail 逻辑,并根据很多事情开始显示不同的踪迹。 - 你真的为我节省了一天,这里有英雄徽章吗?我也会检查那个框。非常感谢您花时间阅读。 - (MKMapView )addOverlayTo :(ParkMap) thePark withMapView:(MKMapView *)theMapView ParkMapOverlay *overlay = [[ParkMapOverlay alloc] initWithPark:thePark]; theMapView.delegate = self; [theMapView addOverlay:overlay];返回地图视图; 似乎无法弄清楚将新版本的代码粘贴到哪里,以供将来遇到同样问题的人使用。我确实在每行的开头放了 4 个空白字符.... 更新您的问题,因为代码格式在 cmets 中不起作用。

以上是关于iOS - 当我将方法移动到另一个类时,MKMapView 覆盖不会呈现的主要内容,如果未能解决你的问题,请参考以下文章

IOS 地图移动中心点获取

iOS 地图移动中心点获取

在 xamarin ios 中使用 MkMap 不会出现路线

移动到另一个项目时无法识别类型化数据集

移动到另一个文本字段时,为啥 UIScrollView 会重新调整大小 - iOS iPhone

将文件夹中的所有文件移动到另一个?