Repository: SDWebImage/SDWebImage
File: SDWebImage/SDAnimatedImageView.m (Objective-C)

Code before:
        if (!self.isProgressive) {
            self.currentFrame = image;
            SD_LOCK(self.lock);
            self.frameBuffer[@(self.currentFrameIndex)] = self.currentFrame;
            SD_UNLOCK(self.lock);
        }
        
        // Ensure disabled highlighting; it's not supported (see `-setHighlighted:`).
        super.highlighted = NO;
        
        // Calculate max buffer size
        [self calculateMaxBufferCount];
        // Update should animate
        [self updateShouldAnimate];
        if (self.shouldAnimate) {
            [self startAnimating];
        }
        
        [self.layer setNeedsDisplay];
#if SD_MAC
        [self.layer displayIfNeeded]; // macOS's imageViewLayer may not equal to self.layer. But `[super setImage:]` will impliedly mark it needsDisplay. We call `[self.layer displayIfNeeded]` to immediately refresh the imageViewLayer to avoid flashing
#endif
    }
}

#if SD_UIKIT
- (void)setRunLoopMode:(NSRunLoopMode)runLoopMode
{
    if ([_runLoopMode isEqualToString:runLoopMode]) {
        return;
    }
    if (_displayLink) {
        if (_runLoopMode) {
            [_displayLink removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:_runLoopMode];
        }
        if (runLoopMode) {
            [_displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:runLoopMode];
        }
    }
    _runLoopMode = [runLoopMode copy];
}

- (NSRunLoopMode)runLoopMode
{
    if (!_runLoopMode) {
        _runLoopMode = [[self class] defaultRunLoopMode];
    }
    return _runLoopMode;
}
#endif


Review comment (suggestion):
There logic, seems does not handle the case, when user change `runLoopMode` after animation started. Seems we can do better. Like YYImage.

Code after:
        // Get the scale
        self.animatedImageScale = image.scale;
        if (!self.isProgressive) {
            self.currentFrame = image;
            SD_LOCK(self.lock);
            self.frameBuffer[@(self.currentFrameIndex)] = self.currentFrame;
            SD_UNLOCK(self.lock);
        }
        
        // Ensure disabled highlighting; it's not supported (see `-setHighlighted:`).
        super.highlighted = NO;
        
        // Calculate max buffer size
        [self calculateMaxBufferCount];
        // Update should animate
        [self updateShouldAnimate];
        if (self.shouldAnimate) {
            [self startAnimating];
        }
        
        [self.layer setNeedsDisplay];
#if SD_MAC
        [self.layer displayIfNeeded]; // macOS's imageViewLayer may not equal to self.layer. But `[super setImage:]` will impliedly mark it needsDisplay. We call `[self.layer displayIfNeeded]` to immediately refresh the imageViewLayer to avoid flashing
#endif
    }
}

#if SD_UIKIT
- (void)setRunLoopMode:(NSRunLoopMode)runLoopMode
{
    if ([_runLoopMode isEqual:runLoopMode]) {
        return;
    }
    if (_displayLink) {
        if (_runLoopMode) {
            [_displayLink removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:_runLoopMode];
        }
        if (runLoopMode.length > 0) {
            [_displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:runLoopMode];
        }
    }
    _runLoopMode = [runLoopMode copy];
}

- (NSRunLoopMode)runLoopMode
{
    if (!_runLoopMode) {
        _runLoopMode = [[self class] defaultRunLoopMode];
    }
    return _runLoopMode;
}