Skip to content

implement SchedulerDelegateProxy::schedulerShouldSynchronouslyUpdateViewOnUIThread #51334

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ NS_ASSUME_NONNULL_BEGIN
forShadowView:(const facebook::react::ShadowView &)shadowView;

- (void)synchronouslyUpdateViewOnUIThread:(ReactTag)reactTag
changedProps:(NSDictionary *)props
changedProps:(folly::dynamic)props
componentDescriptor:(const facebook::react::ComponentDescriptor &)componentDescriptor;
@end

Expand Down
19 changes: 14 additions & 5 deletions packages/react-native/React/Fabric/Mounting/RCTMountingManager.mm
Original file line number Diff line number Diff line change
Expand Up @@ -282,25 +282,34 @@ - (void)setIsJSResponder:(BOOL)isJSResponder
}

- (void)synchronouslyUpdateViewOnUIThread:(ReactTag)reactTag
changedProps:(NSDictionary *)props
changedProps:(folly::dynamic)props
componentDescriptor:(const ComponentDescriptor &)componentDescriptor
{
RCTAssertMainQueue();
NSArray<NSString *> *propsKeysToBeUpdated = extractKeysFromFollyDynamic(props);
bool updatesTransform = props.find("transform") != props.items().end();
bool updatesOpacity = props.find("opacity") != props.items().end();

UIView<RCTComponentViewProtocol> *componentView = [_componentViewRegistry findComponentViewWithTag:reactTag];
if (!componentView) {
RCTLogWarn(@"Attempted to update view with tag %ld, but it no longer exists", (long)reactTag);
return;
}

SurfaceId surfaceId = RCTSurfaceIdForView(componentView);
Props::Shared oldProps = [componentView props];
Props::Shared newProps = componentDescriptor.cloneProps(
PropsParserContext{surfaceId, *_contextContainer.get()}, oldProps, RawProps(convertIdToFollyDynamic(props)));
PropsParserContext{surfaceId, *_contextContainer.get()}, oldProps, RawProps(std::move(props)));

NSSet<NSString *> *propKeys = componentView.propKeysManagedByAnimated_DO_NOT_USE_THIS_IS_BROKEN ?: [NSSet new];
propKeys = [propKeys setByAddingObjectsFromArray:props.allKeys];
propKeys = [propKeys setByAddingObjectsFromArray:propsKeysToBeUpdated];
componentView.propKeysManagedByAnimated_DO_NOT_USE_THIS_IS_BROKEN = nil;
[componentView updateProps:newProps oldProps:oldProps];
componentView.propKeysManagedByAnimated_DO_NOT_USE_THIS_IS_BROKEN = propKeys;

const auto &newViewProps = static_cast<const ViewProps &>(*newProps);

