IOS run loop nsunloop

Source: Internet
Author: User

In phone application development, the overview of the nsunloop is described in this article. The nsunloop is a better message processing mode, he is capable of better abstraction and encapsulation of the message processing process, so that you don't have to process some very trivial and low-level specific messages, in the nsunloop, each message is packaged in the input source or timer source. Let's take a look at the details.

1. What is nsunloop?

We often see thisCode:

    1. -(Ibaction) Start :( ID) sender
       
    2. {
       
    3. Pagestillloading = yes;
       
    4. [Nsthread detachnewthreadselector: @ selector (loadpageinbackground :) totarget: Self withobject: Nil];
       
    5. [Progress sethidden: No];
       
    6. While (pagestillloading ){
       
    7. [Nsunloop currentrunloop] runmode: nsdefaultrunloopmode beforedate: [nsdate distantfuture];
       
    8. }
       
    9. [Progress sethidden: Yes];
       
    10. }

Copy code

This code is amazing because it will "pause" the Code andProgramThe running will not be affected because there is a while loop. After [Progress sethidden: No] is executed, the entire function is paused and stops in the loop. After the operations in loadpageinbackground are completed, the [Progress sethidden: Yes] can be run. This is a brief introduction and the logic is clear. If you do not do this, you need to call [Progress sethidden: Yes] In the loadpageinbackground to indicate that the load is complete. It seems that the Code is not compact and error-prone.
[Igoogle has the saying that the main thread of the application framework has encapsulated the call to the nsunloop runmode: beforedate:; it and the while loop constitute a message pump that continuously obtains and processes messages; it may be strange to everyone that since the main thread has encapsulated the call to the nsunloop, why can we call it again here? This is the difference between it and Windows message loop, and it can be nested calls. when the while + nsunloop is called again, the program does not stop execution, and the program continuously extracts or processes messages. this is the same as the nested call of active scheduler in Symbian to achieve synchronization.]

So what is nsunloop? In fact, the essence of the nsunloop is a message mechanism processing mode. If you have some knowledge of VC ++ programming, there are a series of important functions in windows, such as sendmessage, postmessage, and getmessage, which are APIs for message passing and processing.

But when you enter the cocoa programming world, I don't know if you are too fast or too hasty to ignore this very important question, cocoa does not mention any APIs for message processing. Developers have never cared about the message transmission process themselves. It seems that everything is so natural and as natural as nature? In cocoa, you no longer need to define a macro such as wm_commad_xxx to identify a message, or perform special processing on a specific message in switch-case. Is there no message mechanism in cocoa? The answer is no, but apple adopts a better model when designing message processing, that is, runloop.

2. Working Principle of nsunloop

Next, let's take a look at the specific working principle of the nsunloop. The first is the statement provided in the official documentation, as shown in the figure:

All "messages" are added to the nsunloop, here, these messages are divided into "Input Source" and "timer source", and check whether there is an event in the loop. If necessary, call the corresponding function for processing. For a clearer explanation, we will compare the message processing processes of VC ++ and IOS.

In VC ++, After all initialization is complete, the program starts such a loop (the code is intercepted from the slides of the Sir MFC Program Design Course ):

    1. Int apientry winmain (hinstance, hinstance hprevinstance, lpstr lpcmdline, int ncmdshow ){
       
    2. ...
       
    3. While (getmessage (& amp; MSG, null, 0, 0 )){
       
    4. If (! Translateaccelerator (msg. hwnd, hacceltable, & amp; MSG )){
       
    5. Translatemessage (& amp; MSG );
       
    6. Dispatchmessage (& amp; MSG );
       
    7. }
       
    8. }
       
    9. }

We can see that after getmessage, we can distribute and process the message. In iOS, the main function only calls uiapplicationmain, so we can think that uiapplicationmain will enter this situation after Initialization is complete:

    1. Int uiapplicationmain (...){
       
    2. ...
       
    3. While (running ){
       
    4. [Nsunloop currentrunloop] runmode: nsdefaultrunloopmode beforedate: [nsdate distantfuture];
       
    5. }
       
    6. ...
       
    7. }

Therefore, in uiapplicationmain, the program is also constantly processing runloop. I just mentioned that the nsunloop is a better message processing mode, and he is better at abstracting and encapsulating the message processing process, in this way, you do not need to process some very trivial and low-level specific messages. In the nsunloop, each message is packaged in the input source or timer source, when processing is required, the corresponding object processing function is called directly.

So what you feel for external developers is to add source/timer to the runloop, and then something like [handler action] will happen as appropriate. Most of the time, you don't even feel the first half of the process. You just feel a function call to an object.

For example, when a uiview is touched, a function such as touchesbegan/touchesmoved is called. You may think, "Damn it, I don't know where I was notified of a touch message, these processing functions are called !?" Therefore, there are some messages, but runloop has already helped you! To prove my point of view, I intercepted a call stack of DEBUG touchesbegan,
 

 

 

Nsoperation thread blocking by using nsunloop
The introduction of Multithreading is introduced in the use of nsoperationqueue to simplify multithreading development. Here I will mainly introduce the use of nsunloop to block threads.
It is mainly used for tasks enabled on nstimer or asynchronous data retrieval. For example, if a socket obtains network data, it is necessary to block the thread until the thread is released after the data is obtained.
The following is the code and execution effect of the thread that does not use the nsunloop to block the thread:
Thread class:

# Import <Foundation/Foundation. h>
@ Interface mytask: nsoperation {
}
@ End

