I have a method called Display. Can somebody explain me the difference of calling the same method in the following two ways.
[self Display];
[self performselector:#selector(Display)]
- (void)Display {
NSlog(#"Data");
}
both are basically the same with one minute difference.. #selector gives a name to your method which you can pass around as an attribute to other objects or in other function calls.
Like if you want to send a message to other object and you want to send display as an attribute then you will have to give it a name using #selector and thus you can send it.. its a pretty vague concept.. hope this helps.
and to quote apple documents...
"However, the performSelector: method allows you to send messages that
aren’t determined until runtime. A variable selector can be passed as
the argument:
SEL myMethod = findTheAppropriateSelectorForTheCurrentSituation();
[anObject performSelector:myMethod];
The aSelector argument should identify a method that takes no
arguments. For methods that return anything other than an object, use
NSInvocation."
[self Display] is shorter and easier to read, write and comprehend.
[self performSelector:#selector(Display)] makes it possible to execute arbitrary selectors. If you save the selector in a variable, then you can execute it later on without knowing the method you invoke. It is therefore more flexible. Even better: you can pass selectors and objects to other objects and let them invoke it for you when necessary. An example why you want to use this is the NSUndoManager which simple invokes a selector to undo an action if the user executes the Undo command.
I do not think that there is a big difference between examples you provided, but perform selector is very useful when you for instance wanna move execution of your method to the background thread.
[self Display]; is a call to a known method on a known object.
It's easy to give it some params if your want : [self DisplayWithParam1:(NSString*)aString param2:(int)aNumber param3:(NSDictionary*)aDict
[self performselector:#selector(Display)] is a call that allows you to call a possibly not known method on a possibly not known object type.
Let's imagine you have many kind of classes that all respond to a given protocol that require to have the Display method implemented. You put some objects of thoses different classes in an NSMutableArray. When parsing the array later, you will get id typed objects.
So calling[myArrayObject Display]; will work at runtime but will generate a warning at compile time as id does not support any method of course, even if you know that this object supports the method.
To prevent thoses warning, call [myArrayObject performselector:#selector(Display)];.
The problem with that call is that is harder to pass some parameters.
performSelector:withObject:withObject:
Sends a message to the receiver with two objects as arguments.
- (id)performSelector:(SEL)aSelector withObject:(id)anObject withObject:(id)anotherObject
Parameters
aSelector
A selector identifying the message to send. If aSelector is NULL, an NSInvalidArgumentException is raised.
anObject
An object that is the first argument of the message.
anotherObject
An object that is the second argument of the message
Return Value
An object that is the result of the message.
Discussion
This method is the same as performSelector: except that you can supply two arguments for aSelector. aSelector should identify a method that can take two arguments of type id. For methods with other argument types and return values, use NSInvocation.
Availability
Available in Mac OS X v10.0 and later.
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocSelectors.html
The #select call is faster. Generally the uglier (and less dynamic) the code you have in Objective-C, the faster it runs. Here, the selector call bypasses the usual call to objc_msgSend().
I wouldn't recommend writing code like this if you can avoid it. Selectors are somewhat common in Cocoa, but if you're using it for a speedup it's really not worth it. objc_msgSend() is highly optimized and very fast.
Related
This question already has answers here:
What's the difference between a method and a selector?
(3 answers)
Closed 8 years ago.
Here I can't understand what is selector?, still now I knew it is used for calling methods,and someother says its is a callback mechanism.
What is the difference between these two methods.
Instance is created
Car *porsche = [[Car alloc] init];
The methods in these two ways whicih one is better.
SEL stepTwo = #selector(driveForDistance:);
[porsche performSelector:stepOne];
or
[porsche startEngine];
"whicih one is better" - neithier (sic) one is better. They have different purposes.
Furthermore, there aren't "normal" (or "abnormal", for that matter) methods. There are methods. And selectors are unique names identifying methods.
If you don't need dynamic method dispatch, then there's no reason for using performSelector: (even less reason to use it the wrong way you used it - calling a method that takes one argument without any arguments). If you know which method you want to call on an object, just call it.
If you need reflection and dynamism, then it's useful and reasonable to use selectors to dynamically resolve methods.
The performSelector allows you to dynamically determine which selector to call a selector on the given object. In other words the selector need not be determined before runtime.
Thus even though these are equivalent:
[theObject aMethod];
[theObject performSelector:#selector(theMethod)];
The second form allows you to do this:
SEL aSelector = findTheAppropriateSelectorForTheCurrentSituation();
[theObject performSelector: theSelector];
Short Answer :
Main thing performSelector allows you to dynamically determine which selector to call a selector on the given object and there is not need to determine it Runtime. But as Both are some In Perfromselector a Selector is the name of a method. message is a selector and the arguments you are sending with it. and where method is a combination of a selector and an implementation. Try this there are number of Question on SO.
This is a slight follow on from a previous question:
for(id <stuffieProtocol> eachObject in stuffieArray) {
if([eachObject respondsToSelector:#selector(secretID)]) [eachObject secretID];
}
The above is a line from a fast enumeration loop that takes a number of objects out of an NSArray and checks to see if they respond to the method secretID. The method secretID is not part of the #protocol but rather a method defined on one of the objects in the collection.
The if statement above fails because the compiler says "No known instance method for selector secretID" Which is fine, id does not care and the method is not defined in <stuffieProtocol> I can fix this by casting each object to the type that does define secretID:
if([eachObject respondsToSelector:#selector(secretID)]) [(Ted *)eachObject secretID];
My question is in the original code, how does the compiler know that eachObject responds to the method secretID but yet when you ask it to call that method its says "No known method" I am just a little curious about the mechanics?
The compiler doesn't know anything about whether the object responds to that selector but the runtime does. (i.e. The compiler doesn't execute the code.) The compiler only cares that any NSObject can respond to respondsToSelector:.
I'm able to make the method for the call [self weaponAttachments:mpk5] but I don't like having to call self. I think [mpk5 weaponAttachments] is more natural and is easier to read.
The problem I'm having is I need to pass in the weapon (mpk5) in order to use it, which I can do with the first method but not with the second one. Does this mean that I need to subclass NSDictionary in order to be able to use a statement like [mpk5 weaponAttachments]? If so, how do I get ahold of the caller "mpk5" so that I can use it inside the method?
EDIT
I apologize for not putting this in the first time but my objective is to have [mpk5 weaponAttachments] return an NSDictionary or NSArray. Right now I have NSDictionary *attachments = [self weaponAttachments:mpk5]; which works but it just doesn't seem like the best approach.
So firstly, your two calls are a little mixed up:
[self weaponAttachments:mpk5] calls the weaponAttachments method, passing in the variable mpk5.
But [mpk5 weaponAttachments] is either asking the mpk5 object to return the weaponAttachments property or is asking the mpk5 object to run a method called weaponAttachments (I'm simplifying here - it's always a method, but if you're using properties you probably won't realise this as Objective-C will create them for you).
These are fundamentally different things.
On to the brunt of your question:
I don't like having to call self
...unfortunately, if you're working in an object-oriented language you're going to have to get used to this. Say I have a class called mySimpleClass, and a method inside that class called doSomething. Writing this:
[mySimpleClass doSomething] would be what we call a static method. Whereas calling [self doSomething] from within an instance of mySimpleClass would be an instance method.
If you're unsure of the difference between static and instance methods you should probably step back and take a look at some of the basic guides out there.
I'm trying to transform one method call into another dynamically (at runtime).
For instance, I'd like the following:
[obj foo]
to delegate to:
[obj getAttribute: #"foo"]
(I'd like to do this dynamically as I don't know ahead of time what those method names or attributes are going to be).
I see that there's a hook into:
- (id) forwardingTargetForSelector: (SEL) aSelector
That only seems to work for delegation, though, I want to keep the object as "self" and transform the method arguments.
Where should I look for this sort of behavior? Is it even possible in obj-c?
You can use the method -forwardInvocation: for that. It takes a full NSInvocation object which represents the method call, and you can handle it however you wish. If you do this, you should also override -methodSignatureForSelector: to return the correct NSMethodSignature (required for -forwardInvocation: to work on unknown selectors). It's also recommended that you override -respondsToSelector: to declare that you can handle the selector in question.
I want to intercept messages sent to a proxy object by just printing the selector and arguments. Even if the proxy does not implement them and does not have a target object. Please help. I have looked at several options and Apple docs but they assume that you already know the target object. I want to do this cleanly without memory issues.
#implementation MyProxy
-(void)forwardInvocation:(NSInvocation*)anInvocation
{
// at this point I would
//like to fetch the arguments and put on an array
NSMutableArray *myArgs = .....;
NSLog(#"Invoking selector %#", theSelector);
NSLog (myArgs); // this should print me the list of arguments to the method
}
#end
// e.g
MyProxy *proxy = [[MyProxy alloc] init];
[proxy SendMeAnyThing: #"hello"]; // this should print me arguments
or [proxy add: 12 to: 89 sub: 89]; // should print the arguments
Thanks thanks
The arguments are of just about any C type, including Objective-C types, that may be passed to the method. Thus, they can't be represented in an array.
Note that invoking a method that is not declared anywhere doesn't make any sense. Quite specifically, the compiler has no idea how to encode the arguments at the call site to make a valid C function call (a method call is really just a C function call to objc_msgSend() or a variant). So, to answer your "any method, even if it doesn't exist" question; no, you can't do that.
You can, however, effectively eliminate all compiler warnings. If you eliminate all compiler warnings -- all "method foo:bar: has can't be found" type warnings -- then that means the compiler does have enough information and you can do whatever the heck you want with a proxy.
Furthermore (as I read more into your question), there is no need to implement any method on the proxy. A proxy can quite happily forward-into-NSInvocation any method call. Written correctly, you can have a proxy stand in for any object without issue.
What you need to do is enumerate the arguments using the API of NSInvocation, sussing out the types and then decoding each argument accordingly and printing appropriately.
You can grab the number of arguments by invoking numberOfArguments on the method signature of the NSInvocation instance (the signature can be had via the methodSignature method).
Then, loop through the arguments and call getArgumentTypeAtIndex: on the method signature to get the type. You would then most likely write a switch() statement on the type encoding to then call getArgument:atIndex: and decode appropriately based on type.
Note that argument 0 is self and argument 1 is _cmd; the SEL of the method that was invoked.