Perform Selector and Delayed Perform

Selectors identify the messages that are sent to Objective-C objects.They’re used by
the receivers of messages to select which methods will be performed.

In particular, selectors are key to Cocoa’s
implementation of the Notifications, Delegates,Targets and Actions, Invocations, and Forwarding
patterns. Using selectors, Cocoa objects can be asked to perform methods immediately
or after arbitrary time delays.

Selectors are an object-oriented substitute for C function pointers.A function pointer
is a variable that stores the address of a compiled function. In the C programming language
and languages derived from it like Objective-C and C++, compilers and linkers
convert explicit function calls in program source code into machine language jumps to
code at predetermined fixed addresses in memory.The conversion of code to fixed addresses
in sometimes called binding. Using a function pointer variable enables programmers
to postpone binding of a function call until the program is running. For example,
the value of a function pointer might be partly determined by user input at runtime.The
technique is sometimes called late-binding. Just like using function pointers can postpone
specification of precisely what function will be called, using selectors can postpone specification
of precisely what message will be sent to an object.

 

Motivation
Use Perform Selector to postpone specifying the message that will be sent to an object
until runtime. Reduce coupling between objects by limiting the information that message
senders need about the message sent.
Use Perform Selector in combination with the Anonymous Type and Heterogeneous
Containers patterns described in Chapter 7,“Anonymous Type and Heterogeneous
Containers,” to completely decouple the sender of a message from the receiver.At
compile time, the sender of a message doesn’t need to know what message is sent or
what object will receive the message.This capability underlies the Targets and Actions
pattern.
Use Delayed Perform to schedule messages to be sent at a specified time in the future.

 

 

interdependent concepts:

Objects have methods of performing operations.A method is composed of program
code that’s part of the implementation of an object.

A message is a request for an object to perform an operation.The object determines
which method will be used to perform the operation.The same message can be
sent to different objects and produce different results.

A selector identifies the message sent to an object, and the object that receives the
message uses the selector to select which method to invoke.

 

Objective-C provides the SEL data type used to declare variables that store selectors.

SEL aSelector = @selector(update);

Cocoa’s NSObject base class provides the -(id)performSelector:(SEL)aSelector
method, which is used to send a variable message at runtime.The -performSelector:
method can be used in any situation where the message to be sent has no arguments and
returns an object.

SEL aSelector = @selector(update);
// These three lines are interchangeable
id result1 = [someObject update];
id result2 = [someObject performSelector:@selector(update)];
id result3 = [someObject performSelector:aSelector];

 The selector used with –performSelector: doesn’t have to be specified at compile
time. For example, Cocoa provides the SEL NSSelectorFromString(NSString *) C
function that converts a string into a selector.The string could come from any source; it
might even be based on user input.A selector can be converted back into a string using
Cocoa’s NSStringFromSelector() C function. 

NSObject provides the –(BOOL)respondsToSelector:(SEL)aSelector method that
can be used to verify that an object responds to a selector before sending a message.

id MYSendMessageToObject(NSString *userEnteredString, someObject)
{
SEL aSelector = NSSelectorFromString(userEnteredString)];
id result = nil;
if([someObject respondsToSelector:aSelector])
{
result = [someObject performSelector:aSelector];
}
return result;
}

  

To send a variable message that requires a single object argument, use NSObject’s
- (id)performSelector:(SEL)aSelector withObject:(id)anObject method.

You can send messages that require two object arguments using NSObject’s

- (id)performSelector:(SEL)aSelector 
               withObject:(id)anObject
               withObject:(id)anotherObject method.

 However, if you need to send a variable
message that requires more than two arguments or requires nonobject arguments or
returns a nonobject value, you need to use Cocoa’s NSInvocation class and the
Invocations pattern described in Chapter 20,“Invocations.” 

 

Delayed Perform

To send a message after a delay, use

NSObject’s - (void)performSelector:(SEL)aSelector
               withObject:(id)anArgument 
               afterDelay:(NSTimeInterval)delay

method.The
message with the specified selector and argument is scheduled and sent sometime after
the specified delay measured in seconds.

 

 

Messaging is implemented with the following two C functions or variations based on return types and platform-specific function calling conventions:

id objc_msgSend(id self, SEL op, ...);

id objc_msgSendSuper(struct objc_super *super, SEL op, ...);

 The messaging functions are the core of Objective-C. When the Objective-C compiler encounters a messaging expression such as [receiver someMessageSelector], it replaces that expression with code to call objc_msgSend(receiver, @selector(someMessageSelector)) in the compiled result. The objc_msgSend() function searches for a method implemented by the receiver that corresponds to the specified selector.

 If a suitable method is found, a corresponding C function pointer is used to call a funtion that implements the method. Function pointers that correspond to method implementation are stored in variables with the IMP type declared as follows: typedef id(*IMP)(id self,SEL _cmd, ...);

The objc_msgSendSuper(struct objc_super *super, SEL op, ...) begins the search for a method with the receiver's superclass and doesn't consider any methods implemented by the receiver itself.  [super someMessageSelector]

You can convert any code that sends messages into a function call via an IMP. Cocoa's NSObject base class provides methods to obtain an IMP directly:

-(IMP)methodForSelector:(SEL)aSelector;

+(IMP)instanceMethodForSelector:(SEL)aSelector;

So

-(id) performSelector:(SEL)aSelector
{
      IMP    methodImplementation = [self methodForSelector:aSelector];
      return (*IMP)(self, aSelector);?
}

 

Consequences

The Perform Selector and Delayed Perform patterns make it possible to send variable messages and send messages at variable times in the future.

From a software engineering perspective, Perform Selector and Delayed Perform are an applicaiton of late-binding to object-oriented systems.   

 

 

 

 

 

posted on 2013-02-22 16:02  Chansonyan  阅读(306)  评论(0)    收藏  举报

导航