简体   繁体   English

为什么 class object 可以调用“methodSignatureForSelector:”实例方法

[英]why the instance method that is “methodSignatureForSelector:” can be invoke by the class object

What make me doubt is that the class object can invoke instance method.让我怀疑的是 class object 可以调用实例方法。

The method of " methodSignatureForSelector is instance method but when I invoke it by instance object, it go wrong. methodSignatureForSelector的方法是实例方法,但是当我通过实例 object 调用它时,它 go 错误。

NSString *classStr = @"NSInvocationObject";

// 获取class
Class objClass = NSClassFromString(classStr);

// 获取函数
SEL selector = NSSelectorFromString(@"classTest");

// 获取对象
Class stclass = [objClass class];
// - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector OBJC_SWIFT_UNAVAILABLE(""); here is a instance method ,but be invoke by objClass 
NSMethodSignature *singature = [objClass methodSignatureForSelector:selector];

NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:singature];

invocation.target = objClass;
invocation.selector = selector;
[invocation invoke];ere

Selector选择器

  • Selector identifies method by name, not method implementations.选择器通过名称识别方法,而不是方法实现。
  • The hallo method in one class has the same selector as hallo method in another class.一个 class 中的hallo方法与另一个 class 中的hallo方法具有相同的选择器。
  • A class method and an instance method with the same name have assigned the same selector. class 方法和具有相同名称的实例方法分配了相同的选择器。

Selector just identifies method by name and it's irrelevant if it's a class or an instance.选择器只是按名称识别方法,它是 class 还是实例无关紧要。

  • -(void)hallo; -> selector = hallo -> 选择器 = hallo
  • +(void)hallo; -> selector = hallo -> 选择器 = hallo

NSMethodSignature NSMethodSignature

Method signature describes type information of the return value and parameters.方法签名描述了返回值和参数的类型信息。 It doesn't say anything about method name, if it's an instance method, a class method, ... Just types .它没有说明方法名称,如果它是一个实例方法,一个 class 方法,......只是类型

  • -(void)hallo; - signature/encoding = v@: - 签名/编码 = v@:
    • v - void, return type v - 无效,返回类型
    • @ - object @ - object
    • : - selector : - 选择器
  • +(void)hallo; - signature/encoding = v@: - 签名/编码 = v@:

Type Encodings for more info. 键入编码以获取更多信息。

To make it more obvious, imagine you have following methods:为了使其更明显,假设您有以下方法:

- (void)foo {
}

+ (NSUInteger)foo {
    return 2;
}

Both of them have foo as a selector, but they do differ in encoding:它们都将foo作为选择器,但它们在编码方面确实不同:

  • -(void)foo - signature/encoding = v@: -(void)foo - 签名/编码 = v@:
  • +(NSUInteger)foo - signature/encoding = Q@: +(NSUInteger)foo - 签名/编码 = Q@:

Usage用法

Here's an example.这是一个例子。 If your class method & instance method equals (name & return type & parameter types), you can use the same selector and method signature on the class and on the instance.如果您的 class 方法和实例方法等于(名称和返回类型和参数类型),您可以在 class 和实例上使用相同的选择器和方法签名。 invokeWithTarget: says - send a message (identifier by selector = method name & signature = return value & parameter types) - target can be anything that can receive this message. invokeWithTarget:说 - 发送一条消息(选择器的标识符 = 方法名称 & 签名 = 返回值 & 参数类型) - target可以是任何可以接收此消息的东西。

Simplified a bit, but should explain what's going on here.简化了一点,但应该解释这里发生了什么。

Sample class:样品 class:

@interface MyClass: NSObject

+(void)hallo; // Class method
-(void)hallo; // Instance method

@end

@implementation MyClass

+(void)hallo {
    NSLog(@"classHallo");
}

-(void)hallo {
    NSLog(@"instanceHallo");
}

@end

Invocations:调用:

Class c = [MyClass class];   // Class of MyClass
MyClass *i = [MyClass new];  // Instance of MyClass

// Selector identifies method by name
// It's irrelevant if it's a class or an instance method
SEL selector = @selector(hallo);

// Signature just contains types of return value & parameters
// It's irrelevant if it's a class or an instance method
// Get a signature of the +hallo method
NSMethodSignature *signature = [c methodSignatureForSelector:selector];

// Create invocation
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
invocation.selector = selector;  // Set the selector
[invocation invokeWithTarget:c]; // Invokes +hallo (class)
[invocation invokeWithTarget:i]; // Invokes -hallo (instance)

// Get a signature of the -hallo method
signature = [i methodSignatureForSelector:selector];

// Create invocation
invocation = [NSInvocation invocationWithMethodSignature:signature];
invocation.selector = selector;  // Set the selector
[invocation invokeWithTarget:c]; // Invokes +hallo (class)
[invocation invokeWithTarget:i]; // Invokes -hallo (instance)

