如何在Objective-C中扩展协议/委托


73

如果我想扩展像AVAudioPlayer这样的类,什么是向AVAudioPlayerDelegate添加另一个方法的最佳方法是什么?我是否为此做一个类别,是否对其进行扩展?如果我扩展它,那我还必须确保覆盖实际的委托getter / setter吗?我将如何扩展协议?以下给我错误



@protocol AudioTrackDelegate : AVAudioPlayerDelegate {
    - (void)foo;
}
@end

@interface AudioTrack : AVAudioPlayer {
}
@end

Answers:


131

创建实现另一个协议的协议的语法如下:

@protocol NewProtocol <OldProtocol>
- (void)foo;
@end

如果要在NewProtocol输入为的指针上调用方法,OldProtocol可以调用respondsToSelector

if ([object respondsToSelector:@selector(foo)])
    [(id)object foo];

或将存根方法定义为以下类别NSObject

@interface NSObject (NewProtocol)
- (void)foo;
@end
@implementation NSObject (NewProtocol)
- (void)foo
{
}
@end

如果我创建了一个实现另一个协议的协议,我还需要做其他事情以确保触发“ OldProtocol”方法吗?因为对我来说,我正在触发新协议,但是所有现有协议都不再
可用了

10
协议没有方法,它有方法定义。也就是说,它描述了必须被视为“符合”所述协议的类的名称,参数和返回类型。根据您的评论/问题,我敢打赌,您忘记了在-setDelegate中调用[super setDelegate:value]:
rpetrich

使用这种方法,您不会暴露新协议的方法,请以一种最简洁的方式看一下我的回复
Kappe 2014年

@simonthumper:它以什么方式可怕?
rpetrich

您正在通过类别添加与NSObject无关的方法,将其添加到随处可见的系统类。当然,这不会破坏您的代码,但是它很hacky,您访问的每个对象都可以调用这些方法,这将使代码完成变得有趣!
simonthumper 2015年

10

请记住,协议没有向已编译的应用程序添加任何代码-它仅强制您的类必须实现被视为“符合”协议的方法。这样做的一个好用法是生成一组具有相同操作方式的类:<printable><serialized>等,因此您可以创建一个<plays>协议,例如:

@protocol plays
    - (void) play;
    - (NSString *) type;
@end

然后,符合条件的类<plays>必须实现playandtype方法。如果不是,则编译器会发出警告,但仍会编译该类。在您的代码中,使用以下代码检查对象是否符合协议:

if ([obj conformsTo: @protocol(plays)]) {
    [obj play];
}

类别实际上是在您的类中动态添加新方法。这些方法可以作为选择器在运行时全局访问,并且可以按名称在@selector(foo)和中调用[object foo:bar];

类别的目的是向类添加特殊的新代码,即使您没有该类的源代码也是如此。可能存在安全问题,并且您可能在类等中创建内存泄漏。

就您而言,可能在单独的文件中 AVAudioPlayerDelegate_TrackOps.m

#import "AVAudioPlayerDelegate.h"
@implementation AVAudioPlayerDelegate (TrackOps)

- (NSObject *) foo {
    // do foo stuff;
    return bar;
}

@end

将其作为分类的类别NSObject会使所有类都响应fooFoo也可以是独立方法 Objc_perform_selector(@selector(foo))

底线:使用类别将快速方法添加到类,用于实施方法实现的协议以及使用子类来使现有类专用化(诸如添加成员变量或主要的新功能之类的东西)。当不需要子类并且不需要子类时,类别也可以用于覆盖一个或两个方法,但是通常,如果要向类中添加功能,则可以创建子类。有关该主题的更多示例,想法和其他一般信息,始终有Apple对Objective-C的介绍。


您能否详细说明如何在协议中添加类别?我认为您编写的语法有问题。谢谢
dizy 09-4-10的
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.