从子类 setDelegate 设置超类委托

Set superclass delegate from subclass setDelegate

我有一个超级class A,它有一个BaseModalViewControllerDelegate 协议和一个用于id<BaseModalViewControllerDelegate> delegate 的保留属性。 我还有 class B,A 的子 class,它有一个 ModalLoginDelegate 协议和一个保留 属性 用于 id<ModalLoginDelegate> delegate

现在,我将 B 的 setter 方法设置为 class 委托此方法:

-(void)setDelegate: (id<ModalLoginDelegate>)delegate
{
    _delegate = delegate;
    [super setDelegate: (id<BaseModalViewControllerDelegate>)delegate;
}

因此,存在实现这两种协议的 RootViewController,但它仅初始化 B class 并将自己设置为 B class 的委托,因为它不知道 B class 是 A.

的子class

您认为这是将 RootVC 设置为两种协议的委托的正确方法吗?谢谢

添加

将 B class 的协议设置为继承自 A class:

@protocol ModalLoginDelegate <BaseModalDelegate>
    // delegate method of subclass
@end

现在,我的 RootVC 不必将自己设置为 BaseModalViewController 的委托。但是现在,当在我的 B class 中我想调用 superclass 的委托方法时,我正在这样做

if (self.loginDelegate)
{
    [self.loginDelegate baseModalViewController: self willDismiss: YES];
}

我认为这不是一个非常干净的方法,所以我在 superclass -(void)pressedCloseButton; 中创建了一个 public 方法,它将执行此操作

-(void)pressedCloseButton
{
    if (self.delegate)
    {
        [self.delegate baseModalViewController: self willDismiss: YES];
    }
}

并且在子class中:

-(IBAction)closeBtnPressed: (id)sender
{
    [super pressedCloseButton];
}

你觉得对吗?

更好的设计是为您的子class实现一个单独的委托属性,比如说loginDelegate。在 subclass 中更改 属性 的类型不是很好的 OO 设计。大多数 OO 语言甚至不允许这样做。

这也确保了消耗 class 是 "aware" 涉及两个单独的委托协议。

RootVC 如果需要实现两个协议,则需要将自己设置为两个委托。您不能指望 class 不知道它需要实现哪些委托协议。如果 RootVC 认为它只处理基础 class 那么它不会设置 loginDelegate 并且不会实现该协议中的方法。

我完全不反对 Paulw11 在这里的回答,但有趣的是,Apple 自己也这样做了。 例子。 UIScrollView 有一个委托 属性

@property (weak, nonatomic) id <UIScrollViewDelegate> delegate;

子类 UITableView 有一个委托 属性

@property (weak, nonatomic) id <UITableViewDelegate> delegate;

当我们在 ObjC 中声明一个协议时,我们通常让该协议扩展 协议。

@protocol BaseModalViewControllerDelegate <NSObject>
-(void)doSomething;
-(NSString *)titleForThing;
@end

现在上面这个协议不仅有这里原型化的方法,还有 协议中的方法原型。它非常像这个协议是另一个协议的 'subclass',也继承了它的所有内容。

如果您使用第二个协议执行此操作

  @protocol ModalLoginDelegate <BaseModalViewControllerDelegate>
        -(void)doAnotherThing;
        -(NSString *)titleForTheOtherThing;
    @end

那么你在这里所做的将与 Apple 对 UITableView 和 UIScrollView 所做的完全一致,因为类型 id 的指针始终也是类型 id 的对象,就像UIButton* 将始终能够作为 UIView* 传入 ...

但如果不这样做,您的

就会出现根本性问题
 -(void)setDelegate:(id<ModalLoginDelegate>)delegate

方法在那里,因为你假设这个对象符合 BaseModalViewControllerDelegate 协议,而你唯一确定的是它符合 ModalLoginDelegate 协议。某些继承的方法可能会使用 self.delegate 不响应的 BaseModalViewControllerDelegate 方法调用 self.delegate。 我希望这会有所帮助:)