2011-02-09 9 views
9

Buduję aplikację opartą na MapKit dla iPhone'a.Czy można dziedziczyć z MKPolyline

Mam wiele MKolinesów dodanych do mapy.

Jednak zamiast mieć MKPolyline, chciałbym mieć własną klasę modelu zgodną z protokołem MKOverlay dodanym do mapy, aby uzyskać dostęp do właściwości modelu podczas tworzenia odpowiedniego widoku w mapView: viewForOverlay.

Problem polega na tym, że nie mogę znaleźć sposobu na dziedziczenie z MKPolyline, ponieważ nie ma ona żadnych metod inicjowania, które można wywołać z podklasy 'init. Możesz je tworzyć tylko za pomocą wygodnych metod.

Jak mogę połączyć właściwości modelu i zachowanie MKPolyline?

Odpowiedz

2

To prawda, że ​​MKPolyline nie ma własnej metody init. W rzeczywistości jedyną klasą w łańcuchu dziedziczenia MKPolyline, która ma metodę init, jest NSObject.

Więc kiedy podklasy MKPolyline Właśnie overrode metodę init, zdefiniowany przez NSObject ...

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

Potem, gdy chcesz instancję swoją podklasę z współrzędne można zrobić coś takiego ...

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

Problem z tym jest to, że nie ma wtedy możliwości ustawienia współrzędnych, ponieważ współrzędne są właściwością tylko do odczytu i można je ustawić tylko za pomocą metody wygody. Ja także liczyłem na podklasę MKPolyline, tylko po to, żeby dodać do niej informację, ale wygląda na to, że nie mogę tego zrobić. – GendoIkari

+0

Istnieje sposób ustawiania współrzędnych na podklasie MKPolyline, tutaj jest fragment kodu ... MyPolyline * myPolyline = (MyPolyline *) [Polilinia MyPolylineWith Współrzędne: współrzędne liczba: coordinateCount]; –

+3

polylineWithCoordinates zawsze zwraca MKPolyline ... nigdy nie zwróci MyPolyline. Więc nawet jeśli rzucisz to w ten sposób, wszystko, co robisz, mówi kompilatorowi, że jest to MyPolyline. W pamięci nadal będzie to MPPolyline. – GendoIkari

2

AKTUALIZACJA: Jest jeszcze jedna opcja (może być lepiej) do korzystania z przekazywania wiadomości w tym celu (np. -forwardingTargetForSelector lub inne).

Miałem ten sam problem dzisiaj, ale wymyśliłem inne rozwiązanie. Zamiast używać sugestii związanych z atrybutem obiektów związanych z Wayne, po prostu zamknąłem w innej klasie MKPolyline i przesłałem do niego komunikaty protokołu z MKOverlay.

Więc mam coś w ncurses.h:

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

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

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

@end 

A w .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 więc zachowuje się jak MKPolyline (zgodną MKOverlay) oraz w tym samym czasie mogę z tym zrobić, mając tyle właściwości, ile potrzebuję.

+0

Czy osoba zmarła może wyjaśnić, co jest nie tak z tą odpowiedzią? –

7

kod MANIAK_dobrii jest do zrobienia, ale znalazłem musiałem wdrożyć kilka dodatkowych metod MKMultiPoint aby zmusić go do pracy, tutaj są moje kompletne pliki nagłówkowe i wdrożeniowe dla AnchorLine klasy I używane: -

Header AnchorLine .h

#import <MapKit/MapKit.h> 

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

@property (nonatomic, retain) MKPolyline* polyline; 

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

AnchorLine.m Realizacja

#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 

nadzieja, że ​​ktoś pomaga.

0

To, co tu dotąd wspominałem, nie sprawdziło się, ale udało mi się znaleźć rozwiązanie oparte na innych odpowiedziach i kilku niezależnych badaniach. Nie jestem w 100% pewien tego, ale możesz rzucić MKPolyline w niestandardową podklasę tylko, jeśli używasz statycznego wywołania metody, która wewnętrznie wywołuje właściwą metodę "init".

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

Powyższe nie będzie działać, ponieważ polylineWithCoordinates tylko przydziela pamięć dla obiektu MKPolyline i nie CustomPolyline. Podejrzewam, że wewnętrznie dzieje się tak, że polylineWithCoordinates nazywa inną metodę inicjalizującą w sposób podobny do: [MKPolyline otherInitMethod:...]. I nie przypisuje odpowiedniej ilości pamięci, ponieważ teraz używa statycznego wywołania metody, a nie naszego statycznego wywołania CustomPolyline.

Jednak jeśli używamy

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

To działa. Myślę, że to dlatego, że polylineWithPoints używa inicjalizatora, który zwraca id nie tylko łańcuchowe do innego wywołania metody. A ponieważ wywoływaliśmy go przy użyciu klasy CustomPolyline inicjator przydziela pamięć dla CustomPolyline, a nie MKPolyline.

Mogę się mylić, dlaczego to działa. Ale testowałem to i wygląda na to, że działa dobrze. MKPolygon może zostać przedłużony w podobny sposób. W tym przypadku myślę, że właściwa metoda statyczna w użyciu jest MKPolygon polygonWithCoordinates:points count:pointSet.count]]

Moja implementacja dla odniesienia:

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 
Powiązane problemy