1. nsunloop
In cocoa, each thread (nsthread) object contains a run loop (nsunloop) object to process input events cyclically. The processed events include two types:
Asynchronous events of sources. One is a synchronization event from timer sources;
Run loop generates notifications when processing input events. You can use core Foundation to add run-loop observers to the thread to listen for specific events, to perform additional processing when a monitored event occurs.
Each run loop can run in different modes. A run loop mode is a set that contains several input event sources, timers, and the run loop observers to be notified when an event occurs. The run loop running in one mode only processes the Input Source events, Timer events, and observers contained in its run loop mode.
The predefined modes in cocoa include:
- Default Mode
Definition: nsdefaultrunloopmode (cocoa) kcfrunloopdefaultmode (Core
Foundation)
Description: The default mode contains almost all input sources (except nsconnection). This mode is generally used.
- Connection Mode
Definition: nsconnectionreplymode (cocoa)
Description: handles nsconnection object-related events, which are used inside the system and are rarely used by users.
- Modal Mode
Definition: nsmodalpanelrunloopmode (cocoa)
Description: used to process the modal panels event.
- Event tracking mode
Definition: uitrackingrunloopmode (IOS) nseventtrackingrunloopmode (cocoa)
Description: This mode is used when loop or other user interface tracking loops is dragged. In this mode, the processing of input events is restricted. For example, if you hold down the uitableview and drag it with your finger, it will be in this mode.
- Common Mode
Definition: nsunloopcommonmodes (cocoa) kcfrunloopcommonmodes (Core
Foundation)
Description: This is a pseudo mode. It is a set of run loop modes. Adding an input source to this mode means that all modes included in common modes can be processed. In the cocoa application, the common modes contains default modes, modal modes, and event tracking modes by default. You can use the cfrunloopaddcommonmode method to think of common
Add custom modes to modes.
Obtains the run loop mode of the current thread.
NSString* runLoopMode = [[NSRunLoop currentRunLoop] currentMode];
2. nstimer, nsurlconnection, and uitrackingrunloopmode
By default, nstableand nsurlconnection run in the default mode. When the user is dragging the uitableview to the uitrackingrunloopmode mode, nstablecannot be fire, and nsurlconnection data cannot be processed.
Nstimer example:
Enable a 0.2s cycle timer in a uitableviewcontroller, update a counter when the timer expires, and display it on the label.
-(void)viewDidLoad{ label =[[[UILabel alloc]initWithFrame:CGRectMake(10, 100, 100, 50)]autorelease]; [self.view addSubview:label]; count = 0; NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval: 1 target: self selector: @selector(incrementCounter:) userInfo: nil repeats: YES];}- (void)incrementCounter:(NSTimer *)theTimer{ count++; label.text = [NSString stringWithFormat:@"%d",count];}
Under normal circumstances, you can see the number + 1 displayed on the label every 0.2 s, but when you drag or hold down tableview, the number on the label will not be updated, when your finger leaves, the number on the label is updated. When you drag the uitableview, the current thread run loop is in the uieventtrackingrunloopmode mode. In this mode, if you do not process the timer event, the timer cannot fire, and the number on the label cannot be updated.
Solution: One method is to process timer events in another thread. You can add timer to nsoperation to schedule tasks in another thread; another method is to modify the run loop mode of timer and add it to the uitrackingrunloopmode mode or the nsunloopcommonmodes mode.
That is
[[NSRunLoop currentRunLoop] addTimer:timer forMode:UITrackingRunLoopMode];
Or
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
The same is true for nsurlconnection. For details, see the description in sdwebimage and the implementation in sdwebimagedownloader. m code. To modify the running mode of nsurlconnection, use scheduleinrunloop: formode: method.
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:15]; NSURLConnection *connection = [[[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO]autorelease];[connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];[connection start];
Refer:
Threading programming guide-run
Loops
Nsunloop class reference
Nsurlconnection class reference
Nstimer class reference
Cfrunloop Wiki
Sdwebimage
Testbuttondown
Nstimerdoesntrunwhenmenuclicked