2011-02-09 13 views
9

? Estoy construyendo una aplicación basada en MapKit para iPhone.¿Es posible heredar de MKPolyline

Tengo un número MKPolylines agregado al mapa.

Sin embargo, en lugar de tener un MKPolyline, me gustaría tener mi propia clase Model conforme al protocolo MKOverlay agregado al mapa para poder acceder a las propiedades del modelo al crear la vista correspondiente en mapView: viewForOverlay.

El problema es que no puedo encontrar la manera de heredar de MKPolyline porque no tiene ningún método de inicio al que pueda llamar desde la subclase 'init. Solo puedes crearlos usando los métodos de conveniencia.

¿Cómo puedo unir las propiedades del modelo y el comportamiento de MKPolyline?

Respuesta

4

Puede set an associated object attribute de la clase. Esto le permite vincular una variable de instancia a una clase existente. Asegúrese de limpiar adecuadamente después de usted mismo.

2

Es cierto que MKPolyline no tiene su propio método init. De hecho, la única clase en la cadena de herencia de MKPolyline que tiene un método init es NSObject.

Así que cuando una subclase MKPolyline acabo hicieron caso omiso del método init definido por NSObject ...

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

Luego, cuando se desea crear una instancia de su subclase con coordenadas que podría hacer algo como esto ...

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

problema con esto es que entonces no hay forma de establecer las coordenadas, ya que las coordenadas son una propiedad de solo lectura y solo se pueden configurar por el método de conveniencia. Yo también esperaba subclasificar a MKPolyline, solo para agregarle una información, pero parece que no puedo hacer esto. – GendoIkari

+0

Hay una manera de establecer las coordenadas en una subclase de MKPolyline, aquí hay un fragmento de código ... MyPolyline * myPolyline = (MyPolyline *) [MyPolyline polylineWithCoordinates: coordinates count: coordinateCount]; –

+3

polylineWithCoordinates siempre devuelve una MKPolyline ... nunca devolverá una MyPolyline. Entonces, incluso si lo lanzas así, todo lo que estás haciendo es decirle al compilador que es MyPolyline. En memoria, seguirá siendo una MKPolyline. – GendoIkari

2

ACTUALIZACIÓN: Hay otra opción (podría ser mejor) para utilizar el reenvío de mensajes para esto (como -forwardingTargetForSelector o esas cosas).

Tuve el mismo problema hoy, pero se me ocurrió otra solución. En lugar de utilizar cosas del atributo de objeto asociado a Wayne sugeridas, simplemente encapsulé MKPolyline en otra clase y le transferí los mensajes del protocolo MKOverlay.

así que tengo algo así como en .h:

@interface MyOverlay : NSObject <MKOverlay> 
{ 
    MKPolyline* polyline; 
    id object; 
} 

@property (nonatomic, retain) id object; 
@property (nonatomic, retain) MKPolyline* polyline; 

+ (MyOverlay*)myOverlayWithObject: (id)anObject; 

@end 

Y en .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 

Así MyOverlay se comporta como MKPolyline (se ajusta a MKOverlay) y, al mismo tiempo que puede hacer cualquier cosa con eso, teniendo tantas propiedades como necesite.

+0

¿Podría la persona que votó negativamente explicar qué pasa con esta respuesta? –

7

código de MANIAK_dobrii es el camino a seguir, pero me pareció que tenía que poner en práctica algunos métodos MKMultiPoint adicionales para conseguir que funcione, aquí están mis completos archivos de encabezado e implementación de una clase AnchorLine utilicé: -

Cabecera AnchorLine .h

#import <MapKit/MapKit.h> 

@interface AnchorLine : NSObject <MKOverlay> { 
    MKPolyline* polyline; 
} 

@property (nonatomic, retain) MKPolyline* polyline; 

+ (AnchorLine*)initWithPolyline: (MKPolyline*) line; 
@end 

AnchorLine.m Implementación

#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 

la esperanza de que ayude a alguien.

0

Lo que he mencionado aquí hasta ahora no me ha funcionado del todo, pero logré una solución basada en las otras respuestas y en algunas investigaciones independientes. No estoy 100% seguro de esto, pero puede convertir un MKPolyline en una subclase personalizada solo si utiliza la llamada al método estático que llama internamente al método 'init' correcto.

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

Lo anterior no funcionará porque polylineWithCoordinates solamente asigna memoria para un objeto MKPolyline y no CustomPolyline. Sospecho que lo que sucede internamente es que polylineWithCoordinates llama a otro método de inicialización de una manera similar a: [MKPolyline otherInitMethod:...]. Y no asigna la cantidad adecuada de memoria porque ahora está utilizando una llamada de método estático MKPolyline y no nuestra llamada estática CustomPolyline.

Sin embargo, si usamos

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

No funciona. Creo que esto se debe a que polylineWithPoints está utilizando un inicializador que devuelve id no solo encadenando a otra llamada de método. Y como lo llamamos usando la clase CustomPolyline, el inicializador asigna memoria para CustomPolyline, no MKPolyline.

Podría estar completamente equivocado sobre por qué funciona. Pero probé esto y parece funcionar bien. MKPolygon se puede extender de una manera similar. En ese caso, creo que el método estático correcto a utilizar es MKPolygon polygonWithCoordinates:points count:pointSet.count]]

Mi aplicación para referencia:

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