The GCD timer

/** dispatch_source_t timer (nonatomic, strong) */ @property (nonatomic, strong) dispatch_source_t timer; int count = 0; - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {// create a view of the scene dispatch_get_global_queue(0, 0); // dispatch_queue_t queue = dispatch_get_main_queue(); Self. timer = dispatch_source_create(dispatch_source_timer, 0, 0, dispatch_source_timer) queue); // Set various attributes of timer (when to start the task, how often to execute it) // GCD time parameter, Dispatch_time (DISPATCH_TIME_NOW, DISPATCH_TIME_NOW) 3.0 * NSEC_PER_SEC) dispatch_time_t start = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)); Uint64_t interval = (uint64_t)(1.0 * NSEC_PER_SEC); //NSEC_PER_SEC dispatch_source_set_timer(self.timer, start, interval, 0); / / set the callback dispatch_source_set_event_handler (self timer, ^ {NSLog (@ "-- -- -- -- -- -- -- -- -- -- - % @", [NSThread currentThread]); count++; // if (count == 4) {// // dispatch_cancel(self.timer); // self.timer = nil; / /}}); // Start timer dispatch_resume(self.timer); }Copy the code

NSTimer

- (void) timer timer = {NSTimer * [NSTimer timerWithTimeInterval: 2.0 target: self selector: @ the selector (run) the userInfo: nil repeats:YES]; // The timer only runs in NSDefaultRunLoopMode. Once the RunLoop enters another mode, The timer will not work / / [[NSRunLoop currentRunLoop] addTimer: timer forMode: NSDefaultRunLoopMode]; // Timer only runs in UITrackingRunLoopMode, once RunLoop enters another mode, The timer will not work / / [[NSRunLoop currentRunLoop] addTimer: timer forMode: UITrackingRunLoopMode]; // The timer will run in modes marked common modes: UITrackingRunLoopMode and NSDefaultRunLoopMode [[NSRunLoop currentRunLoop] addTimer: timer forMode: NSRunLoopCommonModes]; }Copy the code
- (void)timer2 {// scheduledTimer is automatically added to the current runLoop. And it is NSDefaultRunLoopMode NSTimer * timer = [NSTimer scheduledTimerWithTimeInterval: 2.0 target: self selector: @ the selector (run)  userInfo:nil repeats:YES]; / / modify model [[NSRunLoop currentRunLoop] addTimer: timer forMode: NSRunLoopCommonModes]; [[NSRunLoop currentRunLoop] run]; [NSRunLoop currentRunLoop] run]; }Copy the code
  • 02 Part 2 05Quartz2D 08 Snowflake Timer Animation timer
CADisplayLink *link = [CADisplayLink displayLinkWithTarget:self selector:@selector(timeChange)]; / / added to the main operating cycle [link addToRunLoop: [NSRunLoop mainRunLoop] forMode: NSDefaultRunLoopMode];Copy the code

ImageView display

- (void)useImageView {// Only display images in NSDefaultRunLoopMode (no lag) [self.imageView performSelector:@selector(setImage) WithObject: [UIImage imageNamed: @ "placeholder"] afterDelay: 3.0 inModes: @ [NSDefaultRunLoopMode]]. }Copy the code

PerformSelector

self performSelector:<#(nonnull SEL)#> withObject:<#(nullable id)#> afterDelay:<#(NSTimeInterval)#> inModes:<#(nonnull NSArray<NSRunLoopMode> *)#> // Only display images in NSDefaultRunLoopMode [self.imageView performSelector:@selector(setImage:) WithObject: [UIImage imageNamed: @ "placeholder"] afterDelay: 3.0 inModes: @ [NSDefaultRunLoopMode]].Copy the code

Permanent thread

  • Resident thread: the thread does not die: it often performs time-consuming operations in the background (child threads), such as: == Monitors user operations in the background ==
#import <Foundation/Foundation.h> @interface XMGThread : NSThread @end #import "XMGThread. H "@implementation XMGThread - (void)dealloc {  self); } @end /** Thread object */ @property (nonatomic, strong) XMGThread *thread; Self. thread = [[XMGThread alloc] initWithTarget:self selector:@selector(run) object:nil]; Self.thread. name = @" open resident thread "; [self.thread start]; / / want a thread to die to open runLoop open die threads in the thread - (void) run {NSLog (@ "-- -- -- -- -- -- -- -- -- -- run -- % @", [NSThread currentThread]); / / 1. Method 1 addPort [[NSRunLoop currentRunLoop] addPort: [NSPort port] forMode: NSDefaultRunLoopMode]; / / 2. The method 2 addTimer / / a new NSTimer object NSTimer * timer = [NSTimer timerWithTimeInterval: 5.0 target: self selector: @ the selector (show)  userInfo:nil repeats:YES]; // Add NSTimer to RunLoop and tell the system that Tiemr is currently valid only in the default mode of RunLoop [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode]; [[NSRunLoop currentRunLoop] run]; [NSRunLoop currentRunLoop] run]; // start runLoop NSLog(@"---------"); / / equivalent to / / [[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode beforeDate: [NSDate distantFuture]]. // [[NSRunLoop currentRunLoop] runUntilDate:[NSDate distantFuture]]; } /** * This method can save the name of the thread, But the threads will not be able to deal with other behaviors (events) * / / / - (void) run / / {/ / NSLog (@ "-- -- -- -- -- -- -- -- -- -- run -- % @", [NSThread currentThread]); // // while (1); // The current thread is always processing this line of code // // NSLog(@"---------"); (void) Touch Began:(NSSet *) View withEvent:(UIEvent *) View {[self performSelector:@selector(test)]  onThread:self.thread withObject:nil waitUntilDone:NO]; } / / wake up the child thread to do things in the child thread - (void) test {NSLog (@ "-- -- -- -- -- -- -- -- -- -- test -- % @", [NSThread currentThread]); }Copy the code

Automatic release tank

- (void) execute {@ autoreleasepool {[NSTimer scheduledTimerWithTimeInterval: 2.0 target: self selector: @ the selector (test) userInfo:nil repeats:YES]; [[NSRunLoop currentRunLoop] run]; }}Copy the code

RunLoop interview questions

  • What is runLoop?
    • It literally runs a loop
    • Inside is a do-while loop that continuously processes various events (such as source, timeer, observer)
    • Each thread has one RunLoop. The main thread RunLoop starts by default, and the child thread RunLoop starts manually
    • RunLoop can only start in one mode. If there is no source (source0, source1) or timer in the current mode, exit runLoop directly
  • How do you use runLoop in your development
    • Start a resident thread (to keep a child thread from dying, waiting for messages from other threads, and processing other events)
      • Start a timer in a child thread
      • Monitor some behavior over time in child threads
    • You can control the timer to run in a specific mode
    • You can make certain events (actions, tasks) run in a particular mode
    • You can add an Observer to listen for runLoop status, such as click status processing (doing something before clicking)
  • When is the automatic release pool released?
    • Released before the runLoop sleep ==kCFRunLoopAfterWaiting==
    • Observe the status of the RunLoop and release the automatic release pool (kCFRunLoopBeforeWaiting) as soon as the RunLoop is about to enter sleep wait.

Automatically release pools and runloops

  • kCFRunLoopEntry; // Create an automatic release pool
  • kCFRunLoopBeforeWaiting; // Destroy the auto release pool to create a new auto release pool
  • KCFRunLoopExit; // Destroy the automatic release pool