2011-02-09 9 views
9

Sto costruendo un'app basata su MapKit per iPhone.E 'possibile ereditare da MKPolyline

Ho aggiunto un numero di MKPolylines alla mappa.

Tuttavia, invece di avere una MKPolyline, mi piacerebbe avere la mia classe Model conforme al protocollo MKOverlay aggiunto alla mappa in modo che possa accedere alle proprietà del modello quando si crea la vista corrispondente in mapView: viewForOverlay.

Il problema è che non riesco a trovare il modo di ereditare da MKPolyline perché non ha alcun metodo di init che posso chiamare dalla sottoclasse 'init. Puoi crearli solo usando i metodi di convenienza.

Come posso unire le proprietà del modello e il comportamento di MKPolyline?

risposta

4

È possibile set an associated object attribute della classe. Ciò consente di associare una variabile di istanza a una classe esistente. Assicurati di pulire correttamente dopo te stesso.

2

È vero che MKPolyline non ha il proprio metodo init. In effetti, l'unica classe nella catena ereditaria di MKPolyline che ha un metodo init è NSObject.

Così, quando ho sottoclasse MKPolyline ho appena escludeva il metodo init definito da NSObject ...

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

Poi, quando si vuole istanziare la sottoclasse con le coordinate si potrebbe fare qualcosa di simile ...

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

problema con quello è che non c'è quindi modo di impostare le coordinate, poiché le coordinate sono proprietà di sola lettura e possono essere impostate solo con il metodo di convenienza. Anch'io speravo di sottoclasse MKPolyline, solo per aggiungere un pezzo di informazione ad esso, ma sembra che non possa farlo. – GendoIkari

+0

C'è un modo per impostare le coordinate su una sottoclasse di MKPolyline, ecco uno snippet di codice ... MyPolyline * myPolyline = (MyPolyline *) [MyPolyline polylineWithCoordinates: coordinate count: coordinateCount]; –

+3

polylineWithCoordinates restituisce sempre un MKPolyline ... non restituirà mai MyPolyline. Quindi, anche se lo lanci in quel modo, tutto quello che stai facendo è dire al compilatore che si tratta di una MyPolyline. In memoria sarà ancora effettivamente un MKPolyline. – GendoIkari

2

AGGIORNAMENTO: C'è un'altra opzione (potrebbe essere meglio) per utilizzare l'inoltro dei messaggi per questo (come -forwardingTargetForSelector o roba del genere).

Ho avuto lo stesso problema oggi ma ho trovato altra soluzione. Invece di usare suggerito da roba di attributo dell'oggetto Wayne ho appena incapsulato MKPolyline in un'altra classe e trasferito i messaggi del protocollo MKOverlay ad esso.

Così ho qualcosa di simile in .h:

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

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

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

@end 

E in .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 

Così MyOverlay si comporta come MKPolyline (conforme a MKOverlay) e allo stesso tempo mi può fare qualsiasi cosa con esso, con tutte le proprietà di cui ho bisogno.

+0

La persona downvote potrebbe spiegare cosa c'è di sbagliato in questa risposta? –

7

codice di MANIAK_dobrii è la strada da percorrere, ma ho trovato ho dovuto implementare alcuni metodi MKMultiPoint aggiuntivi per farlo funzionare, qui ci sono i miei file di intestazione e di implementazione completi per una classe AnchorLine ho usato: -

Header AnchorLine .h

#import <MapKit/MapKit.h> 

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

@property (nonatomic, retain) MKPolyline* polyline; 

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

Attuazione 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 

Speranza che aiuta qualcuno.

0

Le cose qui menzionate finora non ha funzionato per me, ma ho gestito una soluzione basata sulle altre risposte e alcune ricerche indipendenti. Non sono sicuro al 100% in questo, ma puoi trasmettere una MKPolyline in una sottoclasse personalizzata solo se si utilizza la chiamata al metodo statico che chiama internamente il metodo "init" corretto.

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

che questo non funzionerà perché polylineWithCoordinates solo alloca memoria per un oggetto MKPolyline e non CustomPolyline. Sospetto che ciò che sta accadendo internamente sia che lo polylineWithCoordinates chiama un altro metodo di inizializzazione in un modo simile a: [MKPolyline otherInitMethod:...]. E non sta allocando la giusta quantità di memoria perché ora sta usando una chiamata al metodo statico MKPolyline e non alla nostra chiamata statica CustomPolyline.

Tuttavia, se usiamo

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

funziona. Penso che questo sia dovuto al fatto che polylineWithPoints utilizza un inizializzatore che restituisce un id non solo concatenando ad un'altra chiamata di metodo. E poiché l'abbiamo chiamato usando la classe CustomPolyline, l'inizializzatore alloca la memoria per CustomPolyline non MKPolyline.

Potrei sbagliarmi completamente sul perché funzioni. Ma ho provato questo e sembra funzionare bene. MKPolygon può essere esteso in modo simile. In questo caso penso che il metodo statico corretto da utilizzare è MKPolygon polygonWithCoordinates:points count:pointSet.count]]

mia implementazione di riferimento:

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