Analysis of run loop in iOS

Source: Internet
Author: User
Tags usleep

Analysis of run loop in iOS
Analysis of run loop in iOS

Although runloop is an important concept related to thread thinking, runloop in cocoa is not used much at all, but it is not getting started with its "why" in related blog posts ". So a few days of study, I have to share a rough text, as a note, write down its own. I am not very grateful for any errors or errors.

Run loop

After the thread is executed, it will be destroyed. To keep the thread running, we can get a run loop in the thread to keep the thread running:

- (void)myThread:(id)sender{  while (TRUE) {    @autoreleasepool {      //do some jobs      //break in some condition      usleep(10000);    }  }}

Now the thread can run continuously. The new task comes: while this thread is running, you can also add or remove different computing tasks from other threads. This is what makes the nsunloop powerful.
Let's make a simple evolution:

NSMutableArray *targetQueue;NSMutableArray *actionQueue;- (void)myThread:(id)sender{  while (TRUE) {    @autoreleasepool {      //do some jobs      //break in some condition      NSUInteger targetCount = [targetQueue count];      for(NSUInteger index = 0; index < targetCount; ++index){        id target = targetQueue[index];        SEL action = NSSelectorFromString(actionQueue[index]);        if ([target respondsToSelector:action]) {          [target performSelector:action withObject:nil];        }      }      usleep(10000);    }  }}

From here, when we can add objects and methods to targetQueue and actionQueue in other threads at the same time, this thread can execute dynamically added code.
The so-called runloop is the following structure:

while (TRUE) {    //break in some condition}

This structure is the runloop of the thread. It is very similar to the name of the class "nsunloop", but it is not actually a thing. So what is nsunloop? Let's look at the following code:

@interface MyNSTimer : NSObject{    id target;    SEL action;    float interval;    CFAbsoluteTime lasttime;}- (void)invoke;@end@implementation MyNSTimer- (void)invoke;{    if ([target respondsToSelector:action]) {        [target performSelector:action withObject:nil];    }}@end#!objc@interface MyNSRunloop : NSObject{    NSMutableArray *timerQueue;}- (void)addTimer:(MyNSTimer*)t;- (void)executeOnce;@end@implementation MyNSRunloop- (void)addTimer:(MyNSTimer*)t;{    @synchronized(timerQueue){        [timerQueue addObject:t];    }}- (void)executeOnce;{    CFAbsoluteTime currentTime=CFAbsoluteTimeGetCurrent();    @synchronized(timerQueue){        for(MyNSTimer *t in timerQueue){            if(currentTime-t.lasttime>t.interval){                t.lasttime=currentTime;                [t invoke];            }        }    }}@end@interface MyNSThread : NSObject{    MyNSRunloop *runloop;}- (void)main:(id)sender;@end@implementation MyNSThread- (void)main:(id)sender{  while (TRUE) {    @autoreleasepool {      //do some jobs      //break in some condition      [runloop executeOnce];      usleep(10000);    }  }}@end

Here, we basically abstracted the Runloop structure. For example, I have a MyNSThread instance named myThread1. I can add required tasks to the thread of this instance, and the mynsunloop object in myThread1 manages these tasks.

MyNSTimer *timer1=[MyNSTimer scheduledTimerWithTimeInterval:1 target:obj1 selector:@selector(download1:)];[myThread1.runloop addTimer:timer1];MyNSTimer *timer2=[MyNSTimer scheduledTimerWithTimeInterval:2 target:obj2 selector:@selector(download2:)];[myThread1.runloop addTimer:timer2];
Run loop model

We know that in iOS, user experience is extremely important. For example, when UITableView slides smoothly, the main thread is responsible for page updates, but even if we add more NSTimer scheduled tasks to the main thread by default, that is, it does not affect the sliding of UITableView. How does the main thread achieve this? This is related to the run loop model.
Let's improve the Code:

@ Interface mynsunloopmode: NSObject {NSMutableArray * _ timerQueue; NSString * _ name;}-(void) addTimer :( MyNSTimer *) timer: NSObject {NSMutableSet * _ modes; mynsunloopmode * _ currentMode;}-(void) addTimer :( MyNSTimer *) t;-(void) addTimer :( MyNSTimer *) t forMode :( NSString *) mode;-(void) executeOnce; @ end // implementation file @ implementation mynsunloopmode-(void) executeOnce {CFAbsoluteTime currentTime = CFAbsoluteTimeGetCurrent (); @ synchronized (timerQueue) {for (MyNSTimer x t in timerQueue) {if (currentTime-t.lasttime> t. interval) {t. lasttime = currentTime; [t invoke] ;}}@ end @ implementation mynsunloop-(void) addTimer :( MyNSTimer *) timer {[self addTimer: timer forMode: @ NSDefaultRunLoopMode];}-(void) addTimer :( MyNSTimer *) timer forMode :( NSString *) modeName {mynsunloopmode * mode = nil; for (mode in _ modes) {if ([mode. name isEqualToString: modeName]) {break;} [mode addTimer: timer];}-(void) executeOnce {[_ currentMode executeOnce];} @ end

We added another class: mynsunloopmode, which put the execution task originally in the nsunloop into the object of this class. In contrast, nsunloop has a set of modes and currentMode. Runloop can only run in currentMode at any time, that is, it will only execute tasks in this mode. We can specify the mode of the current nsunloop:[NSRunLoop runMode:beforeDate:].
The system defines several modes, and each model has its own name. One of them is NSDefaultRunLoopMode. When we add a task to the run loop, we only need to specify the name of the model to add the task to the corresponding model.
I guess it's because nstablewill be added to NSDefaultRunLoopMode by default, but the main thread is not in this mode when UITableView slides (instead, it is switched to NSEventTrackingRunLoopMode ), therefore, NSTimer tasks will not be executed, and of course they will not have any impact on the slide. After sliding, the main thread switches to NSDefaultRunLoopMode, And the NSTimer task can be executed again. Of course, we can still add NSTimer to any mode:[NSRunLoop addTimer:forModel:].
How is this mode introduced!
  
This article introduces the basic principle of the run loop. The real situation of the runloop is naturally much more complicated, so it will never be different. If you are interested, you can also study its implementation.

 

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.