From 73c7e267a99376d175c7fb297617f00ce9f44bfe Mon Sep 17 00:00:00 2001 From: Kevin Hardman Date: Fri, 3 Jan 2025 13:37:04 -0500 Subject: [PATCH] Add autoreleasepool to DisplayLinkCallback to release objects --- SDWebImage/Private/SDDisplayLink.m | 32 ++++++++++++++++-------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/SDWebImage/Private/SDDisplayLink.m b/SDWebImage/Private/SDDisplayLink.m index f595f79a..aeae570d 100644 --- a/SDWebImage/Private/SDDisplayLink.m +++ b/SDWebImage/Private/SDDisplayLink.m @@ -269,22 +269,24 @@ static BOOL kSDDisplayLinkUseTargetTimestamp = NO; // Use `next` fire time, or ` #if SD_MAC static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp *inNow, const CVTimeStamp *inOutputTime, CVOptionFlags flagsIn, CVOptionFlags *flagsOut, void *displayLinkContext) { - // CVDisplayLink callback is not on main queue - // Actually `SDWeakProxy` but not `SDDisplayLink` - SDDisplayLink *object = (__bridge SDDisplayLink *)displayLinkContext; - if (!object) return kCVReturnSuccess; - // CVDisplayLink does not use runloop, but we can provide similar behavior for modes - // May use `default` runloop to avoid extra callback when in `eventTracking` (mouse drag, scroll) or `modalPanel` (modal panel) - NSString *runloopMode = object.runloopMode; - if (![runloopMode isEqualToString:NSRunLoopCommonModes] && ![runloopMode isEqualToString:NSRunLoop.mainRunLoop.currentMode]) { + @autoreleasepool { + // CVDisplayLink callback is not on main queue + // Actually `SDWeakProxy` but not `SDDisplayLink` + SDDisplayLink *object = (__bridge SDDisplayLink *)displayLinkContext; + if (!object) return kCVReturnSuccess; + // CVDisplayLink does not use runloop, but we can provide similar behavior for modes + // May use `default` runloop to avoid extra callback when in `eventTracking` (mouse drag, scroll) or `modalPanel` (modal panel) + NSString *runloopMode = object.runloopMode; + if (![runloopMode isEqualToString:NSRunLoopCommonModes] && ![runloopMode isEqualToString:NSRunLoop.mainRunLoop.currentMode]) { + return kCVReturnSuccess; + } + CVTimeStamp outputTime = inOutputTime ? *inOutputTime : *inNow; + // `SDWeakProxy` is weak, so it's safe to dispatch to main queue without leak + dispatch_async(dispatch_get_main_queue(), ^{ + object.outputTime = outputTime; + [object displayLinkDidRefresh:(__bridge id)(displayLink)]; + }); return kCVReturnSuccess; } - CVTimeStamp outputTime = inOutputTime ? *inOutputTime : *inNow; - // `SDWeakProxy` is weak, so it's safe to dispatch to main queue without leak - dispatch_async(dispatch_get_main_queue(), ^{ - object.outputTime = outputTime; - [object displayLinkDidRefresh:(__bridge id)(displayLink)]; - }); - return kCVReturnSuccess; } #endif