Ios-run Loop Learning Summary

Source: Internet
Author: User
Tags instance method terminates



Do not know if you have ever thought about this problem, an application started executing after it was put there, assuming that it was not done correctly whatever the operation. The application is as ingenious as it is, and does not spontaneously have any action whatsoever. But suppose we click on a button on the interface. At this point, a corresponding button response event occurs. It feels like the app is always on standby. It is resting when no one is working, and it responds immediately when it is allowed to work. In fact, this is the credit of the run loop.


One, thread and run loop


1.1 Types of thread tasks
Then talk about threading. Some threads perform tasks that are a straight line, a starting point to an end point, and some threads have a circle to work on. Keep looping until it terminates in some way.



The line thread, like the simple Hello World, finishes printing, and its life cycle is over. Like a flash in the pan, a circle type like an operating system that executes until you shut down. In iOS, a round thread is implemented through a loop of run loops.



1.2 The relationship between a thread and a run loop
Run loop, as its name implies, loops represent a loop, which, together with run, represents a loop that has been executing. In fact, the run loop is tightly connected to the thread, so that the run loop is meant to be threaded and has no threads. It is not necessary to exist. Run loops is the infrastructure part of the thread, and both cocoa and corefundation provide the run loop object for easy configuration and management of the thread's run loop (cocoa for example below).



Each thread. The main thread, which contains the program, has a run loop object corresponding to it.



The run loop of the 1.2.1 main thread is started by default.




iOS applications, the program starts with a main () function such as the following:


 
int main(int argc, char *argv[])

     { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([appDelegate class]));

           }

  }


The focus is on the Uiapplicationmain () function, which sets a Nsrunloop object for the main thread, which explains why our application is able to rest in an unmanned operation and respond immediately when it needs to work.



1.3 A few notes on the run loop
The Nsrunloop class in 1.3.1 cocoa is not thread-safe



We can no longer manipulate the run loop object of another thread in one thread. That is very likely to cause unintended consequences.



Fortunately, the opaque class cfrunloopref in Corefundation is thread-safe, and both types of run loops can be used in a mixed manner. The Nsrunloop class in cocoa is able to pass an instance method:


    • (Cfrunloopref) Getcfrunloop;


Gets the corresponding Cfrunloopref class. To achieve the purpose of thread safety.



The management of the 1.3.2 Run loop is not entirely self-motivated.
We still have to design the thread code to start the run loop at the appropriate time and respond correctly to the input event, if the run loop is needed in the thread. Also, we need to use the WHILE/FOR statement to drive the run loop to execute. The following code succeeds in driving a run loop:


BOOL isRunning = NO; do {

            isRunning = [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDatedistantFuture]];

     } while (isRunning);


1.3.3 Run Loop is also responsible for the creation and release of Autorelease pool at the same time
In projects that use manual memory management, many of the objects that are actively released by themselves are often used, assuming that these objects cannot be released immediately, resulting in a sharp increase in memory consumption. The run loop does this for us, and whenever an execution loop ends, it releases the Autorelease pool, and all of the active release type variables in the pool are freed at the same time.



Advantages of 1.3.4 Run loop
A run loop is an event-processing loop that continuously listens and processes input events and assigns them to the corresponding targets for processing. Assuming that you just want to implement this function, you might think that a simple while loop will not be able to achieve it, you need to cost the boss to do a complex mechanism? Obviously, Apple architects are not eating cooked rice, and you think of them long ago.



First of all, Nsrunloop is a more sophisticated message processing model, and he has a better abstraction and encapsulation of the message processing process, so that you do not have to deal with some very trivial and very low-level details of the processing, in Nsrunloop each message is packaged in the input source or timer source (see below).



Secondly, it is also a very important point. Using Run loop enables your thread to work at work and hibernate when it is not working, which can greatly save system resources.





Second, Run loop related knowledge points


2.1 Input Event Source
The Run loop receives input events from two different sources: the input source and the timing feed (timer source). Both provenances use a specific processing routine of the program to handle the event that arrives. Figure 1 shows the conceptual structure of the run loop and the various sources.



What needs to be explained is. When you create an input source. You need to assign it to one or more patterns in the run loop (what is a pattern, as described below). The pattern only affects the source of the listener in a particular event.



In most cases, run loop executes in the default mode. But you can also make it perform in your own definition mode. If a source is not being monitored in the current mode, then whatever its generated message is only passed in its associated mode in the run loop execution.
Figure 1 Runloop structure and input source type



2.1.1 Input source
Passes an asynchronous event, typically a message from another thread or program. The input source passes the asynchronous message to the corresponding processing routine and calls the Rununtildate: method to exit (The associated Nsrunloop object call within the thread).



