Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ios/REAModule.m
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ - (void)addOperationBlock:(AnimatedOperation)operation

- (void)uiManagerWillPerformMounting:(RCTUIManager *)uiManager
{
[_nodesManager maybeFlushUpdateBuffer];
if (_operations.count == 0) {
return;
}
Expand Down
2 changes: 2 additions & 0 deletions ios/REANodesManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,6 @@ typedef void (^REAEventHandler)(NSString *eventName, id<RCTEvent> event);

- (void)setValueForNodeID:(nonnull NSNumber *)nodeID value:(nonnull NSNumber *)newValue;

- (void)maybeFlushUpdateBuffer;

@end
71 changes: 71 additions & 0 deletions ios/REANodesManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#import <React/RCTConvert.h>

#import <React/RCTShadowView.h>
#import <stdatomic.h>
#import "Nodes/REAAlwaysNode.h"
#import "Nodes/REABezierNode.h"
#import "Nodes/REABlockNode.h"
Expand Down Expand Up @@ -46,6 +47,17 @@ - (void)runSyncUIUpdatesWithObserver:(id<RCTUIManagerObserver>)observer;

@end

@interface ComponentUpdate : NSObject

@property (nonnull) NSMutableDictionary *props;
@property (nonnull) NSNumber *viewTag;
@property (nonnull) NSString *viewName;

@end

@implementation ComponentUpdate
@end

@implementation RCTUIManager (SyncUpdates)

- (BOOL)hasEnqueuedUICommands
Expand Down Expand Up @@ -99,6 +111,9 @@ @implementation REANodesManager {
BOOL _tryRunBatchUpdatesSynchronously;
REAEventHandler _eventHandler;
volatile void (^_mounting)(void);
NSMutableDictionary<NSNumber *, ComponentUpdate *> *_componentUpdateBuffer;
volatile atomic_bool _shouldFlushUpdateBuffer;
NSMutableDictionary<NSNumber *, UIView *> *_viewRegistry;
}

- (instancetype)initWithModule:(REAModule *)reanimatedModule uiManager:(RCTUIManager *)uiManager
Expand All @@ -113,6 +128,9 @@ - (instancetype)initWithModule:(REAModule *)reanimatedModule uiManager:(RCTUIMan
_wantRunUpdates = NO;
_onAnimationCallbacks = [NSMutableArray new];
_operationsInBatch = [NSMutableArray new];
_componentUpdateBuffer = [NSMutableDictionary new];
_viewRegistry = [_uiManager valueForKey:@"_viewRegistry"];
_shouldFlushUpdateBuffer = false;
}

_displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(onAnimationFrame:)];
Expand Down Expand Up @@ -492,6 +510,11 @@ - (void)configureProps:(NSSet<NSString *> *)nativeProps uiProps:(NSSet<NSString
_nativeProps = nativeProps;
}

- (BOOL)isNotNativeViewFullyMounted:(NSNumber *)viewTag
{
return _viewRegistry[viewTag].superview == nil;
}

- (void)setValueForNodeID:(nonnull NSNumber *)nodeID value:(nonnull NSNumber *)newValue
{
RCTAssertParam(nodeID);
Expand All @@ -506,6 +529,24 @@ - (void)updateProps:(nonnull NSDictionary *)props
ofViewWithTag:(nonnull NSNumber *)viewTag
withName:(nonnull NSString *)viewName
{
ComponentUpdate *lastSnapshot = _componentUpdateBuffer[viewTag];
if ([self isNotNativeViewFullyMounted:viewTag] || lastSnapshot != nil) {
if (lastSnapshot == nil) {
ComponentUpdate *propsSnapshot = [ComponentUpdate new];
propsSnapshot.props = [props mutableCopy];
propsSnapshot.viewTag = viewTag;
propsSnapshot.viewName = viewName;
_componentUpdateBuffer[viewTag] = propsSnapshot;
atomic_store(&_shouldFlushUpdateBuffer, true);
} else {
NSMutableDictionary *lastProps = lastSnapshot.props;
for (NSString *key in props) {
[lastProps setValue:props[key] forKey:key];
}
}
return;
}

// TODO: refactor PropsNode to also use this function
NSMutableDictionary *uiProps = [NSMutableDictionary new];
NSMutableDictionary *nativeProps = [NSMutableDictionary new];
Expand Down Expand Up @@ -553,4 +594,34 @@ - (NSString *)obtainProp:(nonnull NSNumber *)viewTag propName:(nonnull NSString
return result;
}

- (void)maybeFlushUpdateBuffer
{
RCTAssertUIManagerQueue();
bool shouldFlushUpdateBuffer = atomic_load(&_shouldFlushUpdateBuffer);
if (!shouldFlushUpdateBuffer) {
return;
}

__weak typeof(self) weakSelf = self;
[_uiManager addUIBlock:^(__unused RCTUIManager *manager, __unused NSDictionary<NSNumber *, UIView *> *viewRegistry) {
__typeof__(self) strongSelf = weakSelf;
if (strongSelf == nil) {
return;
}
atomic_store(&strongSelf->_shouldFlushUpdateBuffer, false);
NSMutableDictionary *componentUpdateBuffer = [strongSelf->_componentUpdateBuffer copy];
strongSelf->_componentUpdateBuffer = [NSMutableDictionary new];
for (NSNumber *tag in componentUpdateBuffer) {
ComponentUpdate *componentUpdate = componentUpdateBuffer[tag];
if (componentUpdate == Nil) {
continue;
}
[strongSelf updateProps:componentUpdate.props
ofViewWithTag:componentUpdate.viewTag
withName:componentUpdate.viewName];
}
[strongSelf performOperations];
}];
}

@end