I've seen objects which require the parameter, selector. What is the general concept in understanding a selector?
An example of choosing a selector is the NSTimer where my selector I have chosen is a function that increments the counter.
timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: ("incrementCounter"), userInfo: nil, repeats: true)
A selector is a concept from Objective-C that represents a message to be sent (i.e. a method to be called) dynamically at run time. When you set up something to be done via a selector, you know which message will be sent, but not necessarily what its parameters are. (And sometimes not even which object it'll be sent to.)
You can consider selectors a relative of closures/blocks, since they let you package up some code to be called later and hand it off to some other function. However, a closure must be specified/resolved at compile time, so it's less dynamic than a selector.
Selectors are great for "loose binding" concepts like control actions. You can use a selector to choose in Interface Builder which method a button should call when clicked, even though your app isn't actually running in IB; or you can say "this button should call paste: on whatever text view has keyboard focus", not knowing when you set up the button which view that'll be (because keyboard focus changes all the time).
Selectors in ObjC predate blocks/closures, so historically, selectors were the primary way to tell an API things like "call this method later", which is why you find them throughout Cocoa for patterns like timers, array sorting, and undo even when such patterns might benefit more from the tight binding of closures/blocks.
For more on using selectors in Swift, see Interacting with Objective-C APIs in Using Swift with Cocoa and Objective-C and/or this SO answer. For more on selectors and Cocoa in general, see Cocoa Core Competencies: Selector.
A selector is a custom method which is called in the class specified by target when the timer fires. If the method is supposed to take parameters each parameter is represented by a colon.
In Swift the struct Selector responds to the protocol StringLiteralConvertible,
Therefore – since the compiler knows the type in your example – a literal string is implicitly converted to a Selector instance and the Selector initializer is not needed.
PS: The parentheses around your selector string are not needed either.
Related
Specifically, when a task can be complemented with or without selectors, is there any (objective) reason to prefer one way over the other?
For instance, an NSTimer can run a method on an interval in two ways:
A) Using Selectors:
let timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(timerAction()), userInfo: nil, repeats: true)
dynamic func timerAction() {
print("foo")
}
B) Without Selectors:
let timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in
self.timerAction()
}
func timerAction() {
print("foo")
}
Both versions are entirely functional, so is there any (objective) reason to prefer one over the other?
The target/selector design is baggage left over from the earlier Objective-C, pre-block days of the APIs.
If Apple were to redo all of those APIs today, the whole target/selector design would disappear and all be replaced with blocks/closures. This idea is supported by newer Apple APIs. Example - the old UIAlertView used a delegate. The newer UIAlertController only uses closures/blocks for the alert actions.
Using closures (Swift) or blocks (Objective-C) is much preferred over using the target/selector approach.
Here are problems with using target/selector:
The dreaded "unrecognized selector" error.
The need to create an extra, top-level method just for the selector.
The possibility of specifying the wrong parameters and data types on the selector method.
Losing all of the current context you have at the point you setup the object that needs the target/selector.
The opposite of all of those are the benefits of using the closure/block form.
It's possible, that over time, many of the delegate versions of APIs will become deprecated and replaced with closure/block versions. If you have the choice, I'd suggest using the closure/block form now to avoid the need to update later, not to mention it's just the simpler solution.
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.
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.
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 am writing an iPhone application which in numerous places needs to perform non HTTP or FTP networking of a very simple request response type.
I've wrapped all this up into a SimpleQuery class that integrates with the run loop.
SimpleQuery *lookup = [[SimpleQuery alloc] init];
[lookup setDelegate:self];
[lookup doQueryToHost:queryServer port:queryPort query:queryString ];
As you can see the calling object sets itself as a delegate. When the results are complete it then calls a method on the delegate with the results.
[delegate simpleQueryResult:resultString simpleQuery:self];
I am now in a position where I have a user of SimpleQuery that has two types of query so I need to extend SimpleQuery to support this.
I can think of two sensible ways of doing this.
Firstly passing a selector into doQueryString, or a seperate doQueryStringWithSelector.
[lookup doQueryToHost:queryServer port:queryPort query:queryString selector:#SEL ];
Secondly passing a tag into doQueryString so that when the delegate is called it can query the tag, as the simpleQuery is passed, to find out what the results are for.
[lookup doQueryToHost:queryServer port:queryPort query:queryString withTag:tag ];
I'm just wondering which is best from a coding style perspective, the first seems simpler but tagging seems more in keeping with the iPhone SDK and Interface Builder
An option which is used commonly in Apple's code (for example, in UIControl) is to provide both a target object and a selector. This works only if there is a single callback, and is more appropriate than a delegate in that case. (If there are multiple callbacks, then you'll probably have to go with a delegate and the tag approach.)
If you go this route, then you do away with the delegate altogether and instead have a method with a signature like this:
doQueryToHost:(id)queryServer port:(int)queryPort query:(NSString*)queryString target:(id)target action:(SEL)action
Note that "action" is typically preferred over "selector" in methods arguments in this case. The query would simply call the selector on the target when done. This would allow your clients to have multiple selectors, and also multiple target objects; this can help clean up code because you don't need to shove everything into a single delegate object.
If you want to go with your tag route, you should call it "context", which is what Apple uses (for example, in addObserver:forKeyPath:options:context).
There's a third option that's a common pattern in the kits, which is to use #protocols.
For example:
#protocol QueryCompleteHandlerProtocol
- (void)queryType1Complete:(int)intStuff;
- (void)queryType2Complete:(float)floatStuff;
#end
What this does is declare a set of method calls that an object adopting the protocol has to conform to (the compiler will actually enforce this).
So your SimpleQuery object will hold on to something like the delegate pointer, which you might declare like this among the ivars:
NSObject<QueryCompleteHandlerProtocol> *callback;
What this tells the compiler is that callback is an object that descends from NSObject and adopts the QueryCompleteHandlerProtocol protocol. Sometimes you see this written as:
id<QueryCompleteHandlerProtocol> callback;
When you want to call the callback there's nothing special about them, SimpleQuery's methods will just call:
[callback queryType1Complete:1];
[callback queryType2Complete:2.0];
Finally you client for the procotol class will declare itself as adopting the protocol:
#interface MyClass : NSObject<QueryCompleteHandlerProtocol>
...
#end
And will set itself as the callback with some code like:
[lookup setCallback:self];
This is where the compiler checks that MyClass conforms to QueryCompleteHandlerProtocol, meaning it has implemented queryType1Complete: and queryType2Complete:.
I'm not sure I understand the problem here. Can't SimpleQuery's user just set another delegate object for the second query, or branch on the simpleQuery: parameter? That's a basic part of the delegate pattern, just like having two UIActionSheets for one view controller.