简体   繁体   English

Objective-C - 子类中委托的子类

[英]Objective-C — Subclass of delegate in subclass

This is a fairly complicated inheritance hierarchy, so bear with me (I've tried to simplify things rather than state the exact case I am using which is even more complex):- 这是一个相当复杂的继承层次结构,所以忍受我(我试图简化事情,而不是陈述我使用的确切情况,这更复杂): -

Let's say I create a subclass of UITextField called TextField which is my own custom enhanced general-purpose textfield. 假设我创建了一个名为TextFieldUITextField子类,它是我自己的自定义增强通用文本字段。 Now, in order to provide this enhanced functionality, in the init method of TextField , I set super.delegate = self so that all the delegate methods from UITextField are sent to TextField . 现在,为了提供这种增强功能,在TextFieldinit方法中,我设置了super.delegate = self以便将UITextField中的所有委托方法发送到TextField TextField implements the UITextFieldDelegate protocol and receives those delegate methods to do something interesting. TextField实现UITextFieldDelegate协议并接收这些委托方法以执行一些有趣的操作。

However, in turn, I want to make it so that TextField has it's own delegate. 但是,反过来,我想让它成为TextField拥有它自己的委托。 So I create a new protocol called TextFieldDelegate (note the lack of UI -prefix!) and give TextField an ivar id<TextFieldDelegate> __weak delegate with corresponding property so that other classes can receive delegate methods from TextField . 所以我创建了一个名为TextFieldDelegate的新协议(注意缺少UI -prefix!),并为TextField一个具有相应属性的ivar id<TextFieldDelegate> __weak delegate ,以便其他类可以从TextField接收委托方法。

I hope you're still with me, because I haven't done anything too complex so far. 我希望你还和我在一起,因为到目前为止我还没有做过任何太复杂的事情。 But let's say that now, I create another custom subclass of TextField , let's call it PasswordTextField (in real life, one probably wouldn't need to create a subclass just to implement a password functionality, but let's assume that there is some fairly sophisticated implementation that would require this). 但是让我们说现在,我创建另一个TextField自定义子类,让我们称之为PasswordTextField (在现实生活中,人们可能不需要创建一个子类来实现密码功能,但让我们假设有一些相当复杂的实现这需要这个)。

Let's also assume that I want to make it so that PasswordTextField (which like TextField has a delegate property) is able to send an enhanced set of delegate methods. 让我们假设我想让它成为PasswordTextField (类似TextField具有委托属性)能够发送一组增强的委托方法。 For example, maybe it can send a method passwordIsSecure which is sent once a password has reached a required level of complexity. 例如,也许它可以发送一个方法passwordIsSecure ,一旦密码达到所需的复杂程度就会发送该方法。 Now since this behaviour that wouldn't be found in the regular TextField , I create a new protocol: PasswordTextFieldDelegate <TextFieldDelegate> which defines the new delegate methods for PasswordTextField and inherits all of the delegate methods sent by TextField . 现在,由于在常规TextField找不到这种行为,我创建了一个新协议: PasswordTextFieldDelegate <TextFieldDelegate> ,它定义了PasswordTextField的新委托方法, 继承了TextField发送的所有委托方法。

The problem is: how do I do implement this in PasswordTextField ? 问题是:我如何在PasswordTextField实现它? Things that don't work: 不起作用的事情:

Inheritance 遗产

I cannot simply inherit the delegate from TextField , because TextField 's delegate conforms only to TextFieldDelegate and not PasswordTextFieldDelegate , so I can't send methods like [delegate passwordIsSecure] because TextFieldDelegate has no such method. 我不能简单地从TextField继承委托,因为TextField的委托只符合TextFieldDelegate而不是PasswordTextFieldDelegate ,所以我不能发送像[delegate passwordIsSecure]这样的方法,因为TextFieldDelegate没有这样的方法。

Overriding ivar 压倒伊娃

I could try declaring an ivar in PasswordTextField called delegate, but the compiler complains that this is a duplicate declaration, because of course there is already an ivar called delegate in the superclass, so this doesn't work either*. 我可以尝试在PasswordTextField声明一个名为delegate的ivar,但编译器抱怨这是一个重复的声明,因为当然在超类中已经有一个名为delegate的ivar,所以这也不起作用*。

Modifying the superclass 修改超类

I could go back to the TextField class and redefine the delegate to implement both TextFieldDelegate and PasswordTextFieldDelegate , but this seems messy and tells TextField that it can send PasswordTextFieldDelegate methods, which of course, it can't! 我可以回到TextField类并重新定义委托以实现TextFieldDelegate PasswordTextFieldDelegate ,但这看起来很乱并且告诉TextField它可以发送PasswordTextFieldDelegate方法,当然,它不能!

I haven't tried this one, simply because it seems to break every sensible coding rule in the book. 我没有试过这个,只是因为它似乎打破了书中所有合理的编码规则。

In summary, there must be some way of doing this such that a subclass of a class can have it's own delegate that's a sub-delegate of the superclass's delegate and for all of this to fit together nicely, but I just can't figure it out! 总而言之,必须有一些方法来做到这一点,这样一个类的子类可以拥有它自己的委托,它是超类委托的子委托,并且所有这些都可以很好地融合在一起,但我无法理解它出来了! Any ideas? 有任何想法吗?

(* As a side issue, I don't understand why the compiler complains when PasswordTextField declares a "duplicate" ivar named delegate, but doesn't complain when TextField declares an ivar named delegate which is presumably a duplicate of UITextField 's property called delegate!) (*作为一个副作用,我不明白为什么编译器会在PasswordTextField声明一个名为delegate的“重复”ivar时抱怨,但是当TextField声明一个名为delegate的ivar时,它不会抱怨,这可能是UITextField属性的副本代表!)

UITextField delegate ivar is named _delegate, not delegate. UITextField委托ivar名为_delegate,而不是委托。 Hence why you get away with declaring it again in TextField, but not in PasswordTextField. 因此,为什么你在TextField中再次声明它,但在PasswordTextField中却没有。

As for your delegate inheritance problem. 至于你的委托继承问题。 I'm not sure ObjectiveC supports what you want. 我不确定ObjectiveC是否支持你想要的东西。

You may just have to type your delegate 'id', instead of 'id<TextFieldDelegate>'. 您可能只需要键入您的委托'id',而不是'id <TextFieldDelegate>'。 Then you could override setDelegate and ensure that the delegate passed in conformsToProtocol. 然后你可以覆盖setDelegate并确保委托传递conformsToProtocol。 However, you would lose your compile time checks here and only have the runtime check of conformsToProtocol 但是,您将丢失此处的编译时检查,并且仅对conformsToProtocol进行运行时检查

So, there! 所以,那里! works.. and manages to have the compile-time warnings as well.. 工作..并设法有编译时警告..

SimpleParent.h SimpleParent.h

@protocol Parentprotocol <NSObject>

@end

@interface SimpleParent : NSObject {
    id<Parentprotocol> obj;
}

@property (retain) id<Parentprotocol> obj;

@end

SimpleParent.m SimpleParent.m

#import "SimpleParent.h"

@implementation SimpleParent
@synthesize obj;

@end

SimpleChild.h SimpleChild.h

#import <Foundation/Foundation.h>
#import "SimpleParent.h"

@protocol SimpleChildProtocol <Parentprotocol>


@end

@interface SimpleChild : NSObject

@property (assign) id<SimpleChildProtocol> obj;

@end

SimpleChild.m SimpleChild.m

#import "SimpleChild.h"

@implementation SimpleChild
@synthesize obj;

@end

It is a quite confusing question, so forgive me if I'm missing the point, but it seems like your three different inheritance levels each have different requirements from their delegate, ergo each delegate would have to conform to a different protocol, so would it be a solution to hold each level's delegate as a differently named ivar, and as a different reference? 这是一个相当令人困惑的问题,所以请原谅我,如果我错过了这一点,但看起来你的三个不同的继承级别每个都有不同的委托要求,每个代表都必须遵循不同的协议,所以它会是一个解决方案,将每个级别的委托作为一个不同名称的ivar,并作为一个不同的参考?

For example, your base class would have its delegate , which you have decided will be assigned to the first inheriting subclass. 例如,您的基类将具有其delegate ,您已决定将其分配给第一个继承的子类。 This has it's own delegate, called level1delegate , and the next level down has another delegate, called level2delegate . 它有自己的委托,名为level1delegate ,下一级别有另一个委托,名为level2delegate You could of course set all three of these to the same object if that object conformed to all three protocols. 如果该对象符合所有三个协议,您当然可以将所有这三个设置为同一个对象。

Basically, there's no rule that says a delegate has to be called "delegate", so don't tear yourself apart trying not to break it. 基本上,没有规则说代表必须被称为“代表”,所以不要因为不打破它而撕裂自己。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM