ios - 直接在类上实现时类别方法无效

时间:2014-02-02 19:41:27

标签: ios protocols categories

我有以下设计:

@protocol SomeProtocol <NSObject>

@optional
- (void)someMethod;

@end

@interface SomeObject : NSObject <SomeProtocol>
@end

我想为我的协议提供someMethod的默认工具,所以我创建了一个类似的类别:

@interface SomeObject (SomeCategory) <SomeProtocol>

- (void)someMethod;

@end

@implementation SomeObject (SomeCategory)

- (void)someMethod
{
    // default implementation for all classes implementing the protocol SomeProtocol
}

@end

现在我还想留下实现此方法的自定义实现的可能性。如果我直接在SomeObject类上实现,如下所示:

@interface SomeObject <SomeProtocol>

- (void)someMethod;

@end

@implentation SomeObject

- (void)someMethod
{
    // custom implementation for SomeObject class
}

@end

此实现似乎优先于类别方法。但Apple文档说:

  

如果类别中声明的方法的名称与方法相同   在原始类中,或在另一个类别中的方法相同   class(甚至是超类),行为未定义为哪个   方法实现在运行时使用。

我还没有想到其他可能更好的可能性(比如使用基类和子类)但是我在这里做的是一个好的设计还是必须导致未定义的行为?

提前感谢您的帮助

2 个答案:

答案 0 :(得分:1)

关于此事的文件不太清楚。除了到目前为止所提到的,在文档中的其他一些点上,它说:“当一个类别覆盖一个继承的方法时,该类别中的方法可以像往常一样通过消息调用继承的实现到超级。 ,如果一个类别覆盖了类别类中已经存在的方法,则无法调用原始实现“ - 我将其视为”类别实现将始终运行而不是原始实现“。

我以前读过这篇文章,但直到现在才发现,但this SO answer已经提到过。

就个人而言,我经常使用类别覆盖方法,到目前为止,它给我带来了麻烦。但是,因为我知道我“杀死”了原始实现,所以我只关注这样做的方法,可以安全地假设该类继承了超类的原始实现。

例如,我认为在touchesBegan:withEvent:上的类别中覆盖UIView是安全的,因为该方法已从UIResponder继承而且原始实现仍未受影响且可以(并且应该通过在类别的实施中调用super来达到。

据我所知,抽象或空实现也可以安全地覆盖。例如,我已经覆盖awakeFromNib中的UIScrollView以克服滚动视图不能根据实际内容大小自行设置其contentSize属性的问题,以防它在Interface Builder中创建:

@implementation UIScrollView (MyHandyCategory)

-(void)awakeFromNib {

   [self autoResizeContent];

}

-(void)autoResizeContent {

   NSArray *subViews = [self subviews];
   UIView *contentView = [subViews objectAtIndex:0];
   [self setContentSize:contentView.frame.size];

}

@end

如果你想知道为什么我不把autoresize代码放在awakeFromNib中 - 我希望能够在其他场合调用autoresize。在我的实际类别中,awakeFromNib中有更多代码,我不一定要与自动调整代码一起运行。

答案 1 :(得分:0)

好吧,既然Apple说这种行为是不明确的,那么我认为这是一个坏主意。它今天可能有用,但不能保证明天会有效。

我不确定你想要做什么有一个很好的选择,但更好的选择是调查混合。

这允许您将一个类的选择器替换为另一个类。以下是一个很好的介绍,它可以做些什么以及需要注意的一些方面 - https://stackoverflow.com/a/8636521/3096507