“This is the 21st day of my participation in the Gwen Challenge in November. See details: The Last Gwen Challenge in 2021”

About CADisplayLink

CADisplayLink is a timer used to synchronize the screen refresh rate

  • CADisplayLink is a timer that matches the refresh rate of the screen. After CADisplayLink registers with Runloop in a specific mode, the Runloop sends the specified selector message to CADisplayLink’s target every time the screen refreshes. The corresponding selector of the CADisplayLink class is called once. So typically, the screen refresh rate on iOS devices is 60 times per second

  • IOS devices refresh their screens at a fixed rate, and CADisplayLink is normally called at the end of each refresh with a high degree of accuracy. However, if the method called is time-consuming and exceeds the screen refresh cycle, several callback callbacks will be skipped

  • If the CPU is too busy to ensure a screen refresh rate of 60 beats/SEC, it will result in a number of missed calls to the callback method, depending on how busy the CPU is


CADisplayLink common methods and properties

  • Create method

    When you add the CADisplayLink object to the runloop, give it a target and select to call when the screen refreshes

    CADisplayLink *link = [CADisplayLink displayLinkWithTarget:self selector:@selector(run)];
    
    [link addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
    Copy the code
  • Stop methods

    When the invalidate operation is performed, the CADisplayLink object is removed from the runloop and the selector call stops, similar to the invalidate method of NSTimer

    [link invalidate];
    link = nil;
    Copy the code
  • Important attributes

    • timestamp

      Read-only property, which returns the timestamp of the last screen refresh. If the application of video playback, you can obtain the specific time of the previous frame through the timestamp, to calculate the next frame

    • duration

      Read-only property, which returns the time between frames, that is, the time between each screen refresh. Note that this property is not assigned until target’s selector is called for the first time. The interval between calls of selector is calculated as follows: Call interval = duration × frameInterval

    • frameInterval

      Readable and writable property, a value of type NSInteger that sets how many frames each time the selector method is called. The default value is 1, which is called every frame. If every frame is called once, on iOS devices the refresh rate is 60 Hz which is 60 times per second. If the frameInterval is set to 2 then the refresh rate is once every two frames which is 30 times per second

    • preferredFramesPerSecond

      Readable and writable property that sets the number of refreshes per second. The default value is the maximum screen frame rate, currently 60.

      The actual screen frame rate will differ somewhat from the Preferred Frame rate, resulting from the interaction between the set value and the screen’s maximum frame rate. The rules are as follows:

      If the maximum screen frame rate is 60, the actual frame rate can only be 15, 20, 30, or 60. If the value is greater than 60, the actual screen frame rate is 60. If the value is between 26 and 35, the actual frame rate is 30. If set to 0, the highest frame rate is used.

      Often used for operations that can be resolved by lowering the frame rate if an object cannot be provided within a particular frame rate


The use of CADisplayLink

Due to the synchronization with the screen refresh, it is very suitable for repeated UI drawing, such as: download progress bar, custom animation design, video rendering and so on

Here is a simple example

- (void)viewDidLoad {
    [super viewDidLoad];
    
    CADisplayLink *disLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(test)];
    [disLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    
    // Multiple calls per second defaults to 60.
    disLink.preferredFramesPerSecond = 10;
}
- (void)test{ 
    NSLog(@"Test");
}
Copy the code