Can anyone explain for what is NSRunLoop
? so as I know NSRunLoop
is a something connected with NSThread
right? So assume I create a Thread like
NSThread* th=[[NSThread alloc] initWithTarget:self selector:@selector(someMethod) object:nil];
[th start];
-(void) someMethod
{
NSLog(@"operation");
}
so after this Thread finishes his working right? why use RunLoops
or where to use ? from Apple docs I have read something but its not clear for me, so please explain as simple as it possible
They allow you to wait till user taps and respond accordingly, wait till you get a completionHandler and apply its results, wait till you get a timer and perform a function. If you don't have a runloop then you can't be listening/waiting for user taps, you can't wait till a network call is happening, you can't be awoken in x minutes unless you use
DispatchSourceTimer
orDispatchWorkItem
Also from this comment:
Specifically about: "Background threads don't have their own runloops". The following timer fails to fire for an async dispatch:
I think the reason the
sync
block also runs is because:sync blocks usually just get executed from within their source queue. In this example, source queue is main queue, the whatever queue is the destination queue.
To test that I logged
RunLoop.current
inside every dispatch.The sync dispatch had the same runloop as main queue. While the RunLoop within the async block was a different instance from the others. You might be thinking how why does
RunLoop.current
return a different value. Isn't it a shared value. Great question! Read further:IMPORTANT NOTE:
The class property
current
is NOT a global variable.It's contextual ie visible only within the scope of the thread ie Thread-local storage). For more on that see here.
This is a known issue with timers. You don't have the same issue if you use
DispatchSourceTimer
A run loop is an abstraction that (among other things) provides a mechanism to handle system input sources (sockets, ports, files, keyboard, mouse, timers, etc).
Each NSThread has its own run loop, which can be accessed via the currentRunLoop method.
In general, you do not need to access the run loop directly, though there are some (networking) components that may allow you to specify which run loop they will use for I/O processing.
A run loop for a given thread will wait until one or more of its input sources has some data or event, then fire the appropriate input handler(s) to process each input source that is "ready.".
After doing so, it will then return to its loop, processing input from various sources, and "sleeping" if there is no work to do.
That's a pretty high level description (trying to avoid too many details).
EDIT
An attempt to address the comment. I broke it into pieces.
Indeed. NSRunLoop is not thread safe, and should only be accessed from the context of the thread that is running the loop.
If you want to monitor a port, you would just add that port to the run loop, and then the run loop would watch that port for activity.
You can also add a timer explicitly with
The run loop will process all ready events each iteration (according to its mode). You will need to look at the documentation to discover about run modes, as that's a bit beyond the scope of a general answer.
In most applications, the main run loop will run automatically. However, you are responsible for starting the run loop and responding to incoming events for threads you spin.
I am not sure what you mean here. You don't add events to the run loop. You add input sources and timer sources (from the thread that owns the run loop). The run loop then watches them for activity. You can, of course, provide data input from other threads and processes, but input will be processed by the run loop that is monitoring those sources on the thread that is running the run loop.
Indeed. In fact, a run loop will "stay" in an event handler until that event handler has returned. You can see this in any app simply enough. Install a handler for any IO action (e.g., button press) that sleeps. You will block the main run loop (and the whole UI) until that method completes.
The same applies to any run loop.
I suggest you read the following documentation on run loops:
https://developer.apple.com/documentation/foundation/nsrunloop
and how they are used within threads:
https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/Multithreading/RunLoopManagement/RunLoopManagement.html#//apple_ref/doc/uid/10000057i-CH16-SW1
From here
From here
RunLoops are a bit of like a box where stuff just happens.
Basically, in a RunLoop, you go to process some events and then return. Or return if it doesn't process any events before the timeout is hit. You can say it as similar to asynchronous NSURLConnections, Processing data in the background without interfering your current loop and but at the same time, you require data synchronously. Which can be done with the help of RunLoop which makes your asynchronous
NSURLConnection
and provides data at calling time. You can use a RunLoop like this:In this RunLoop, it will run until you complete some of your other work and set YourBoolFlag to false.
Similarly, you can use them in threads.
Hope this helps you.