【问题标题】:How to extend protocols / delegates in Objective-C?如何在 Objective-C 中扩展协议/委托?
【发布时间】:2021-04-08 03:40:56
【问题描述】:

如果我想扩展一个像 AVAudioPlayer 这样的类,最好的方法是向 AVAudioPlayerDelegate 添加另一个方法?

我应该为它创建一个类别,我应该扩展它吗?

如果我扩展它,我是否还必须确保覆盖实际的委托 getter/setter?我将如何扩展协议?

以下给我错误

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

@interface AudioTrack : AVAudioPlayer {
}
@end

【问题讨论】:

    标签: iphone objective-c


    【解决方案1】:

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

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

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

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

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

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

    【讨论】:

    • 如果我创建了一个实现另一个协议的协议......我还需要做些什么来确保“OldProtocol”方法被触发吗?因为对我来说,我正在启动新协议,但所有现有协议都不再存在
    • 一个协议没有方法,它有方法定义;也就是说,它描述了一个类必须被视为“符合”所述协议的名称、参数和返回类型。根据您的评论/问题,我打赌您忘记在您的 -setDelegate 中调用 [super setDelegate:value]:
    • 使用这种方法不会暴露新协议的方法,请查看我的回复以获得最干净的方法
    • @simonthumper:到底有多可怕?
    • 您正在通过与 NSObject 无关的类别将方法添加到在任何地方都使用的系统类中。它当然不会破坏你的代码,但它很hacky,而且你访问的每个对象都可以调用这些方法,这将使代码完成变得有趣!
    【解决方案2】:

    请记住,协议不会向已编译的应用程序添加代码——它只会强制您的类必须实现被视为“符合”协议的方法这一事实。一个很好的用途是生成一组具有相同操作方式的类:&lt;printable&gt;&lt;serialized&gt; 等。因此您可以创建一个 &lt;plays&gt; 协议,例如:

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

    然后一个符合&lt;plays&gt; 的类必须实现playtype 方法。如果没有,编译器会发出警告,但无论如何都会编译该类。在您的代码中,您可以使用以下代码检查对象是否符合协议:

    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 introduction to Objective-C

    【讨论】:

    • 您能否详细说明如何将类别添加到协议中?我认为你写的语法有问题。谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-07
    相关资源
    最近更新 更多