What make me doubt is that the class object can invoke instance method.
The method of "methodSignatureForSelector
is instance method
but when I invoke it by instance object, it go wrong.
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
hallo
method in one class has the same selector as hallo
method in another class.Selector just identifies method by name and it's irrelevant if it's a class or an instance.
-(void)hallo;
-> selector = hallo
+(void)hallo;
-> selector = hallo
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.
-(void)hallo;
- signature/encoding = v@:
v
- void, return type@
- object:
- selector+(void)hallo;
- signature/encoding = 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:
-(void)foo
- signature/encoding = v@:
+(NSUInteger)foo
- signature/encoding = Q@:
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. invokeWithTarget:
says - send a message (identifier by selector = method name & signature = return value & parameter types) - target
can be anything that can receive this message.
Simplified a bit, but should explain what's going on here.
Sample 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)
Archived, but still good to learn about:
MyClass
only have a instance method:-(void)hallo;
but when I execute theNSMethodSignature *signature = [c methodSignatureForSelector:@selector(hallo)]
, I can't get a signature of the method, signature isnil
, 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.
No. Check the methodSignatureForSelector:
method aSelector
argument documentation:
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; when the receiver is a class, it should identify a class method.
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.
When the receiver is an instance, aSelector should identify an instance method;
i
is the receiver, i
is an instance, so the following code asks for the -(void)hallo
method signature, not +(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.
c
is the receiver, c
is a class, so the following code asks for the +(void)hallo
method signature, not -(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:
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) ; 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
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:
In Objective-C, a class is itself an object with an opaque type called Class. 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.
[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
.
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.
Here're other resources related to this topic: