What is findTheAppropriateSelectorForTheCurrentSituation() and its content? - iphone

Referring to the discussion performSelector where is explained that with the following line it is possible to call a method
SEL aSelector = findTheAppropriateSelectorForTheCurrentSituation();
[anObject performSelector: aSelector];
My question is what is the content of the method called: findTheAppropriateSelectorForTheCurrentSituation()?
//For me the most important question
And another question is, why I get the warnings when using this piece of code.
1.warning: implicit declaration of function 'findTheAppropriateSelectorForTheCurrentSituation'
2.warning: initialization makes pointer from integer without a cast
3."_findTheAppropriateSelectorForTheCurrentSituation", referenced from:
Thank you for your answeres in advance

You'd have to look up the documentation or disassemble the binary that contains that method in order to determine exactly what it does. As for your warning, your syntax is incorrect. You should use the #selector(name) syntax in order to create a selector you can use to call [obj performSelector:].

Related

Difference Between NormalMethods and Selectors in objective c [duplicate]

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.

Can someone tell me the difference between the call in IOS

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.

How to find out if a method exists in Obj-C when given an NSString

I have a method as an NSString *. If it exists, I want to call it, and if not, do nothing.
SEL eventSelector = NSSelectorFromString(eventSelectorStr);
if ([delegate respondsToSelector:eventSelector]) {
[delegate performSelector:eventSelector];
[delegate adapterDidFinishAdRequest:self];
}
else {
// Does not implement selector
}
This code does not work, since NSSelectorFromString will register the string as a selector, so respondsToSelector:eventSelector will cause a crash because the selector is actually invalid.
Why do you say that that doesn't work? This is the most common way to implement invoking optional delegate methods. I've never had an issue with that construct not working.
Let's clear up some confusion.
NSSelectorFromString() will generate a valid selector from the string, and will not crash in doing so. respondsToSelector: will validly determine if the delegate implements that method or not, without crashing. It is true that if you call performSelector: with a selector that the delegate doesn't implement it will cause a crash.
However, that isn't the situation here. The code is valid. If you have a crash in this code, I would check the error message and look instead to adapterDidFinishAdRequest:.
Try checking for eventSelector != nil before using it.
It took me a while to understand this as well. The key insights are that a selector reference is basically just a dressed-up C string, and that it doesn't 'belong' to any particular class or object. When the NSSelectorFromString() documentation says that the selector is 'registered', it just means that a dressed-up C string is 'blessed' (my term) for use as a selector within the Objective-C runtime.
Here's the section on the return value for NSSelectorFromString() from Apple's documentation:
Return Value
The selector named by aSelectorName.
If aSelectorName is nil, or cannot
be converted to UTF-8 (this should be
only due to insufficient memory),
returns (SEL)0.
Reading it carefully shows that the only situations which can cause (SEL)0 to be returned are if your string was nil or if you ran out of memory.

Add method selector into a dictionary

I want to add a selector into a dictionary (the main purpose is for identifying the callback method and delegate after finish doing something)
But I find that I can not do that, the program will get an error "EXC_BAD_ACCESS".
Are there any other way for me to add that method selector to a dictionary?
Thanks for your help.
I know this question was answered a long time ago, but just in case anyone stumbles upon it like I did...
The combination of NSStringFromSelector and NSSelectorFromString as answered above is probably the best way to go. But if you really want to, you can use a selector as a value or key in an NSDictionary.
A selector (type SEL) is implemented as a pointer to a struct in Apple's Objective-C runtimes. A pointer cannot be used directly in a dictionary, but a pointer can be wrapped in an NSValue object that can be used.
Using this method you can store a selector as a value in a dictionary using code like this:
dictionary =
[NSDictionary dictionaryWithObject:[NSValue valueWithPointer:selector]
forKey:key];
A selector can be retrieved using code like this:
SEL selector = [[dictionary objectForKey:key] pointerValue];
Similarly for using a selector as a key:
dictionary =
[NSDictionary dictionaryWithObject:value
forKey:[NSValue valueWithPointer:selector]];
value = [dictionary objectForKey:[NSValue valueWithPointer:selector]];
Adding a new entry to a dictionary does two things (in addition to adding it to the dictionary, obviously):
It takes a copy of the key value. This means that the the key object must implement the NSCopying protocol
retains the value. This means that it needs to implement the NSObject protocol
It's probably the second that's causing your EXC_BAD_ACCESS.
There are at least two ways around this.
Firstly, rather than adding the selector you could add the instance of the class that implements the selector to your dictionary. Usually your class will inherit from NSObject and it will work fine. Note that it will retain the class though, maybe not what you want.
Secondly, you can convert a selector to a string (and back again) using NSSelectorFromString and NSStringFromSelector (docs are here).
I get my answer based on the comment of Zydeco:
You can convert between SEL and
NSString using NSSelectorFromString
and NSStringFromSelector
The common idiom in Obj-C is to have specific names for callbacks for specific events. (Such parserDidBeginDocument: from NSXMLParserDelegate). If you really need to be able to specify the names, it is likely that your only recourse is to add the names of the selectors as #"mySelector:withArgument:context:" or somesuch.

Printing arguments sent to forwardInvocation: subclass of NSProxy

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.