尝试实现委托继承

Ser*_*nce 5 iphone cocoa-touch delegates design-patterns ios

我有一个名为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
Run Code Online (Sandbox Code Playgroud)

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];
        }

        ...
}
Run Code Online (Sandbox Code Playgroud)

ToolbarViewDelegate.h

@class ToolbarView;

@protocol ToolbarViewDelegate

@required

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

@end
Run Code Online (Sandbox Code Playgroud)

DraggableToolbarView.h

#import"ToolbarView.h"

@protocol DraggableToolbarViewDelegate;

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

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

@end
Run Code Online (Sandbox Code Playgroud)

DraggableToolbarView.m

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

...

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

  ...

}

...
Run Code Online (Sandbox Code Playgroud)

DraggableToolbarViewDelegate.h

#import "ToolbarViewDelegate.h"

@class DraggableToolbarView;

@protocol DraggableToolbarViewDelegate <ToolbarViewDelegate>

@required

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

@end
Run Code Online (Sandbox Code Playgroud)

SomeViewController.h

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

@interface SomeViewController : UIViewController <ToolbarViewDelegate, DraggableToolbarViewDelegate>
{

}
@end
Run Code Online (Sandbox Code Playgroud)

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];

...
Run Code Online (Sandbox Code Playgroud)

当我这样做时,只有DraggableToolbarDelegate方法响应.但是当我也这样做的[drabbleToolbarView setToolbarViewDelegate:self]时候.我已经尝试单独执行每个委托没有继承,它工作正常,所以我认为问题不在代码的任何其他部分.

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

更新:添加了更多代码

Jos*_*ell 6

在您的代码中,任何给定的DraggableToolbarView实例都有两个连接到委托的属性,一个叫做toolbarViewDelegate它从超类继承,另一个叫做自己draggableToolbarViewDelegate定义DraggableToolbarView.如果您希望控制器获取所有委托消息,则必须设置这两个.

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

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

@interface ToolbarView : UIView <UIGestureRecognizerDelegate>
@property (nonatomic, assign) id <ToolbarViewDelegate> delegate;
@end
Run Code Online (Sandbox Code Playgroud)

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

@interface DraggableToolbarView : ToolbarView
@property (nonatomic, assign) id <DraggableToolbarViewDelegate> delegate;
@end
Run Code Online (Sandbox Code Playgroud)

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

// In superclass
@synthesize delegate;
// In subclass
@synthesize delegate = delegate_;
Run Code Online (Sandbox Code Playgroud)

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

- (void)showBars 
{

    if (self.delegate)
    {
        [self.delegate ...

- (void)drag:(UIPanGestureRecognizer *)sender
{
    //...
    if (self.delegate)
    {
        [self.delegate ...
Run Code Online (Sandbox Code Playgroud)

现在您可以发送setDelegate:到a DraggableToolbarView,它将使用相同的委托来进行拖动方法和显示/隐藏方法.

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

@protocol DraggableToolbarViewDelegate <ToolbarViewDelegate>
Run Code Online (Sandbox Code Playgroud)

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

在这种情况下,这意味着a DraggableToolbarView可以期望其委托实现方法ToolbarViewDelegate.