我在学习Objective-C,想知道下面两个语句的区别:
[object performSelector:@selector(doSomething)];
[object doSomething];
我在学习Objective-C,想知道下面两个语句的区别:
[object performSelector:@selector(doSomething)];
[object doSomething];
performSelector基本上允许您动态确定要在给定对象上调用哪个选择器。换句话说,选择器不需要在运行时之前确定。
因此,即使这些是等效的:
[anObject aMethod];
[anObject performSelector:@selector(aMethod)];
第二种形式允许您这样做:SEL aSelector = findTheAppropriateSelectorForTheCurrentSituation();
[anObject performSelector: aSelector];
在发送消息之前。
对于这个问题中的非常基本的示例,
[object doSomething];
[object performSelector:@selector(doSomething)];
将要发生的事情并没有什么区别。 doSomething方法将由对象同步执行。 只是“doSomething”是一个非常简单的方法,不返回任何内容,也不需要任何参数。
如果这是一些更复杂的内容,比如:
(void)doSomethingWithMyAge:(NSUInteger)age;
如果使用“performSelector”任何变种,调用[object doSomethingWithMyAge:42]就会变得复杂,因为只有带对象参数的变种才能接受参数。 这里的选择器将是“doSomethingWithMyAge:”,但任何尝试
[object performSelector:@selector(doSomethingWithMyAge:) withObject:42];
代码无法编译。即使传递NSNumber:@(42)而不是42也无济于事,因为该方法期望基本的C类型 - 而不是对象。
此外,performSelector变体最多有2个参数,没有更多了。而方法很多次有更多的参数。
我发现尽管performSelector有同步变体:
- (id)performSelector:(SEL)aSelector;
- (id)performSelector:(SEL)aSelector withObject:(id)object;
- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;
始终返回一个对象,但我也能够返回一个简单的BOOL或NSUInteger,并且它也可以工作。
performSelector的两个主要用途之一是动态组合您想要执行的方法的名称,如以前的答案中所解释的那样。例如:
SEL method = NSSelectorFromString([NSString stringWithFormat:@"doSomethingWithMy%@:", @"Age");
[object performSelector:method];
另一种用法是异步地向对象分派消息,稍后在当前运行循环中执行。为此,有几种其他的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;
(是的,我从几个Foundation类别中收集了它们,比如NSThread、NSRunLoop和NSObject)
每个变量都有自己特殊的行为,但所有变量都有一个共同点(至少在waitUntilDone设置为NO时)。"performSelector"调用会立即返回,在一段时间后,消息才会被放置在当前运行循环中。
由于延迟执行 - 自然地,方法的选择器中没有可用的返回值,因此所有这些异步变量都具有-(void)返回值。
希望我在某种程度上涵盖了这个问题...
@ennuikiller说得很对。动态生成的选择器在编译代码时不知道(通常也不可能知道)要调用的方法名时非常有用。
一个关键区别在于,-performSelector:
和相关方法(包括多线程和延迟变种)有些限制,它们设计用于带有 0-2 个参数的方法。例如,使用 6 个参数调用-outlineView:toolTipForCell:rect:tableColumn:item:mouseLocation:
并返回 NSString
相当麻烦,并且不受提供的方法支持。
NSInvocation
对象。 - Dave DeLongperformSelector:
及其相关方法都需要传递对象参数,这意味着你不能使用它们来调用(例如)setAlphaValue:
,因为它的参数是一个浮点数。 - Chuck这两者之间还有一个微妙的区别。
[object doSomething]; // is executed right away
[object performSelector:@selector(doSomething)]; // gets executed at the next runloop
performSelector:withObject:afterDelay:
的,但问题和你所提供的代码片段使用的是 performSelector:
,这是一个完全不同的方法。根据它的文档:<quote>performSelector:
方法相当于直接向接收者发送 aSelector
消息。</quote> - jscsperformSelector/performSelector:withObject/performSelector:withObject:afterDelay
这些方法的行为都相同,这是我的错误。 - avi
performSelector:
是你只有在类中实现目标-动作时才会用到的东西。而performSelectorInBackground:withObject:
和performSelectorOnMainThread:withObject:waitUntilDone:
这两个方法则更加常用。前者用于创建后台线程,后者则用于在后台线程中回调结果到主线程。 - PeyloWperformSelector
还可以用来抑制编译警告。如果你知道方法存在(例如使用respondsToSelector
后),它将阻止 Xcode 显示“可能无法响应your_selector
”的消息。但是不要仅仅使用它来代替查找警告的真正原因。 ;) - Marc