2015-05-14 3 views
11

Я хочу создать класс, который может наследовать от двух настраиваемых классов. У вас есть идея сделать это, пожалуйста? Пожалуйста, смотрите ниже моего примера:Множественное наследование для IOS

первого класса:

@interface UIZoomableView : UIView 
{ 
    UITapGestureRecognizer *_tapGestureRecognizer; 
} 

и реализация:

- (void)onDoubleTap:(UITapGestureRecognizer *)sender 
{ 
    CGSize newSize; 
    CGPoint centerPoint = self.center; 
    if ([self isSmall]) 
    { 
     newSize = [self bigSize]; 
    } 
    else 
    { 
     newSize = [self smallSize]; 
    } 

    [UIView animateWithDuration:0.3 animations:^{ 
     self.size = newSize; 
     self.center = centerPoint; 
    }]; 
} 

Второй класс:

@interface UIDraggableView : UIView 

    UIPanGestureRecognizer *_panGestureRecognizer; 

@end 

реализация:

- (void)handlePan:(UIPanGestureRecognizer*)sender 
{ 
    .. 
} 

Я хочу создать пользовательский вид, который можно масштабировать и перетаскивать. У вас есть идея сделать это, пожалуйста? (без кода копирования ..)

Я думаю, что-то вроде протоколов, но мне нужно значение по умолчанию для базовых классов? Как я могу реализовать это с помощью протокола или что-то вроде протоколов.

Спасибо за любой ответ!

+6

Objective-C не поддерживает множественное наследование, вы можете найти лучшее решение, чтобы быть протоколы. –

+0

Как я могу реализовать это, пожалуйста? я не хочу свойство, которое является делегатом .. и я хочу значение по умолчанию, например, в масштабируемом представлении. Я хочу по умолчанию небольшой размер, если подкласс не переопределяет функцию, возвращает класс (50,50). – Rebecca

+0

Невозможно установить значения по умолчанию для протокола, так как предполагается, что они не реализованы. Что вы можете сделать, так это наследовать от класса, который реализует протокол, посмотрите на этот вопрос: https://gist.github.com/paulrehkugler/9647085 –

ответ

4

Ближе всего, что вы можете получить для множественного наследования в Objective C с категориями. Это механизм добавления дополнительных методов в уже существующий класс.

Обратите внимание, что это имеет некоторые важные ограничения:

  1. Вы не можете добавлять свойства или Ивар, используя категорию, хотя вы можете использовать associated objects, чтобы получить подобный эффект;
  2. Компилятор не скажет вам, есть ли у вас методы с тем же именем, которые объявлены в классе и категории, или в двух категориях, поэтому вы должны быть осторожны, чтобы избежать столкновения имен;
  3. Это не будет выглядеть как подходящий класс (поскольку Objective C не имеет множественного наследования), поэтому у вас не будет чего-то в вашем коде с именем ScrollableZoomableView, который наследует от ScrollableView и ZoomableView. Это невозможно в Objective C (в отличие от C++, например).
  4. При связывании файлов с категориями вам нужен флаг -ObjC, в противном случае вы получите unrecognized selector ошибки при запуске кода;
  5. Вы не можете получить свой код во время -init или +initialize, потому что они относятся к базовому классу. Вы должны явно инициализировать свои свойства. Вы все равно можете использовать +load;
  6. Вы также не можете перехватывать dealloc, так что вам может потребоваться, чтобы явным образом отменил регистрацию ваших слушателей.

Вы хотите что-то вроде этого:

@interface UIView (Zoomable) 

@property (nonatomic) UITapGestureRecognizer * my_tapGestureRecognizer; 

@end 


@implementation UIView (Zoomable) 

-(void)my_enableZooming() { 
    self.my_tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(my_onDoubleTap:)]; 
    self.my_tapGestureRecognizer.numberOfTapsRequired = 2; 
    [self addGestureRecognizer:self.my_tapGestureRecognizer]; 
} 

