Skip to content

Commit 947e71a

Browse files
Mehdi Mulanifacebook-github-bot
Mehdi Mulani
authored andcommitted
Add RCTWeakProxy to properly deallocate RCTUIImageViewAnimated
Summary: @public CADisplayLink strongly holds onto its target, so you have to use a weak proxy object to pass the target into the CADisplayLink. Previously we passed a weak-self point (i.e. weakSelf) but this did not have the intended effect, since the pointer to self would still be passed to CADisplayLink, and thus it would hold onto the RCTUIImageViewAnimated strongly. So is weakSelf doing anything other than using self? It is but it's very minor and not useful. In the case that the object got de-allocated between assigning self to weakSelf and creating the CADisplayLink, then we would pass a nil target. This is actually impossible though because we are running an instance method, so self is implicitly retained! So semantically it is something different but in practice it is the same as passing self through. Notes: * This system was added originally in #24822 * #25636 then "enabled" this system by deprecating existing approach Reviewed By: fkgozali Differential Revision: D16939869 fbshipit-source-id: 7a0e947896f23aa30ad074d1dcb4d4db7543e00a
1 parent d2213c7 commit 947e71a

File tree

4 files changed

+58
-2
lines changed

4 files changed

+58
-2
lines changed

Libraries/Image/RCTUIImageViewAnimated.h

+3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
*/
77

88
#import <React/RCTAnimatedImage.h>
9+
#import <React/RCTDefines.h>
10+
11+
RCT_EXTERN void RCTUIImageViewEnableWeakProxy(BOOL enabled);
912

1013
@interface RCTUIImageViewAnimated : UIImageView
1114

Libraries/Image/RCTUIImageViewAnimated.m

+9-2
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,16 @@
66
*/
77

88
#import <React/RCTUIImageViewAnimated.h>
9+
#import <React/RCTWeakProxy.h>
910

1011
#import <mach/mach.h>
1112
#import <objc/runtime.h>
1213

14+
static BOOL weakProxyEnabled = YES;
15+
void RCTUIImageViewEnableWeakProxy(BOOL enabled) {
16+
weakProxyEnabled = enabled;
17+
}
18+
1319
static NSUInteger RCTDeviceTotalMemory() {
1420
return (NSUInteger)[[NSProcessInfo processInfo] physicalMemory];
1521
}
@@ -146,8 +152,9 @@ - (NSOperationQueue *)fetchQueue
146152
- (CADisplayLink *)displayLink
147153
{
148154
if (!_displayLink) {
149-
__weak __typeof(self) weakSelf = self;
150-
_displayLink = [CADisplayLink displayLinkWithTarget:weakSelf selector:@selector(displayDidRefresh:)];
155+
__weak typeof(self) weakSelf = self;
156+
id target = weakProxyEnabled ? [RCTWeakProxy weakProxyWithTarget:self] : weakSelf;
157+
_displayLink = [CADisplayLink displayLinkWithTarget:target selector:@selector(displayDidRefresh:)];
151158
NSString *runLoopMode = [NSProcessInfo processInfo].activeProcessorCount > 1 ? NSRunLoopCommonModes : NSDefaultRunLoopMode;
152159
[_displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:runLoopMode];
153160
}

React/Base/RCTWeakProxy.h

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#import <Foundation/Foundation.h>
9+
10+
@interface RCTWeakProxy : NSObject
11+
12+
@property (nonatomic, weak, readonly) id target;
13+
14+
+ (instancetype)weakProxyWithTarget:(id)target;
15+
16+
@end

React/Base/RCTWeakProxy.m

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#import "RCTWeakProxy.h"
9+
10+
@implementation RCTWeakProxy
11+
12+
- (instancetype)initWithTarget:(id)target
13+
{
14+
if (self = [super init]) {
15+
_target = target;
16+
}
17+
return self;
18+
}
19+
20+
+ (instancetype)weakProxyWithTarget:(id)target
21+
{
22+
return [[RCTWeakProxy alloc] initWithTarget:target];
23+
}
24+
25+
- (id)forwardingTargetForSelector:(SEL)aSelector
26+
{
27+
return _target;
28+
}
29+
30+
@end

0 commit comments

Comments
 (0)