Documentation文档

Archived, but still good to learn about:已存档,但仍然值得了解:

Comments注释

MyClass only have a instance method: -(void)hallo; MyClass只有一个实例方法-(void)hallo; but when I execute the NSMethodSignature *signature = [c methodSignatureForSelector:@selector(hallo)] , I can't get a signature of the method, signature is nil , if the selector just identifies method by name and it's irrelevant if it's a class or an instance, I should get a signature of method.但是当我执行NSMethodSignature *signature = [c methodSignatureForSelector:@selector(hallo)]时,我无法获得该方法的签名,签名为nil ,如果选择器仅通过名称识别方法并且它是无关紧要的,如果它是 class或者一个实例,我应该得到一个方法的签名。

No. Check the methodSignatureForSelector: method aSelector argument documentation:否。检查methodSignatureForSelector:方法aSelector参数文档:

A selector that identifies the method for which to return the implementation address.一个选择器,标识要为其返回实现地址的方法。 When the receiver is an instance, aSelector should identify an instance method;当接收者是一个实例时,aSelector 应该标识一个实例方法; when the receiver is a class, it should identify a class method.当接收器是 class 时,它应该识别 class 方法。

What selector identifies?什么选择器标识? Method by name and it's hallo in our case - NOT +(void)hallo and NOT -(void)hallo , just hallo - this is what I meant with irrelevant comment.按名称命名的方法,在我们的例子中是hallo - NOT +(void)hallo和 NOT -(void)hallo ,只是hallo - 这就是我所说的无关评论。

When the receiver is an instance, aSelector should identify an instance method;当接收者是一个实例时,aSelector 应该标识一个实例方法;

i is the receiver, i is an instance, so the following code asks for the -(void)hallo method signature, not +(void)hallo . i是接收者, i是一个实例,所以下面的代码要求-(void)hallo方法签名,而不是+(void)hallo

MyClass *i = [MyClass new];   // Instance of MyClass
SEL selector = @selector(hallo);
NSMethodSignature *signature = [i methodSignatureForSelector:selector];

when the receiver is a class, it should identify a class method.当接收器是 class 时,它应该识别 class 方法。

c is the receiver, c is a class, so the following code asks for the +(void)hallo method signature, not -(void)hallo . c是接收者, c是 class,所以下面的代码要求+(void)hallo方法签名,而不是-(void)hallo

Class c = [MyClass class];   // Class of MyClass
SEL selector = @selector(hallo);
NSMethodSignature *signature = [c methodSignatureForSelector:selector];

There's also + (NSMethodSignature *)instanceMethodSignatureForSelector:(SEL)aSelector which you can invoke on a class to get an instance method selector:还有+ (NSMethodSignature *)instanceMethodSignatureForSelector:(SEL)aSelector您可以在 class 上调用它来获取实例方法选择器:

Class c = [MyClass class];   // Class of MyClass
SEL selector = @selector(hallo);
NSMethodSignature *signature = [c instanceMethodSignatureForSelector:selector];

i think i had understanded why the class object can inkove instance method, the class object's isa point to a meta-class that the meat-class is still a NSObject type (same as meta-class: NSObject);我想我已经理解为什么 class object 可以引入实例方法,class 对象的 isa 指向一个元类,该元类仍然是 NSObject 类型: so the class object is same to a isntance object in the sense, this mean that class'object and instance'object can inkove instance method所以 class object 在某种意义上与实例 object 相同,这意味着类'对象和实例'对象可以使用实例方法

I either don't understand what do you mean with this or you're misusing the instance method term.我要么不明白你的意思是什么,要么你在滥用实例方法术语。

Objective-C Classes Are also Objects : Objective-C 类也是对象

In Objective-C, a class is itself an object with an opaque type called Class.在 Objective-C 中, class 本身就是一个 object ,其不透明类型称为 Z9BD81329FEBF6EFE22788E03DDEAF Classes can't have properties defined using the declaration syntax shown earlier for instances, but they can receive messages .类不能使用前面为实例显示的声明语法定义属性,但它们可以接收消息

Objects Send and Receive Messages 对象发送和接收消息

Sending an Objective-C message is conceptually very much like calling a C function.发送 Objective-C 消息在概念上非常类似于调用 C function。

[i hallo] actually means send a hallo message to i & [c hallo] actually means send a hallo message to c where i is an instance and c is a Class . [i hallo]实际上意味着i发送 halo hallo & [c hallo]实际上意味着hallo c发送 halo 消息,其中i是一个实例, cClass

It seems to me that you're just using wrong term.在我看来,您只是使用了错误的术语。 If I understood your comment correctly, yes, you can send a message to either an instance or a class.如果我正确理解您的评论,是的,您可以向实例或 class 发送消息。

Here're other resources related to this topic:以下是与此主题相关的其他资源:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM