我为Objective-C购买了Big Nerd Ranch指南,但有一些关于NSRunLoop
我无法弄清楚的内容。
这是本书中的一大块代码:
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2.0
target:logger
selector:@selector(updateLastTime:)
userInfo:nil
repeats:YES];
[[NSRunLoop currentRunLoop] run];
我的问题是,为什么我需要为要处理的NSRunLoop
对象设置NSTimer
?为什么它需要在最后,而不是开始?
为什么它不像其他函数或对象的方法,我只需要调用一个函数来处理它并登录到控制台?
我真的想弄清楚每个细节的每一个逻辑。
答案 0 :(得分:3)
从可可的早期开始,当恐龙在地球上漫游时,岩石变得柔软,NeXT工作站是新的,直到10.6出现,最常见的多任务类型是运行循环。它是合作的多任务处理。没有主题。没有抢占式调度程序或内核。没有上下文切换。这只是一个大运行循环,说明了现在需要做什么?"并运行它。当那件事情完成时,它会等待下一件需要做的事情并运行它。它实际上是一个很大的while(true)
循环。从技术上讲,代码行是:
for (;;) { ... }
您可以在CFRunLoop.c中亲眼看到。寻找__CFRunLoopRun
。
NSTimer
是在那些日子发明的。所有这一切都在runloop中做了记录告诉它"当这个时间过去了,那么请这样做。" (它有点复杂,因为它使用了马赫端口,在同一个文件中查找__CFRunLoopTimerSchedule
以获取详细信息,但基本上就是这个想法。)
所以重点是,没有魔力。只有一个很大的for(;;)
循环来处理这些东西。有东西必须运行它。当你启动它时(使用run
),它不会返回。这是一个无限循环。没有"背景。"没有其他线程。这就是为什么你需要按照BNR告诉你的顺序做事。否则你的下一行代码将无法运行。
当然,在iOS应用和OS X GUI应用中,您通常不必自己动手。在程序启动期间为您创建运行循环,并且整个主线程都在其中。这是大部分时间都会给你打电话的事情。你不打电话。但是如果您使用主线程以外的线程,并且想要使用运行循环功能,那么您将不得不自己运行它。
今天,很多事情都是用GCD完成的,而不是运行循环。那是"直到10.6出现"我提到过。它真的改变了可可世界。但是大量的Cocoa仍然依赖于运行循环,即使你从未想过它,它仍然是大多数应用程序的主力。
在今天的大多数情况下,如果您必须创建一个runloop才能使用NSTimer
,那么您就不应该使用NSTimer
。只需使用dispatch_after
即可。事实上,即使你做有一个runloop,这是我今天大部分时间通常推荐的。
(你肯定应该阅读评论中@quelish给出的链接。它是关于运行循环的权威词。)