performSelector方法是做什么的?

9

performSelector是什么?创建新的NSThread和使用performSelector方法有什么区别?

它是如何工作的,我们应该在哪里使用它?

2个回答

23

这些方法的作用都是一样的,即使得anObject对象上的doStuff方法在当前线程上同步执行:

// 1
[anObject doStuff];

// 2
[anObject performSelector:@selector(doStuff)];

// 3
objc_msgSend(anObject, @selector(doStuff));

// 4
IMP imp = [anObject methodForSelector:@selector(doStuff)];
imp(anObject, @selector(doStuff));
  1. 通常情况下,这是您执行操作的常规方式。
  2. 用于动态分配消息。如果选择器未知或由客户端提供,例如实现目标-动作模式或者anObject类别未知,则使用此方法。通常会首先使用 -[NSObject respondsToSelector:] 方法查询对象是否包含该方法。
  3. 实际上是将1转换为的形式。通常不需要这么做。
  4. 缓存了一个方法的实际IMP(实现),然后直接调用它。如果在紧密循环中使用,有时比方法1更快。但请记住,“过早优化是万恶之源”。

你需要理解的是,在Objective-C中,方法比类/接口更重要。通常情况下,您不需要查询对象是否属于特定类别或符合任何协议,这是编译器应该关注的问题。在运行时,您需要查询特定的方法。

简而言之:重要的不是你是什么,而是你能做什么。

方便起见,NSObject 还有几个异步的姐妹方法,其中最重要的是:

  • performSelector:withObject:afterDelay: - 以延迟的方式在当前线程上执行该方法。
  • performSelectorInBackground:withObject: - 在新的后台线程上执行该方法。
  • performSelectorOnMainThread:withObject:waitUntilDone: - 在主线程上执行该方法。
  • performSelector:onThread:withObject:waitUntilDone: - 在任何线程上执行该方法。

所有异步执行的方法都依赖于NSRunLoop。除非您自己创建线程,否则无需担心这一点。如果确实要创建线程,则还需要运行新线程的运行循环。现在暂时跳过这些。


1
在不知道对象的类的情况下,您可以使用直接的方法调用 -- id foo; if ([foo respondsToSelector:@selector(bar)]) [foo bar]; 当您在编译时不知道要调用的选择器时(例如从另一个对象发送过来的,或者是用户可选的等),您需要使用performSelector: - Daniel Dickison
(3) 有时很有用,因为 (2) 只能处理参数全部为对象且返回类型为对象或 void、且只有 0-2 个参数的方法。对于其他任何情况,都可以使用 (3)。 - user102008
感谢您提供详细的描述。 - Nguyen Minh Binh
关于“方法比类/接口更重要”的评论很有见地,解释了Objective-C和其他面向对象编程环境之间的一个关键区别。谢谢。 - Basil Bourque

2

performSelector执行一个选择器。换句话说,它调用一个方法。

它与运行新线程非常不同。

我认为最好您阅读有关选择器的内容。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接