尝试实现委托继承

时间:2012-05-26 18:46:44

标签: iphone ios cocoa-touch design-patterns delegates

我有一个名为ToolbarView的类,它是UIView的子类,基本上创建了一个UIView,它顶部有一个消失/重新出现的UIToolbar。我还有一个名为DraggableToolbarView的ToolbarView子类,允许用户在屏幕上拖动视图。

我需要为ToolbarView创建一个委托,以便它可以在工具栏重新出现和消失时通知另一个对象/类。我还需要为DraggableToolbarView创建一个委托,这样我就可以在拖动视图时通知另一个对象/类。 DraggableToolbarViews委托还需要在工具栏重新出现和消失时通知另一个对象/类。

所以我决定实现ToolbarViewDelegate,让DraggableToolbarViewDelegate继承它并拥有自己的方法,如下所示:

ToolbarView.h

#import <UIKit/UIKit.h>

@protocol ToolbarViewDelegate;

@interface ToolbarView : UIView <UIGestureRecognizerDelegate>
{
    id <ToolbarViewDelegate> _toolbarViewDelegate;
}

@property(nonatomic, assign) id <ToolbarViewDelegate> toolbarViewDelegate;

@end

ToolbarView.m

#import "ToolbarView.h"
#import "ToolbarViewDelegate.h"

...

- (void) showBars
{      
       ...
        if (self.toolbarViewDelegate)
        {
            [self.toolbarViewDelegate toolbarViewWillShowToolbar:self];
        }

       ...
}

- (void) hideBars
{
       ...
        if (self.toolbarViewDelegate)
        {
            [self.toolbarViewDelegate toolbarViewWillHideToolbar:self];
        }

        ...
}

ToolbarViewDelegate.h

@class ToolbarView;

@protocol ToolbarViewDelegate

@required

- (void) toolBarViewWillShowToolbar:(ToolbarView *)toolbarView;
- (void) toolBarViewWillHideToolbar:(ToolbarView *)toolbarView;

@end

DraggableToolbarView.h

#import&#34; ToolbarView.h&#34;

@protocol DraggableToolbarViewDelegate;

@interface DraggableToolbarView : ToolbarView
{
    id <DraggableToolbarViewDelegate> _draggableToolbarViewDelegate;
}

@property(nonatomic, assign) id <DraggableToolbarViewDelegate> draggableToolbarViewDelegate;

@end

DraggableToolbarView.m

#import "DraggableToolbarView.h"
#import "DraggableToolbarViewDelegate.h"

...

- (void)drag:(UIPanGestureRecognizer *)sender
{
   ...
        if (self.draggableToolbarViewDelegate)
        {
            [self.draggableToolbarViewDelegate draggableToolbarViewWillDrag:self];
        }

  ...

}

...

DraggableToolbarViewDelegate.h

#import "ToolbarViewDelegate.h"

@class DraggableToolbarView;

@protocol DraggableToolbarViewDelegate <ToolbarViewDelegate>

@required

- (void) draggableToolbarViewWillDrag:(DraggableToolbarView *)draggableToolbarView;

@end

SomeViewController.h

#import <UIKit/UIKit.h>
#import "ToolbarViewDelegate.h"
#import "DraggableToolbarViewDelegate.h"

@interface SomeViewController : UIViewController <ToolbarViewDelegate, DraggableToolbarViewDelegate>
{

}
@end

SomeViewController.m

#import "DraggableToolbarView.h"
...
- (void) toolbarViewWillShowToolbar:(ToolbarView*)toolbarView
{
    //NSLog(@"Toolbar Showed");
}

- (void) toolbarViewWillHideToolbar:(ToolbarView*)toolbarView
{
    //NSLog(@"Toolbar Hidden");
}

- (void) draggableToolbarViewWillDrag:(DraggableToolbarView*)draggableToolbarView
{
    //NSLog(@"Dragged");
}

...

[draggableToolbarView setDraggableToolbarViewDelegate:self];

...

当我这样做时,只有DraggableToolbarDelegate方法正在响应。但是,当我也[drabbleToolbarView setToolbarViewDelegate:self]时,它有效。我已尝试单独执行每个代表而没有继承权,并且工作正常,因此我认为问题不在代码的任何其他部分。

有人可能知道为什么吗?我认为通过使协议继承,我也不必为DraggableToolbar对象设置ToolbarViewDelegate。

更新:添加了更多代码

2 个答案:

答案 0 :(得分:6)

在您的代码中,任何给定的DraggableToolbarView实例都有两个属性来连接到委托,一个名为toolbarViewDelegate,它从其超类继承,另一个名为{{1这是在draggableToolbarViewDelegate本身中定义的。如果您希望控制器获取所有委托消息,您必须设置这两个。

然而,您正在尝试做的事情是可能的。您需要在两个视图类中使用相同的属性名称,以便任何实例只有一个委托连接。

首先,更改超类中委托的名称。 (请注意,您不需要也确实不应该为该属性声明一个ivar - 它是由DraggableToolbarView创建的。)

@synthesize

您将在子类中使用相同的属性名称。

@interface ToolbarView : UIView <UIGestureRecognizerDelegate>
@property (nonatomic, assign) id <ToolbarViewDelegate> delegate;
@end

只要子类中的支持ivar的名称与超类的名称不同,就允许这样做,例如,

@interface DraggableToolbarView : ToolbarView
@property (nonatomic, assign) id <DraggableToolbarViewDelegate> delegate;
@end

现在更改两个视图类中的所有委托消息以使用这一个属性:

// In superclass
@synthesize delegate;
// In subclass
@synthesize delegate = delegate_;

现在您可以将- (void)showBars { if (self.delegate) { [self.delegate ... - (void)drag:(UIPanGestureRecognizer *)sender { //... if (self.delegate) { [self.delegate ... 发送到setDelegate:,它将使用相同的委托来执行拖动方法和显示/隐藏方法。

最后,术语/解释性说明。在回应your previous question时,Caleb使用了正确的术语来表示“堆叠”协议,理查德则没有。协议不会继承,但一个协议可以采用另一个协议。这种关系是相似的,但却截然不同。当一个对象符合协议时,它承诺实现该协议中声明的方法。协议没有实现。采用另一种协议的协议也是如此 - 这两种方法都被宣布存在于两者中。当你写:

DraggableToolbarView

你说任何承诺实现@protocol DraggableToolbarViewDelegate <ToolbarViewDelegate> 方法的对象也会实现DraggableToolbarViewDelegate中的方法。这就是它的意思。同样,没有实现伴随着这个承诺。

在这种情况下,这意味着ToolbarViewDelegate可以指望其委托实施DraggableToolbarView中的方法。

答案 1 :(得分:1)

你没有给出完整的代码,但是从这里的任何内容, 确保

  1. 您的ToolBarView及其子类具有id <ToolBarViewDelegate>委托作为属性。
  2. 您的DraggableToolbarViewDelegate扩展了NSObject协议。
  3. ,您的其他ViewController对象符合委托协议,而不符合工具栏视图。
  4. 一旦您的控制器提供了委托方法的实现并符合协议,请将视图对象的委托设置为self,然后在视图中使用委托属性集来调用这些协议方法。