# import "mytask. H "
@ implementation mytask
-(void) main
{< br> nslog (@ "start thread =%@", self);
[nstimer timerwithtimeinterval: 2 target: Self selector: @ selector (hiandetime :) userinfo: Nil repeats: No];
}< br>-(void) hiandetime :( ID) sender
{< br> nslog (@ "nstimer executed");
}< br>-(void) dealloc
{< br> nslog (@ "delloc mytask =%@", self);
[Super dealloc];
}
@ end

Add a thread to a queue:

-(Void) viewdidload
{
[Super viewdidload];
Nsoperationqueue * queue = [[nsoperationqueue alloc] init];
Mytask * mytask = [[mytask alloc] init] autorelease];
[Queue addoperation: mytask];
Mytask * mytask1 = [[mytask alloc] init] autorelease];
[Queue addoperation: mytask1];
Mytask * mytask2 = [[mytask alloc] init] autorelease];
[Queue addoperation: mytask2];
[Queue release];
}
The execution result is:
09:44:45. 393 operationdemo [20676: 1803] Start thread = <mytask: 0x4b4dea0>
09:44:45. 393 operationdemo [20676: 5d03] Start thread = <mytask: 0x4b50db0>
09:44:45. 396 operationdemo [20676: 1803] Start thread = <mytask: 0x4b51070>
09:44:45. 404 operationdemo [20676: 6303] delloc mytask = <mytask: 0x4b4dea0>
09:44:45. 404 operationdemo [20676: 5d03] delloc mytask = <mytask: 0x4b50db0>
09:44:45. 405 operationdemo [20676: 6303] delloc mytask = <mytask: 0x4b51070>
We can see that the nstimer method is not executed at all, and the thread is released. We need to execute
In nstimer, we need to use the nsunloop method to block the thread. The modified code is as follows:

-(Void) Main
{
Nslog (@ "start thread =%@", self );
Nstimer * timer = [nstimer timerwithtimeinterval: 2 target: Self selector: @ selector (hiandetime) userinfo: Nil repeats: No];
[Timer fire];
While (! Diddisconnect ){
[[Nsunloop currentrunloop] runmode: nsdefaultrunloopmode beforedate: [nsdate distantfuture];
}
}

The execution result is as follows:

10:07:00. 543 operationdemo [21270: 1803] Start thread = <mytask: 0x4d16380>
10:07:00. 543 operationdemo [21270: 5d03] Start thread = <mytask: 0x4d17790>
10:07:00. 550 operationdemo [21270: 6303] Start thread = <mytask: 0x4d17a50>
10:07:00. 550 operationdemo [21270: 1803] executed nstimer
10:07:00. 551 operationdemo [21270: 5d03] executed nstimer
10:07:00. 552 operationdemo [21270: 6303] executed nstimer
10:07:00. 556 operationdemo [21270: 6503] delloc mytask = <mytask: 0x4d16380>
10:07:00. 557 operationdemo [21270: 6303] delloc mytask = <mytask: 0x4d17790>
10:07:00. 557 operationdemo [21270: 5d03] delloc mytask = <mytask: 0x4d17a50>

We can use nsunloop for thread blocking.

 

 

Use runloop to block threads

Runloop can block threads and wait for other threads to execute.

For example:

@ Implementation viewcontroller {
Bool end;
}
...
-(Void) viewdidload
{
[Super viewdidload];
Nslog (@ "Start new thread ...");
[Nsthread detachnewthreadselector: @ selector (runonnewthread) totarget: Self withobject: Nil];
While (! End ){
Nslog (@ "runloop ...");
[[Nsunloop currentrunloop] runmode: nsdefaultrunloopmode beforedate: [nsdate distantfuture];
Nslog (@ "runloop end .");
}
Nslog (@ "OK .");
}
-(Void) runonnewthread {
Nslog (@ "run for new thread ...");
Sleep (1 );
End = yes;
Nslog (@ "end .");
}

However, in this way, the running will find that the statement executed after the while loop will be executed after a long time.

Can it be like this:

[[Nsunloop currentrunloop] runmode: nsdefaultrunloopmode beforedate:[Nsdate datewithtimeintervalsincenow: 0.1]];

Shortening the sleep time of runloop seems to solve the above problems.

However, this is also a problem. The runloop object is often awakened, which violates the original design intention of the runloop. Runloop is used to reduce unnecessary idling of the CPU. The CPU can sleep during idle time to save power.

How can this problem be solved? The correct statement is as follows:

-(Void) runonnewthread {

Nslog (@ "run for new thread ...");
Sleep (1 );
[Self defined mselecw.mainthread: @ selector (setend) withobject: Nil waituntildone: No];
Nslog (@ "end .");
}
-(Void) setend {
End = yes;
}

See the italic text section. Change the directly set variable to send messages to the main thread and execute the methods. The problem is solved.

The reason for the delayed execution of the while loop statement is that the runloop is not awakened. Because the runloop object does not know how to change the value of a variable. The delay duration is always variable because other events wake up the main thread at a certain time point, which ends the while loop. Then, sending messages to the main thread will wake up the runloop, so the problem is solved.

Nsunloop runmode: Nsdefaultrunloopmode/Nsunloopcommonmodes   Eg. [[Nsunloopcurrentrunloop] addtimer: timer formode:Nsunloopcommonmodes]; [[Nsunloop currentrunloop] runmode: nsdefaultrunloopmode beforedate: [nsdate distantfuture];
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.