6

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

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

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

工具栏视图.h

#import <UIKit/UIKit.h>

@protocol ToolbarViewDelegate;

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

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

@end

工具栏视图.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 "工具栏视图.h"

@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。

更新:添加了更多代码

4

2 回答 2

7

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

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

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

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

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

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

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

// 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:到 a DraggableToolbarView,它会为拖动方法和显示/隐藏方法使用相同的委托。

最后,一个术语/解释性说明。在回答您之前的问题时,Caleb 对“堆叠”协议使用了正确的术语,而 Richard 没有。协议不会相互继承,但一个协议可以采用另一个协议。关系相似,但不同。当一个对象符合协议时,它承诺实现该协议中声明的方法。该协议没有任何实现。一个协议采用另一个协议也是如此——这些方法只是被声明为在两者中都存在。当你写:

@protocol DraggableToolbarViewDelegate <ToolbarViewDelegate>

您是说任何承诺实现DraggableToolbarViewDelegate的方法的对象也将实现来自 的方法ToolbarViewDelegate。这就是它的全部含义。同样,没有实现与该承诺一起出现。

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

于 2012-05-27T21:54:09.813 回答
1

您还没有给出完整的代码,但是从这里的任何内容来看,请确保

  1. 您的 ToolBarView 及其子类有一个id <ToolBarViewDelegate>委托作为属性。
  2. 您的 DraggableToolbarViewDelegate 扩展了 NSObject 协议。
  3. 并且您的其他 ViewController 对象符合委托协议而不是工具栏视图。
  4. 一旦您的控制器实现了委托方法并符合协议,请将视图对象的委托设置为 self,然后使用视图中设置的委托属性来调用这些协议方法。
于 2012-05-26T19:09:47.077 回答