【问题标题】:Is it possible to inherit from MKPolyline是否可以从 MKPolyline 继承
【发布时间】:2021-08-18 18:42:22
【问题描述】:

我正在为 iPhone 构建一个基于 MapKit 的应用程序。

我在地图中添加了许多 MKPolylines。

但是,我不想使用 MKPolyline,而是希望将符合 MKOverlay 协议的自己的模型类添加到地图中,以便在 mapView:viewForOverlay 中创建相应视图时可以访问模型属性。

问题是我找不到从 MKPolyline 继承的方法,因为它没有任何我可以从子类的 init 调用的 init 方法。您只能使用方便的方法创建它们。

如何将模型属性和 MKPolyline 行为结合在一起?

【问题讨论】:

    标签: ios mapkit


    【解决方案1】:

    MANIAK_dobrii 的代码是可行的方法,但我发现我必须实现一些额外的 MKMultiPoint 方法才能使其工作,这是我使用的 AnchorLine 类的完整头文件和实现文件:-

    标题 AnchorLine.h

    #import <MapKit/MapKit.h>
    
    @interface AnchorLine : NSObject <MKOverlay> {
        MKPolyline* polyline;
    }
    
    @property (nonatomic, retain) MKPolyline* polyline;
    
    + (AnchorLine*)initWithPolyline: (MKPolyline*) line;
    @end
    

    实现AnchorLine.m

    #import "AnchorLine.h"
    
    @implementation AnchorLine
    
    @synthesize polyline;
    
    
    + (AnchorLine*)initWithPolyline: (MKPolyline*) line {
        AnchorLine* anchorLine = [[AnchorLine alloc] init];
        anchorLine.polyline = line;
        return [anchorLine autorelease];
    }
    
    - (void) dealloc {
        [polyline release];
        polyline = nil;
        [super dealloc];
    }
    
    #pragma mark MKOverlay
    //@property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
    - (CLLocationCoordinate2D) coordinate {
        return [polyline coordinate];
    }
    
    //@property (nonatomic, readonly) MKMapRect boundingMapRect;
    - (MKMapRect) boundingMapRect {
        return [polyline boundingMapRect];
    }
    
    - (BOOL)intersectsMapRect:(MKMapRect)mapRect {
        return [polyline intersectsMapRect:mapRect];
    }
    
    - (MKMapPoint *) points {
        return [polyline points];
    }
    
    
    -(NSUInteger) pointCount {
        return [polyline pointCount];
    }
    
    - (void)getCoordinates:(CLLocationCoordinate2D *)coords range:(NSRange)range {
        return [polyline getCoordinates:coords range:range];
    }
    
    @end
    

    希望对某人有所帮助。

    【讨论】:

      【解决方案2】:

      你可以set an associated object attribute的班级。这允许您将实例变量绑定到现有类。确保您自己正确清理。

      【讨论】:

        【解决方案3】:

        MKPolyline 确实没有自己的 init 方法。事实上,在 MKPolyline 的继承链中,唯一具有 init 方法的类是 NSObject。

        所以当我继承 MKPolyline 时,我只是覆盖了 NSObject 定义的 init 方法...

        -(id) init {
            self = [super init];
            if(self) {
                //my initialization here
            }
            return self;
        }
        

        那么当你想用坐标实例化你的子类时,你可能会做这样的事情......

        -MyPolyline* myPolyline = (MyPolyline*)[MyPolyline polylineWithCoordinates:coordinates count:coordinateCount];
        

        【讨论】:

        • 问题在于没有办法设置坐标,因为坐标是只读属性,只能通过便捷方法设置。我也希望继承 MKPolyline,只是为了向它添加一条信息,但似乎我不能这样做。
        • 有一种方法可以在 MKPolyline 的子类上设置坐标,这里有一个代码 sn-p... MyPolyline* myPolyline = (MyPolyline*)[MyPolyline polylineWithCoordinates:coordinates count:coordinateCount];
        • polylineWithCoordinates 总是返回一个 MKPolyline...它永远不会返回一个 MyPolyline。因此,即使你这样转换它,你所做的只是告诉编译器它是一个 MyPolyline。在内存中它实际上仍然是一个 MKPolyline。
        • 我能告诉你的是,这是我正在使用的代码,它可以工作。我已将数据成员添加到 MyPolyline 类,并且可以毫无问题地读取和设置它们。
        • 使用该代码,您正在将现有对象引用替换为对另一个新对象(MKPolyline)的引用。 Gendolkari 是对的,它不应该起作用。如果确实如此,那只是巧合。它会在最糟糕的时刻停止工作。
        【解决方案4】:

        更新:还有另一种选择(可能更好)为此使用消息转发(如-forwardingTargetForSelector 或其他东西)。

        我今天遇到了同样的问题,但想出了其他解决方案。我没有使用 Wayne 建议的关联对象属性的东西,而是将MKPolyline 封装在另一个类中并将MKOverlay 协议的消息传输给它。

        所以我在 .h 中有类似的东西:

        @interface MyOverlay : NSObject <MKOverlay>
        {
            MKPolyline* polyline;
            id object;
        }
        
        @property (nonatomic, retain) id object;
        @property (nonatomic, retain) MKPolyline* polyline;
        
        + (MyOverlay*)myOverlayWithObject: (id)anObject;
        
        @end
        

        在 .m 中:

        @implementation MyOverlay
        @synthesize object;
        @synthesize polyline;
        
        
        + (MyOverlay*)routePartOverlayWithObject: (id)anObject {    
        
            MyOverlay* myOverlay = [[MyOverlay alloc] init];
        
            ... generating MKPolyline ...
        
            myOverlay.polyline = ... generated polyline ...;
            routePartOverlay.object = anObject;
        
        
            return [myOverlay autorelease];
        }
        
        - (void) dealloc {
            [cdRoutePart release]; cdRoutePart = nil;
            [polyline release]; polyline = nil;
        
            [super dealloc];
        }
        
        #pragma mark MKOverlay
        //@property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
        - (CLLocationCoordinate2D) coordinate {
            return [polyline coordinate];
        }
        
        //@property (nonatomic, readonly) MKMapRect boundingMapRect;
        - (MKMapRect) boundingMapRect {
            return [polyline boundingMapRect];
        }
        
        - (BOOL)intersectsMapRect:(MKMapRect)mapRect {
            return [polyline intersectsMapRect:mapRect];
        }
        
        @end
        

        所以MyOverlay 的行为类似于MKPolyline(符合MKOverlay),同时我可以用它做任何事情,拥有尽可能多的属性。

        【讨论】:

        • 投反对票的人能解释一下这个答案有什么问题吗?
        【解决方案5】:

        我重写了jmathew's excellent answer,这是我在其他任何地方都找不到的,它的作用就像魅力一样。 Swift 中的一个小修改版本:

        final class CustomPolyline: MKPolyline {
            private(set) var color: UIColor?
            private(set) var width: CGFloat?
        
            convenience init(coordinates: [CLLocationCoordinate2D], color: UIColor, width: CGFloat) {
                self.init(coordinates: coordinates, count: coordinates.count)
                self.color = color
                self.width = width
            }
        }
        

        【讨论】:

          【解决方案6】:

          到目前为止,这里提到的内容对我来说并不奏效,但我根据其他答案和一些独立研究管理了一个解决方案。我对此不是 100% 确定的,但是如果您使用在内部调用正确的“init”方法的静态方法调用,您可以将 MKPolyline 转换为自定义子类

          (CustomPolyline*)[CustomPolyline polylineWithCoordinates:coordinates count:coordinateCount]
          

          上述方法不起作用,因为polylineWithCoordinates 只为MKPolyline 对象而不是CustomPolyline 分配内存。我怀疑内部发生的事情是polylineWithCoordinates 以类似于[MKPolyline otherInitMethod:...] 的方式调用另一个初始化方法。而且它没有分配适当的内存量,因为它现在使用MKPolyline 静态方法调用而不是我们的CustomPolyline 静态调用。

          但是如果我们使用

          (CustomPolyline*)[CustomPolyline polylineWithPoints:polyline.points count:polyline.pointCount];
          

          确实有效。我认为这是因为polylineWithPoints 正在使用一个返回id 的初始化程序,而不仅仅是链接到另一个方法调用。由于我们使用CustomPolyline 类调用它,初始化程序为CustomPolyline 而不是MKPolyline 分配内存。

          我可能完全错了它为什么起作用。但我已经对此进行了测试,它似乎工作正常。 MKPolygon 可以以类似的方式扩展。在那种情况下,我认为正确的静态方法是MKPolygon polygonWithCoordinates:points count:pointSet.count]]

          我的实现供参考:

          CustomPolyline.h

          #import <MapKit/MapKit.h>
          
          typedef enum {
              CustomPolylineTypeNone = 0,
              CustomPolylineDifferentStrokes
          } CustomPolylineType;
          
          /**
           * CustomPolyline wraps MKPolyline with additional information about a polyline useful for differentiation.
           */
          @interface CustomPolyline : MKPolyline
          
          @property CustomPolylineType type;
          
          -(CustomPolyline*)initWithMKPolyline:(MKPolyline*)polyline;
          
          @end
          

          CustomPolyline.m

          #import "CustomPolyline.h"
          
          @implementation CustomPolyline
          
          @synthesize type;
          
          /**
           * Takes an MKPolyline and uses its attributes to create a new CustomPolyline
           */
          -(CustomPolyline*)initWithMKPolyline:(MKPolyline*)polyline
          {
              // We must use the this specific class function in this manner to generate an actual
              // CustomPolyline object as opposed to a MKPolyline by a different name
              return (CustomPolyline*)[CustomPolyline polylineWithPoints:polyline.points count:polyline.pointCount];
          }
          
          @end
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2023-04-05
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-03-12
            • 2013-11-22
            • 1970-01-01
            • 2014-02-13
            相关资源
            最近更新 更多