2015-05-14 47 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

我該如何執行該操作?我不希望屬性是委託..我想默認值,例如在zoomable視圖我想默認的小尺寸,如果子類不覆蓋函數,類返回(50,50)。 – Rebecca

+0

沒有真正好的方法來設置協議的默認值,因爲它應該是未實現的。你可以做的是從一個實現協議的類繼承,看看這個要點:https://gist.github.com/paulrehkugler/9647085 –

回答

4

您可以在Objective C中獲得多重繼承的最接近的類別是。這些是向已存在的類添加其他方法的機制。

注意,這有一些重要的限制:

  1. 您不能添加使用類別,雖然你可以使用associated objects來獲得類似的效果屬性或高德;
  2. 編譯器不會告訴您,如果您的方法具有在類和類別中聲明的相同名稱或兩種類別,則必須小心以避免名稱衝突;
  3. 這不會顯示爲合適的類(因爲Objective C沒有多重繼承),所以在代碼ScrollableZoomableView中將不會有任何內容從ScrollableViewZoomableView繼承。這在目標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 

如果您不想在MyClass中實現ClassA和ClassB的所有方法,則可以使用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.