【问题标题】:Dynamically invoke a class method in Objective C在 Objective C 中动态调用类方法
【发布时间】:2018-06-04 21:56:51
【问题描述】:

假设我有一个Objective C接口SomeClass,它有一个名为someMethod的类方法:

@interface SomeClass : NSObject {
}

+ (id)someMethod;
@end

在其他一些接口中,我希望有一个辅助方法,可以在这样的类上动态调用someMethod

[someOtherObject invokeSelector:@selector(someMethod) forClass:[SomeClass class];

invokeSelector 的实现应该是什么?有可能吗?

- (void)invokeSelector:(SEL)aSelector forClass:(Class)aClass {
   // ???
}

【问题讨论】:

  • 在您的示例代码中,您将 SomeClass 声明为根类。应该很少需要这样做。你的问题只是一个错误吗?
  • 是的。这是一个错误。感谢您指出这一点。

标签: objective-c cocoa cocoa-touch


【解决方案1】:

代替:

[someOtherObject invokeSelector:@selector(someMethod) forClass:[SomeClass class];

呼叫:

[[SomeClass class] performSelector:@selector(someMethod)];

示例(使用 GNUstep ...)

文件 A.h

#import <Foundation/Foundation.h>
@interface A : NSObject {}

- (NSString *)description;
+ (NSString *)action;
@end

文件 A.m

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

@implementation A

- (NSString *)description
{
    return [NSString stringWithString: @"A"];
}

+ (NSString *)action
{
    return [NSString stringWithString:@"A::action"];
}

@end

其他地方:

A *a = [[A class] performSelector:@selector(action)];
NSLog(@"%@",a);

输出:

2009-11-22 23:32:41.974 abc[3200] A::action

来自http://www.cocoabuilder.com/archive/cocoa/197631-how-do-classes-respond-to-performselector.html的很好的解释:

"在Objective-C中,一个类对象获取了该类的所有实例方法 其层次结构的根类。这意味着每个类对象 继承自 NSObject 得到所有 NSObject 的实例方法—— 包括 performSelector:."

【讨论】:

  • 我知道我可以在 NSObject 上使用 performSelector。但是,我很困惑,因为我认为 Class 类型没有 performSelector 方法。我懒得试了。
  • Code Sense 不建议 performSelector 用于 [SomeClass class] 表达。
  • 我不在我的 Mac 前,所以我尝试在 Linux 上使用 GNUStep 并且它可以工作...... :)
  • 他的类没有实现 NSObject。
  • 你可以做[A performSelector:@selector(action)];
【解决方案2】:

在 Objective-C 中,类也是对象。然而,类对象的处理方式不同,因为它们可以调用其根类的实例方法(NSObject 或 Cocoa 中的NSProxy)。

因此也可以在类对象上使用NSObject 中定义的所有实例方法,并且动态调用类方法的正确方法是:

[aClass performSelector:@selector(aSelector)];

apple docs 更具体一点。

【讨论】:

    【解决方案3】:

    你不应该自己实现这个。

    NSObject 协议有一个performSelector: 方法可以做到这一点。

    【讨论】:

    • 类型类不是 NSObject。它没有 performSelector 方法
    • @Ben S:他正在尝试调用一个类方法。 Class 对象不来自 NSObject
    • Objective-C 中的类是对象,是 NSObject 的直接子类。 NSObject 上定义的每个实例方法都适用于一个类。
    • @Mike: 是的,但是Class object 不会从NSObject 继承。
    • @mipadi:Class 不是类,而是指向类对象的指针的泛型类型。每个类对象都是其元类的一个实例,它遵循一个继承链,最终结束于相关类的根类,在本例中为NSObject。所以,它来自 NSObject。
    【解决方案4】:

    这是您想要的内置方法吗?

    id objc_msgSend(id theReceiver, SEL theSelector, ...)
    

    (有关此功能,请参阅runtime reference docs。)

    【讨论】:

    • 来自您的链接:“此参考主要用于开发 Objective-C 和其他语言之间的桥接层,或用于低级调试。您通常不需要使用 Objective-C 运行时库直接在 Objective-C 中编程时。”
    • 但不是避免内置检查和平衡动态发送消息的整个要点吗?
    • 没关系;没注意到它不是 NSObject 的子类。
    • 我认为这是最好的选择。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-25
    • 2014-04-24
    • 2012-02-09
    • 1970-01-01
    • 2012-02-26
    • 2012-01-23
    相关资源
    最近更新 更多