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

时间:2022-09-06 20:10:47

If i want to extend a class like AVAudioPlayer, whats the best way to also add another method to AVAudioPlayerDelegate ?. Do I make a category for it, do I extend it? If I extend it do I then also have to make sure to overwrite the actual delegate getter/setter ? How would I extend the protocol ? The following gives me errors

如果我想扩展一个类,比如AVAudioPlayer,那么向AVAudioPlayerDelegate添加另一个方法的最佳方式是什么?我是否为它建立一个类别,我是否扩展它?如果我扩展它,那么我还要确保覆盖实际的委托getter/setter吗?如何扩展协议?下面给出了错误。



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

@interface AudioTrack : AVAudioPlayer {
}
@end

2 个解决方案

#1


126  

The syntax for creating a protocol that implements another protocol is as such:

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

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

If you want to call a method in NewProtocol on a pointer typed as OldProtocol you can either call respondsToSelector:

如果您想在NewProtocol中调用一个作为OldProtocol类型的指针上的方法,您可以调用respondsToSelector:

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

Or define stub methods as a category on NSObject:

或将存根方法定义为NSObject上的一个类别:

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

#2


11  

Remember a protocol adds no code to the compiled app -- it only enforces the fact that your class must implement the methods to be considered "conforming" to the protocol. A good use of this would be to generate a group of classes with all the same way of operating: <printable> or <serialized>, etc. So you could create a <plays> protocol for instance:

请记住,协议不向已编译的应用程序添加任何代码——它只强制您的类必须实现被认为符合协议的方法。一个很好的使用方法是生成一组具有相同操作方式的类: 等。

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

And then a class that conforms to <plays> MUST implement the play and type methods. If it doesn't, the compiler issues a warning but compiles the class anyway. In your code you check if an object does conform to a protocol with the following code:

然后一个符合 >的类必须实现这个游戏和类型方法。如果没有,编译器就会发出警告,但无论如何都会编译类。在您的代码中,您检查一个对象是否符合以下代码的协议:

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

A category actually adds new methods dynamically to your class. These methods are globally accessible to the runtime as selectors and can be called by name as in @selector(foo) and [object foo:bar];

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

The purpose of a category is to add special new code to a class even if you don't have the source code for that class. There may be security problems and you could create memory leaks in classes, etc.

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

In your case maybe, in a separate file AVAudioPlayerDelegate_TrackOps.m

在你的案例中,在一个单独的文件中,avaudioplayerdelegate . _trackops.m。

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

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

@end

Putting it as a category of NSObject makes all classes respond to foo. Foo can be a stand alone method Objc_perform_selector(@selector(foo)) as well.

将它作为NSObject的一个类别,将使所有类都响应foo。Foo也可以是一个独立的方法Objc_perform_selector(@selector(Foo))。

Bottom Line: use a category to add a quick method to a class, protocols for enforcing method implementations, and subclasses to specialize existing classes (things like adding member variables or major new functionality). Categories can also be used to override a method or two when a subclass is not needed and wanted, but usually if you want to add functionality to a class you make a subclass. For more examples, ideas, other general information on this topic, there's always the Apple introduction to Objective-C

底线:使用类别向类添加快速方法,强制实现方法的协议,以及将现有类专门化的子类(比如添加成员变量或主要的新功能)。在不需要和需要子类时,也可以使用类别来覆盖一两个方法,但通常如果您想向类添加功能,您就可以创建一个子类。关于这个主题的更多示例、想法和其他一般信息,始终有苹果Objective-C的介绍

#1


126  

The syntax for creating a protocol that implements another protocol is as such:

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

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

If you want to call a method in NewProtocol on a pointer typed as OldProtocol you can either call respondsToSelector:

如果您想在NewProtocol中调用一个作为OldProtocol类型的指针上的方法,您可以调用respondsToSelector:

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

Or define stub methods as a category on NSObject:

或将存根方法定义为NSObject上的一个类别:

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

#2


11  

Remember a protocol adds no code to the compiled app -- it only enforces the fact that your class must implement the methods to be considered "conforming" to the protocol. A good use of this would be to generate a group of classes with all the same way of operating: <printable> or <serialized>, etc. So you could create a <plays> protocol for instance:

请记住,协议不向已编译的应用程序添加任何代码——它只强制您的类必须实现被认为符合协议的方法。一个很好的使用方法是生成一组具有相同操作方式的类: 等。

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

And then a class that conforms to <plays> MUST implement the play and type methods. If it doesn't, the compiler issues a warning but compiles the class anyway. In your code you check if an object does conform to a protocol with the following code:

然后一个符合 >的类必须实现这个游戏和类型方法。如果没有,编译器就会发出警告,但无论如何都会编译类。在您的代码中,您检查一个对象是否符合以下代码的协议:

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

A category actually adds new methods dynamically to your class. These methods are globally accessible to the runtime as selectors and can be called by name as in @selector(foo) and [object foo:bar];

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

The purpose of a category is to add special new code to a class even if you don't have the source code for that class. There may be security problems and you could create memory leaks in classes, etc.

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

In your case maybe, in a separate file AVAudioPlayerDelegate_TrackOps.m

在你的案例中,在一个单独的文件中,avaudioplayerdelegate . _trackops.m。

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

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

@end

Putting it as a category of NSObject makes all classes respond to foo. Foo can be a stand alone method Objc_perform_selector(@selector(foo)) as well.

将它作为NSObject的一个类别,将使所有类都响应foo。Foo也可以是一个独立的方法Objc_perform_selector(@selector(Foo))。

Bottom Line: use a category to add a quick method to a class, protocols for enforcing method implementations, and subclasses to specialize existing classes (things like adding member variables or major new functionality). Categories can also be used to override a method or two when a subclass is not needed and wanted, but usually if you want to add functionality to a class you make a subclass. For more examples, ideas, other general information on this topic, there's always the Apple introduction to Objective-C

底线:使用类别向类添加快速方法,强制实现方法的协议,以及将现有类专门化的子类(比如添加成员变量或主要的新功能)。在不需要和需要子类时,也可以使用类别来覆盖一两个方法,但通常如果您想向类添加功能,您就可以创建一个子类。关于这个主题的更多示例、想法和其他一般信息,始终有苹果Objective-C的介绍