if (props[@"transform"]) {
if (updatesTransform) {
auto layoutMetrics = LayoutMetrics();
layoutMetrics.frame.size.width = componentView.layer.bounds.size.width;
layoutMetrics.frame.size.height = componentView.layer.bounds.size.height;
Expand All @@ -309,7 +318,7 @@ - (void)synchronouslyUpdateViewOnUIThread:(ReactTag)reactTag
componentView.layer.transform = newTransform;
}
}
if (props[@"opacity"] && componentView.layer.opacity != (float)newViewProps.opacity) {
if (updatesOpacity && componentView.layer.opacity != (float)newViewProps.opacity) {
componentView.layer.opacity = newViewProps.opacity;
}

Expand Down
1 change: 1 addition & 0 deletions packages/react-native/React/Fabric/RCTScheduler.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ NS_ASSUME_NONNULL_BEGIN
blockNativeResponder:(BOOL)blockNativeResponder
forShadowView:(const facebook::react::ShadowView &)shadowView;

- (void)schedulerDidSynchronouslyUpdateViewOnUIThread:(facebook::react::Tag)reactTag props:(folly::dynamic)props;
@end

/**
Expand Down
4 changes: 2 additions & 2 deletions packages/react-native/React/Fabric/RCTScheduler.mm
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ void schedulerDidSendAccessibilityEvent(const ShadowView &shadowView, const std:

void schedulerShouldSynchronouslyUpdateViewOnUIThread(facebook::react::Tag tag, const folly::dynamic &props) override
{
// Does nothing.
// This delegate method is not currently used on iOS.
RCTScheduler *scheduler = (__bridge RCTScheduler *)scheduler_;
[scheduler.delegate schedulerDidSynchronouslyUpdateViewOnUIThread:tag props:props];
}

private:
Expand Down
3 changes: 2 additions & 1 deletion packages/react-native/React/Fabric/RCTSurfacePresenter.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ NS_ASSUME_NONNULL_BEGIN

- (nullable RCTFabricSurface *)surfaceForRootTag:(ReactTag)rootTag;

- (BOOL)synchronouslyUpdateViewOnUIThread:(NSNumber *)reactTag props:(NSDictionary *)props;
- (void)synchronouslyUpdateViewOnUIThread:(NSNumber *)reactTag props:(NSDictionary *)props;
- (void)schedulerDidSynchronouslyUpdateViewOnUIThread:(ReactTag)tag props:(folly::dynamic)props;

- (void)setupAnimationDriverWithSurfaceHandler:(const facebook::react::SurfaceHandler &)surfaceHandler;

Expand Down
20 changes: 13 additions & 7 deletions packages/react-native/React/Fabric/RCTSurfacePresenter.mm
Original file line number Diff line number Diff line change
Expand Up @@ -148,28 +148,34 @@ - (UIView *)findComponentViewWithTag_DO_NOT_USE_DEPRECATED:(NSInteger)tag
return componentView;
}

- (BOOL)synchronouslyUpdateViewOnUIThread:(NSNumber *)reactTag props:(NSDictionary *)props
- (void)synchronouslyUpdateViewOnUIThread:(NSNumber *)reactTag props:(NSDictionary *)props
{
ReactTag tag = [reactTag integerValue];
[self schedulerDidSynchronouslyUpdateViewOnUIThread:tag props:convertIdToFollyDynamic(props)];
}

- (void)schedulerDidSynchronouslyUpdateViewOnUIThread:(ReactTag)tag props:(folly::dynamic)props
{
RCTScheduler *scheduler = [self scheduler];
if (!scheduler) {
return NO;
return;
}

ReactTag tag = [reactTag integerValue];
UIView<RCTComponentViewProtocol> *componentView =
[_mountingManager.componentViewRegistry findComponentViewWithTag:tag];
if (componentView == nil) {
return NO; // This view probably isn't managed by Fabric
return; // This view probably isn't managed by Fabric
}
ComponentHandle handle = [[componentView class] componentDescriptorProvider].handle;
auto *componentDescriptor = [scheduler findComponentDescriptorByHandle_DO_NOT_USE_THIS_IS_BROKEN:handle];

if (!componentDescriptor) {
return YES;
return;
}

[_mountingManager synchronouslyUpdateViewOnUIThread:tag changedProps:props componentDescriptor:*componentDescriptor];
return YES;
[_mountingManager synchronouslyUpdateViewOnUIThread:tag
changedProps:std::move(props)
componentDescriptor:*componentDescriptor];
}

- (void)setupAnimationDriverWithSurfaceHandler:(const facebook::react::SurfaceHandler &)surfaceHandler
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ NS_ASSUME_NONNULL_BEGIN
- (id<RCTSurfaceProtocol>)createFabricSurfaceForModuleName:(NSString *)moduleName
initialProperties:(NSDictionary *)initialProperties;
- (nullable UIView *)findComponentViewWithTag_DO_NOT_USE_DEPRECATED:(NSInteger)tag;
- (BOOL)synchronouslyUpdateViewOnUIThread:(NSNumber *)reactTag props:(NSDictionary *)props;
- (void)synchronouslyUpdateViewOnUIThread:(NSNumber *)reactTag props:(NSDictionary *)props;
- (void)addObserver:(id<RCTSurfacePresenterObserver>)observer;
- (void)removeObserver:(id<RCTSurfacePresenterObserver>)observer;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
namespace facebook::react {

folly::dynamic convertIdToFollyDynamic(id json);
id convertFollyDynamicToId(const folly::dynamic& dyn);
id convertFollyDynamicToId(const folly::dynamic &dyn);
NSArray<NSString *> *extractKeysFromFollyDynamic(const folly::dynamic &dyn);

} // namespace facebook::react
Original file line number Diff line number Diff line change
Expand Up @@ -113,4 +113,20 @@ id convertFollyDynamicToId(const folly::dynamic &dyn)
return nil;
}

NSArray<NSString *> *extractKeysFromFollyDynamic(const folly::dynamic &dyn)
{
NSMutableArray<NSString *> *result = [NSMutableArray new];

if (dyn.type() == folly::dynamic::OBJECT) {
for (const auto &elem : dyn.items()) {
NSString *key = [[NSString alloc] initWithBytes:elem.first.c_str()
length:elem.first.size()
encoding:NSUTF8StringEncoding];
[result addObject:key];
}
}

return result;
}

} // namespace facebook::react
Loading