使用-performSelector:只是调用方法

对于Objective-C,我还是一个新手,我想知道以下两个语句有什么区别?

[object performSelector:@selector(doSomething)]; [object doSomething]; 

基本上performSelector允许你dynamic地决定哪个select器调用给定对象的select器。 换句话说,select器不需要在运行之前确定。

因此即使这些是相同的:

 [anObject aMethod]; [anObject performSelector:@selector(aMethod)]; 

第二种forms可以让你做到这一点:

 SEL aSelector = findTheAppropriateSelectorForTheCurrentSituation(); [anObject performSelector: aSelector]; 

在发送消息之前。

@ennuikiller是现货。 基本上,dynamic生成的select器对于在编译代码时不需要(通常不可能)知道要调用的方法的名称很有用。

一个关键的区别是-performSelector:和朋友(包括multithreading和延迟变体 )有一定的局限性,因为它们被devise用于0-2参数的方法。 例如,调用-outlineView:toolTipForCell:rect:tableColumn:item:mouseLocation:使用6个参数并返回NSString非常笨拙,并且不被所提供的方法支持。

对于这个问题中的这个非常基本的例子,

 [object doSomething]; [object performSelector:@selector(doSomething)]; 

发生的事情没有什么区别。 doSomething将被对象同步执行。 只有“doSomething”是一个非常简单的方法,不会返回任何东西,也不需要任何参数。

是否有点复杂一些,比如:

 (void)doSomethingWithMyAge:(NSUInteger)age; 

事情会变得复杂,因为[object doSomethingWithMyAge:42];

不能再调用任何“performSelector”变体,因为所有带参数的变体只接受对象参数。

这里的select器将是“doSomethingWithMyAge:”,但任何尝试

 [object performSelector:@selector(doSomethingWithMyAge:) withObject:42]; 

根本不会编译。 传递一个NSNumber:@(42)而不是42,也无济于事,因为该方法需要一个基本的Ctypes – 而不是一个对象。

另外,还有performSelectorvariables,最多2个参数。 虽然方法多次有更多的参数。

我发现,尽pipeperformSelector的同步变体:

 - (id)performSelector:(SEL)aSelector; - (id)performSelector:(SEL)aSelector withObject:(id)object; - (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2; 

总是返回一个对象,我也能够返回一个简单的BOOL或NSUInteger,它的工作。

performSelector的两个主要用途之一是dynamic组成你想要执行的方法的名称,正如前面的答案中所解释的那样。 例如

  SEL method = NSSelectorFromString([NSString stringWithFormat:@"doSomethingWithMy%@:", @"Age"); [object performSelector:method]; 

另一个用途是将消息asynchronous分派给对象,稍后在当前的runloop上执行。 为此,还有其他几个performSelector变体。

 - (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay inModes:(NSArray *)modes; - (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay; - (void)performSelector:(SEL)aSelector target:(id)target argument:(id)arg order:(NSUInteger)order modes:(NSArray *)modes; - (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait modes:(NSArray *)array; - (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait; - (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait modes:(NSArray *)array; - (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait; - (void)performSelectorInBackground:(SEL)aSelector withObject:(id)arg; 

(是的,我收集了几个基础类的类别,如NSThread,NSRunLoop和NSObject)

每个变体都有它自己的特殊行为,但是都有共同点(至less在waitUntilDone设置为NO时)。 “performSelector”调用将立即返回,并且在一段时间之后只能将对象的消息放在当前的runloop上。

由于延迟执行 – 当然,在select器的方法中没有可用的返回值,因此在所有这些asynchronousvariables中都有 – (void)返回值。

我希望我以某种方式覆盖这个…

select器有点像其他语言的函数指针。 当你在编译时不知道你想在运行时调用哪个方法时,你可以使用它们。 而且,像函数指针一样,它们只封装了调用的动词部分。 如果该方法有参数,则还需要传递它们。

一个NSInvocation服务于类似的目的,只是它将更多的信息绑定在一起。 它不仅包含动词部分,还包含目标对象和参数。 当你想用特定的参数调用一个特定对象的方法时,这个function非常有用,而不是现在,但是将来。 你可以构build一个合适的NSInvocation并在稍后启动。

两者之间还有一个细微的差别。

  [object doSomething]; // is executed right away [object performSelector:@selector(doSomething)]; // gets executed at the next runloop 

这是苹果文档的摘录

“performSelector:withObject:afterDelay:在下一个运行循环中,在一个可选的延迟时间之后,在当前线程上执行指定的select器,因为它等待直到下一个运行循环执行select器,这些方法提供了一个自动的小延迟当前正在执行的代码,多个排队的select器按照它们排队的顺序依次执行。

Interesting Posts