Можно ли наследовать от MKPolyline - PullRequest
9 голосов
/ 09 февраля 2011

Я создаю приложение на базе MapKit для iPhone.

У меня есть несколько MKPolylines, добавленных на карту.

Однако вместо MKPolyline мне бы хотелось, чтобы к карте был добавлен мой собственный класс Model, соответствующий протоколу MKOverlay, чтобы я мог получить доступ к свойствам модели при создании соответствующего представления в mapView: viewForOverlay.

Проблема в том, что я не могу найти способ наследования от MKPolyline, потому что у него нет никаких методов init, которые я могу вызвать из подкласса init.Вы можете создавать их только с помощью удобных методов.

Как объединить свойства модели и поведение MKPolyline?

Ответы [ 5 ]

7 голосов
/ 17 мая 2012

Код 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

Надеюсь, это кому-нибудь поможет.

4 голосов
/ 04 марта 2011

Вы можете установить связанный атрибут объекта класса. Это позволяет вам связать переменную экземпляра с существующим классом. Убедитесь, что вы правильно убираете за собой.

2 голосов
/ 12 мая 2012

ОБНОВЛЕНИЕ: есть еще один вариант (может быть лучше), чтобы использовать пересылку сообщений для этого (например, -forwardingTargetForSelector или прочее).

У меня была такая же проблема сегодня, но я нашел другое решение. Вместо использования предложенного Уэйном атрибута связанного объекта я просто инкапсулировал 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

И в .м:

@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), и в то же время я могу делать с ним все что угодно, имея столько свойств, сколько мне нужно.

2 голосов
/ 04 марта 2011

Это правда, что у MKPolyline нет собственного метода init. Фактически единственным классом в цепочке наследования MKPolyline, у которого есть метод init, является NSObject.

Поэтому, когда я вложил в MKPolyline, я просто переопределил метод init, определенный NSObject ...

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

Тогда, когда вы хотите создать экземпляр своего подкласса с координатами, вы можете сделать что-то вроде этого ...

-MyPolyline* myPolyline = (MyPolyline*)[MyPolyline polylineWithCoordinates:coordinates count:coordinateCount];
0 голосов
/ 24 июля 2013

То, что упомянуто здесь до сих пор, мне не совсем помогло, но я нашел решение, основанное на других ответах и ​​некоторых независимых исследованиях. Я не уверен на 100% в этом, но вы можете привести MKPolyline в пользовательский подкласс only , если вы используете статический вызов метода, который вызывает правильный метод init изнутри.

(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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...