I defined two functions.They are all the same, except in different class. And I imported one class into another class, and then used #selector(functionName).How does compiler know which function I want to use?
A "selector" is the name of a function. The type is SEL, which is no more than a typedef to NSString*. The selector not the function implementation itself (which also exists, type IMP).
Therefore, you cannot execute a selector, because there is no code behind.
If you want to "call" a function thru a selector, you need to specify an instance on which you want the selector to be performed onto. The root class NSObject has several functions like performSelector, which will take the selector, look for the implementation in that object, and then execute that function implementation.
The magic behind is the Objective C runtime. In reality, it's a little more sophisticated than explained above; look for objc_msgSend if you are interested in more details.
Related
my question as the title says.obviously, the first parameter was used for this pointer , in some taste of c++.what about the second one? thak you.
The signature of objc_msgSend() is:
id objc_msgSend(id self, SEL op, ...);
Every method call is compiled down to a call to this function. I.e., if you call:
[anArray objectAtIndex:42];
That will be compiled as if it were:
objc_msgSend(anArray, #selector(objectAtIndex:), 42);
Now, to your question, why do methods get compiled down to a function that has the SEL as the second argument. Or, more specifically, why is this method:
- (id)objectAtIndex:(NSUInteger)index;
Exactly equivalent to this C function:
id object_at_index(id object, SEL _cmd, NSUInteger index);
The answer is speed speed speed.
Speed
Specifically, by doing this, then objc_msgSend() never has to rewrite the stack frame* and it can also use a tail call optimization to jump directly to the method invocation. This is the same reason why you never see objc_msgSend() in backtraces in the debugger (save for when you actually crash/break in the messenger).
objc_msgSend() uses the object and the _cmd to look up the implementation of the method and then, quite literally, jumps to that implementation.
Very fast. Stack frame untouched.
And, as others have stated, having _cmd around in the method implementation can be handy for a variety of reasons. As well, it also means that the messenger can do neat tricks like proxy support via NSInvocation and the like.
*rewriting the stack frame can be insanely complex and expensive. Some of the arguments might be in registers some of the time, etc... All architecture dependent ABI nastiness. One of the biggest challenges to writing things like imp_implementationWithBlock() was figuring out how to do so without touching the stack because doing so would have been too slow and too bloated to be viable.
The purpose of having the second parameter contain the selector is to enable a common dispatch mechanism. As such, the method dispatch code always expects the second parameter to be the selector, and dispatches based on that, or follows the inheritance chain up, or even creates an NSInvocation and calls forwardInvocation:.
Generally, only system-level routines use the selector argument, although it's rather nice to have it when you hit an exception or are in the debugger trying to figure out what routine is giving you difficulties if you are using forwardInvocation
From the documentation:
Discussion
This data type is a pointer to the start of the function that implements the method. This function uses standard C calling conventions as implemented for the current CPU architecture. The first argument is a pointer to self (that is, the memory for the particular instance of this class, or, for a class method, a pointer to the metaclass). The second argument is the method selector. The method arguments follow.
In Objective-C when you call a method you need to know the target, the selector and the eventual arguments. Let's suppose that you are trying to do this manually: how can you know which method to call if you don't know the selector? Do you call some random method? No, you call the right method because you know the method name.
I have a function - myFunc() in class A. There are multiple other classes calling this function.
How will I be able to find out which class is calling myFunc() at a particular instance?
Would someone be able to help me with this?
Conceptually, this information is available in the stack, though it isn't easy to get to. Most solutions would involve creating an exception in order to capture the stack trace, and then reading the trace. I haven't tried this, but it might work:
void myFunc()
{
NSArray *stack = [NSThread callStackSymbols];
// I have no idea if the current function call is at the 0 or last position
// of the array. Experiment here!
}
Pertinent documentation: NSThread Class Reference
Note that if you want your function to behave differently depending on who is calling, DO NOT DO THIS. It's fragile (there are no guarantees about whether the format of what callStackSymbols returns will change).
It's better to simply pass a parameter into your function. If you're dealing with a C-function callback API, there is typically a void * "context" or "info" parameter that you can use to pass in an arbitrary pointer. This could be a pointer to your object.
Use the Visitor pattern
Have each of the calling classes implement a common protocol that defines the interface of the behavior you are looking to achieve.
Add the protocol as a parameter to myFunc.
When calling myFunc(), specify self as the parameter.
myFunc can now invoke any of the protocol methods without knowing about the other specific classes.
This way you adhere to the concepts of encapsulation.
I have a strange task. I need to get an array that contains all the functions in an objective c object. I then need to be able to tell if each function is a class method or not. Then I need to get the names (preferably an NSString) of each parameter and the type each parameter takes. Is there a way to do this? If not, does anyone know how to access the keys and values coded in the NSCoding Protocol function -(void)encodeWithCoder:(NSCoder*)aCoder; without using NSKeyedArchiver? What I am trying to do here is display a list of properties required to initialize an object. All my objects use class methods to initialize themselves. I am making a level editor that allows me to edit properties that differ between objects and I don't feel like writing getPropertyList and initWithProperties functions for every single object since I have already done this by implementing the NSCoding protocol.
I need to get an array that contains all the functions in an objective c object. I then need to be able to tell if each function is a class method or not.
Easy enough: you want class_copyMethodList(), which gets you just the instance methods for that class. To get the class methods, pass the class object, e.g. class_copyMethodList(object_getClass([NSString class]), &count);
Then I need to get the names (preferably an NSString) of each parameter and the type each parameter takes.
The parameter name part is probably not possible. They're not included in the method's metadata, and I'm pretty sure that they don't survive compilation at all; digging them out of the executable if they're there would certainly not be easy.
The types, however, are easily accessible via one of two runtime functions: either method_getTypeEncoding(), which gets you the signature string for the method's return and arguments, or method_getArgumentType(), which will let you loop over the argument types (the returned strings use the same code as the full type string).
If not, does anyone know how to access the keys and values coded in the NSCoding Protocol function -(void)encodeWithCoder:(NSCoder*)aCoder without using NSKeyedArchiver?
Are you talking about the particular implementation that you've made for encodeWithCoder:? You want the list of ivars implied by [coder encodeObject:firstIvar forKey:#"firstIvar"]; [coder encodeObject:secondIvar forKey:#"secondIvar"];? I'm not sure what that has to do with method signatures, but if so, you could make an NSCoder subclass that creates a dictionary from when you pass it as the coder and send encodeWithCoder: to your objects (see this answer I posted the other day).
What I am trying to do here is display a list of properties required to initialize an object.
What about a class method that returns an array with the names of the properties?
+ (NSArray *)essentialPropertyNames {
return [NSArray arrayWithObjects:#"firstIvar", #"secondIvar", nil];
}
That would probably be less effort than picking through the runtime/class metadata and wouldn't be any less odd.
All my objects use class methods to initialize themselves.
That sounds unusual at best. In Cocoa, instances should use some form of -init to do their initialization.
This question already has answers here:
Using #pragma to suppress “Instance method not found” warnings in Xcode
(5 answers)
Closed 9 years ago.
I have a class whose methods are determined at runtime, as indicated in my question here. This works great, but now I have a bunch of warnings that look like the following littering my code:
Class method '+objectIsNotNil:' not found (return type defaults to 'id')
While these warnings don't actually affect the build process, they're very annoying and make it harder to spot relevant warnings. Is there some way to disable them, but only for the Assert class (maybe some kind of macro)? If this isn't possible, then is there some way to turn them off for the entire build?
One alternative would be to use performSelector:withObject: instead of the direct method call.
So instead of:
[Assert objectIsNotNil:object];
You could have:
[Assert performSelector:#selector(objectIsNotNil:) withObject:object];
It does not look quite as nice but it will remove the warnings. Furthermore, this pattern will work for any selector you want. To make things look a little better you could use macros in the following way:
#define ASSERT_PRECONDITION(sel, obj) [Assert performSelector:#selector(sel) withObject:obj]
This way your assert would look like this:
ASSERT_PRECONDITION(objectIsNotNil:, object);
these cases should be extremely rare...
I've declared a hidden protocol which declared the methods with proper signatures. 'Hidden' in the sense that it was only included by the translations which needed them.
#protocol MONRuntimeClassInterface
+ (BOOL)objectIsNotNil:(id)object;
#end
Easy answer:
You don't want to do this. And if I understand your problem right, you don't need to. You're defining all the relevant methods in your Predicate class described in the link and Assertion is just forwarding to them. Including Predicate.h and making sure everything's declared in the interface should work fine. Like methods called on objects typed id, the compiler will consider methods called on a Class object to be found so long as it knows of at least one class in that compilation unit that implements a class method with the same name.
Alternative answer:
If you really want to suppress compiler warnings, for example if you're calling a method that don't exist anywhere at compile-time then you need to use either NSObject's performSelector: method or the runtime function objc_msgSend(). This won't be checked for a matching method at compile time. However, for some C types which you could plausibly want to pass as arguments (floats and certain larger structs), the compiler needs to know their type. In the absence of a method definition, it needs information from you. performSelector: works by only accepting objects of type id. objc_msgSend needs casting casted to a function with the appropriate signature before it's called (and in some cases, replacing with a variant function). Mike Ash has a good explanation of how this works here.
I have a class which uses resolveInstanceMethod to dynamically implement methods.
When I call the dynamically implemented methods from other parts of the code, the compiler emits a warning that the object may not respond to the selector. I would like the compiler to not emit such warnings for this class, but I don't want to suppress warnings when I invoke an invalid selector on other classes. Is this possible?
Assuming you know the method signatures that will be dynamically resolved at compile time, you can declare 'em in an informal category:
#interface MyDynamicallyResolvingClass(MethodsThatWillResolveAtRuntime)
... declare the methods here ...
#end
No need to provide an implementation.
If you don't know the signatures -- if the method names are dynamic, too -- then you'll need to use either -performSelector: (or the single or double object argument variants) or you will likely want to use NSInvocation, unless performance is a major concern (if it is, there are alternative solutions that are significantly more fiddly).
Use performSelector:
It's equivalent to sending a message directly to the receiver, however, it allows you to send messages that aren’t determined until runtime.
If your methods take one or two arguments, you can use the sisters of this method: – performSelector:withObject: and – performSelector:withObject:withObject:
If your methods have more than two arguments, or arguments that are not of object type, this answer is not adapted.