2.1.1.1 Port-based input source
Port-based input sources are sent by the kernel on its own initiative.
The Cocoa and core foundation built-in supports port-based sources that are created using port-related objects and functions.



For example, you never need to create an input source directly in cocoa. You simply create the Port object and use the Nsport method to add the port to the run loop. The Port object processes the creation and configuration of the input source itself.
In core Foundation, you must manually create the port and its run loop source. We are able to use port-related functions (cfmachportref,cfmessageportref. CFSOCKETREF) to create the appropriate object.



The following example shows how to create a port-based input source, add it to the run loop, and start:


voidcreatePortSource()
{
    CFMessagePortRef port = CFMessagePortCreateLocal(kCFAllocatorDefault, CFSTR("com.someport"),myCallbackFunc, NULL, NULL);
    CFRunLoopSourceRef source =  CFMessagePortCreateRunLoopSource(kCFAllocatorDefault, port, 0);
    CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopCommonModes); while (pageStillLoading) {
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        CFRunLoopRun();
        [pool release];
    }
    CFRunLoopRemoveSource(CFRunLoopGetCurrent(), source, kCFRunLoopDefaultMode);
    CFRelease(source);
}


2.1.1.2 define the input source yourself
The input source that you define needs to be sent manually from other threads.
In order to create a self-defined input source, you must use the Cfrunloopsourceref type-related function inside the core foundation to create it.



You can use a callback function to configure your own definition input source. Core Fundation calls the callback function at different places in the configuration source to handle the input event. Clean it up when the source is removed from the run loop.
In addition to defining the behavior of the input source itself when the event arrives, you must also define the message passing mechanism. This part of the source is executed in a separate thread. It is responsible for passing the data to the source and notifying it to process the data when the data waits for processing. The definition of a messaging mechanism depends on you. But it's better not to be too complicated. Create and start your own definition of the input source as shown in the following scale:


voidcreateCustomSource()
{
    CFRunLoopSourceContext context = {0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
    CFRunLoopSourceRef source = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &context);
    CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopDefaultMode); while (pageStillLoading) {
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        CFRunLoopRun();
        [pool release];
    }
    CFRunLoopRemoveSource(CFRunLoopGetCurrent(), source, kCFRunLoopDefaultMode);
    CFRelease(source);
}


Selector source on 2.1.1.3Cocoa
In addition to port-based sources. Cocoa defines its own input source and agrees that you execute the Selector method regardless of the thread. As with Port-based sources. Execution of the selector request is serialized on the target thread. Slow down many of the synchronization issues that are caused by agreeing to multiple methods on the thread.



It is not like a port-based source. Once a selector executes, it will voluntarily remove itself from the run loop.
When executing selector on other threads, the target thread must have an active run loop. For the thread that you created. This means that the thread will not execute the Selector method until you explicitly start the run loop. It is always dormant.




The NSObject class provides similar selector methods such as the following:


- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)argwaitUntilDone:(BOOL)wait modes:(NSArray *)array;


2.1.2 Timing Sources (timer source)
The timing source passes the message at a preset point-in-time synchronization mode. These messages can occur at a specific time or over a recurring interval. The timing source passes the message directly to the processing routine and does not exit the run loop immediately.
It is important to note that although timers can generate time-based notifications, it is not a real-time mechanism. As with the input source, the timer is also related to the specific mode of your run loop.



Assuming that the mode in which the timer is located is not currently monitored by the run loop, the timer will not start until the run loop executes in the corresponding mode. Similarly, assume that the timer starts when the run loop processes an event. The timer waits until the next run loop starts the corresponding handler.



Assuming that the run loop is no longer executing, the timer will never start.
There are two ways of creating a timer source.


method one:
NSTimer * timer = [NSTimer scheduledTimerWithTimeInterval: 4.0
                                                      target: self
                                                    selector: @selector (backgroundThreadFire :) userInfo: nil
                                                     repeats: YES];
     [[NSRunLoop currentRunLoop] addTimer: timerforMode: NSDefaultRunLoopMode];

Method Two:
[NSTimer scheduledTimerWithTimeInterval: 10
                                         target: self
                                        selector: @selector (backgroundThreadFire :)
                                        userInfo: nil
                                        repeats: YES];


2.2 Runloop Observer
The source is triggered when an appropriate synchronous or asynchronous event occurs, while the run loop watcher is triggered at a specific time when the run loop itself executes.



You can use the Run Loop Viewer to prepare for processing a particular event or entering a dormant thread.



You can associate a run loop observer with the following event:
1. Runloop Entrance
2. Runloop when to process a timer
3. Runloop when to process an input source
4. When Runloop enters sleep state
5. When the Runloop is awakened, but the event to be processed before waking
6. Runloop Termination
Similar to timers, when created you can specify that the run loop observer can be used only once or in a loop. If only used once. So after it's started. Will remove itself from the run loop, and the observer of the loop will not. Define the viewer and add it to the run loop. Only the core fundation can be used.