-(void)my_disableZooming() { 
    [self removeGestureRecognizer:self.my_tapGestureRecognizer]; 
    self.my_tapGestureRecognizer = nil; 
} 

-(void)my_onDoubleTap:(UITapGestureRecognizer *)sender { 
    ... 
} 

-(UITapGestureRecognizer)my_tapGestureRecognizer { 
    return objc_getAssociatedObject(self, @selector(my_tapGestureRecognizer)); 
} 

-(void)setMy_tapGestureRecognizer:(UITapGestureRecognizer)value { 
    objc_setAssociatedObject(self, @selector(my_tapGestureRecognizer), value, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 
} 

@end 


@interface UIView (Draggable) 

@property (nonatomic) UIPanGestureRecognizer * my_panGestureRecognizer; 

@end 

@implementation UIView (Draggable) 

-(void)my_enableDragging() { 
    self.my_panGestureRecognizer = ...; 
} 

-(void)my_disableDragging() { 
    ... 
} 

-(void)my_handlePan:(UIPanGestureRecognizer*)sender { 
    ... 
} 

-(UIPanGestureRecognizer)my_panGestureRecognizer { 
    return objc_getAssociatedObject(self, @selector(my_panGestureRecognizer)); 
} 

-(void)setMy_panGestureRecognizer:(UIPanGestureRecognizer)value { 
    objc_setAssociatedObject(self, @selector(my_panGestureRecognizer), value, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 
} 

@end 
9

Objective-C не поддерживает множественное наследование. Вы можете использовать протокол, состав и пересылку сообщений для достижения того же результата.

Протокол определяет набор методов, которые должен реализовывать объект (возможно также иметь необязательные методы).Композиция - это в основном метод включения ссылки на другой объект и вызов этого объекта, когда требуется его функциональность. Пересылка сообщений - это механизм, позволяющий объектам передавать сообщения на другие объекты, например объект, который включен в состав композиции.

Яблоко Справка:

Таким образом, в вашем случае композиция может быть решение, ниже приведен пример кода

@interface ClassA : NSObject { 
} 

-(void)methodA; 

@end 

@interface ClassB : NSObject { 
} 

-(void)methodB; 

@end 

@interface MyClass : NSObject { 
    ClassA *a; 
    ClassB *b; 
} 

-(id)initWithA:(ClassA *)anA b:(ClassB *)aB; 

-(void)methodA; 
-(void)methodB; 

@end 

@implementation MyClass 

-(id)initWithA:(ClassA *)anA b:(ClassB *)aB { 
    a = anA ; 
    b = aB ; 
} 

-(void)methodA { 
    [a methodA] ; 
} 

-(void)methodB { 
    [b methodB] ; 
} 

@end 

Если вы не хотите внедрять все методы из ClassA и ClassB в MyClass, вы можете использовать пересылку сообщений в MyClass для обработки всех вызовов метода. Ниже работает отлично, пока ClassA и ClassB не имеют общих методов.

@implementation MyClass 

-(id)initWithA:(ClassA *)anA b:(ClassB *)aB { 
    a = anA ; 
    b = aB ; 
} 

//This method will be called, when MyClass can not handle the method itself 
-(void)forwardInvocation:(NSInvocation *)anInvocation 
{ 
    if ([a respondsToSelector:[anInvocation selector]]) 
     [a invokeWithTarget:someOtherObject]; 
    else if ([b respondsToSelector:[anInvocation selector]]) 
     [b invokeWithTarget:someOtherObject]; 
    else 
     [super forwardInvocation:anInvocation]; 
} 

@end 
2

Возможно, вы также можете ознакомиться с этой статьей в objc.io о поведении. Вы можете создавать перетаскиваемые и масштабируемые поведения, а затем добавлять их во все виды, которые вы хотите.

Here's the article.

 Смежные вопросы

  • Нет связанных вопросов^_^