使用-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器按照它们排队的顺序依次执行。