The following example shows how to create an observer for the run Loop:


- (void)addObserverToCurrentRunloop
{ // The application uses garbage collection, so noautorelease pool is needed. NSRunLoop*myRunLoop = [NSRunLoop currentRunLoop]; // Create a run loop observer and attach it to the runloop. CFRunLoopObserverContext  context = {0, self, NULL, NULL, NULL};
   CFRunLoopObserverRef    observer =CFRunLoopObserverCreate(kCFAllocatorDefault,
                                                              kCFRunLoopBeforeTimers, YES, 0, &myRunLoopObserver, &context); if (observer)
    {
        CFRunLoopRef    cfLoop = [myRunLoop getCFRunLoop];
       CFRunLoopAddObserver(cfLoop, observer, kCFRunLoopDefaultMode);
    }
}


Of Kcfrunloopbeforetimers indicates the selection of the listener timer to trigger the pre-processing event. The following yes indicates cyclic listening.



2.3 Runloop Event Queue
Execute the Run loop every time. The run loop on your thread will proactively handle messages that were not processed before and notify the relevant observers. The detailed order is for example the following:
Notifies the watcher that the run loop has started
Notifies the observer that no matter what timer is about to start
Notifies the Observer that no port-based source is about to start
Start whatever is prepared for a non-port-based source
Assuming that the port-based source is ready and in a wait state, start immediately and proceed to step 9.




Notifies the watcher thread to enter hibernation
Put a thread into hibernation until any one of the following events occurs:
An event arrives at a port-based source
Timer start
Time for Run loop setting has timed out
Run loop is explicitly awakened
Notifies the Observer that the thread will be awakened.
Handling Unhandled Events
Assume that the user-defined timer starts, processes the timer event, and restarts the run loop.



Go to step 2
Assuming the input source is started, pass the corresponding message
If the run loop is explicitly awakened and the time has not expired, restart the run loop. Go to step 2
Notifies the Observer that run loop is finished.




Because the observer for the timer and the input source passes the message before the corresponding event occurs, there may be an error between the time of the notification and the time the actual event occurred. It is assumed that precise time control is required. You can use hibernation and wake-up notifications to help you proofread the actual event time.




Because the timer and other recurring events often need to be passed when you execute the run loop, revoking the run loop also terminates message delivery.



A typical example is mouse path tracking.



Because your code obtains the message directly rather than passing it through the program, the active timer does not start until the mouse trace is over and gives control to the program.
The run loop can be explicitly awakened by the run loop object. Other messages can also wake up the run loop.



For example, adding a new non-port-based source wakes up the run loop so that it can process the input source immediately without waiting for other events to occur before processing.




From this event queue, you can see:
① assumes that the event arrives, the message is passed to the corresponding handler for processing, and the run loop exits when Runloop finishes processing the event. And no matter how long it was before the scheduled time. You can start the run loop again to wait for the next event.
② assumes that there are sources in the thread that need to be processed, but when the event of the response does not arrive, the thread sleeps and waits for the corresponding event to occur. That's why the run loop is able to keep the thread busy while it's working. It is dormant when you are not working.



2.4 When to use the run loop
You need to explicitly execute a run loop only if you are creating a worker thread for your program. Run Loop is a key part of the program's main thread infrastructure. Therefore, the cocoa and carbon programs provide a loop for the code to execute the main program and initiate the run loop on its own initiative. The UIApplication run method in the iOS program (or nsapplication in Mac OS x) is part of the program startup step, which starts the program's main loop when the program starts normally. Similar to. The Runapplicationeventloop function starts the main loop for the carbon program. Assuming you create your program using the templates provided by Xcode, you never have to explicitly call these routines yourself.
For worker threads. You need to infer whether a run loop is required. Assumptions are necessary. Then you have to configure and start it yourself.



You don't need to start a thread's run loop under any circumstances.



For example, you use a thread to handle a predefined long-run task. You should avoid starting the run loop.



The Run loop is required when you have a lot of other interactions with the thread. For example, the following conditions:
Use port or define your own input source to communicate with other threads
Using the thread's timer
Cocoa in the use of whatever performselector ... The method
Make threads work periodically
Suppose you decide to use the run loop in your program. Then it's very easy to configure and start.



As with all thread programming. You need to plan the situation where the worker thread exits the thread.



It is often better to let a thread quit naturally than to force it off.



Study Links:


    • http://blog.csdn.net/ztp800201/article/details/9240913
    • Http://www.360doc.com/content/16/0302/04/31139390_538698652.shtml
    • Http://www.cnblogs.com/cqb-learner/p/5859431.html


Ios-run Loop Learning Summary


Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.