MKMapViewDelegate производный класс и назначение делегата

#iphone #objective-c #ios

#iPhone #objective-c #iOS

Вопрос:

Вероятно, это скорее вопрос objective-c по сравнению с iOS, но я видел несколько примеров кода, похожих на следующие, которые я хотел бы лучше понять.

 @interface MyMapView : MKMapView <MKMapViewDelegate> {
// ivars specific to derived class
}

@property(nonatomic,assign) id<MKMapViewDelegate> delegate;

@end

@implementation MyMapView
- (id) initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self)
    {
        // initialize the ivars specific to this class

        // Q1: Why invoke super on this delegate that's also a property of this class?    
        super.delegate = self;

        zoomLevel = self.visibleMapRect.size.width * self.visibleMapRect.size.height;
    }
    return self;
}
#pragma mark - MKMapViewDelegate methods
// Q2: Why intercept these callbacks, only to invoke the delegate?
- (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated
{
    if( [delegate respondsToSelector:@selector(mapView:regionWillChangeAnimated:)] )
    {
        [delegate mapView:mapView regionWillChangeAnimated:animated];
    } 
}

@end
  

Мои два вопроса:
1. Зачем вызывать super.delegate, а также объявлять только «делегат» как свойство?
2. Зачем перехватывать все вызовы делегата только для того, чтобы переслать их обратно делегату?

Я ценю любую информацию.

Ответ №1:

В документации Apple явно указано, что вам следует избегать подкласса MKMapView :

http://developer.apple.com/library/ios/#documentation/MapKit/Reference/MKMapView_Class/MKMapView/MKMapView.html#//apple_ref/doc/uid/TP40008205

Хотя вам не следует создавать подкласс самого класса MKMapView, вы можете получить информацию о поведении представления карты, предоставив объект делегата.

Поэтому я предполагаю, что этот шаблон делегирования «вперед» используется, чтобы не нарушать работу.

Я использую немного другой подход к подклассу MKMapView . Чтобы минимизировать поломку, я использую два класса. Тот, который подкласс MKMapView и просто переопределяет метод init / dealloc и присваивает / освобождает delegate свойство экземпляру другого класса. Другой класс является подклассом NSObject , который реализует MKMapViewDelegate протокол и будет выполнять реальную работу.

MyMapView.h

 @interface MyMapView : MKMapView
@end
  

MyMapView.m

 // private map delegate class
@interface MapDelegate : NSObject <MKMapViewDelegate>
// instance is not alive longer then MKMapView so use assign to also solve
// problem with circular retain
@property(nonatomic, assign) MKMapView *mapView;
@end

@implementation MapDelegate
@synthesize mapView;

- (id)initWithMapView:(ReportsMapView *)aMapView {
  self = [super init];
  if (self == nil) {
    return nil;
  }

  self.mapView = aMapView;

  return self;
}

// MKMapViewDelegate methods and other stuff goes here

@end

@implementation MyMapView
- (id)init {
  self = [super init];
  if (self == nil) {
    return nil;
  }

  // delegate is a assign property
  self.delegate = [[MapDelegate alloc] initWithMapView:self];

  return self;
}

- (void)dealloc {
  ((MapDelegate *)self.delegate).mapView = nil;
  [self.delegate release];
  self.delegate = nil;

  [super dealloc];
}
@end
  

mapView Свойство для MapDelegate класса строго не требуется, но, вероятно, полезно, если вы хотите что-то сделать с представлением карты, что не является результатом какого MKMapViewDelegate -либо вызова метода, таймеров и т. Д.

Ответ №2:

  1. Зачем вызывать super.delegate, а также объявлять только «делегат» как свойство? Ans. Поскольку вы создаете пользовательский mapview, важно также вызывать делегатов.Мы вызываем делегат суперкласса для отправки управления из пользовательского Mapview.

  2. Зачем перехватывать все вызовы делегата только для того, чтобы переслать их обратно делегату? Ans.В этой строке кода мы отправляем обратно элемент управления этому методу делегирования, объявленному в суперклассе, чтобы сделать что-то полезное.

Надеюсь, это решит запрос.