mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
8933724d7d
Summary: Fix a issue that RCTModalHostView can't be dismissed while being presented Steps To Reproduce A native modal presented view controller is being dismissed before the first screen shows. A RCTModalHostView is presented when the first screen shows. The RCTModalHostView will be dismissed after an asynchronous callback. If the callback was called before the completion of the presenting animation, the RCTModalHostView will not be dismissed. ## Changelog [iOS] [Fixed] - Fix that RCTModalHostView can't be dismissed while being presented Pull Request resolved: https://github.com/facebook/react-native/pull/29745 Reviewed By: shergin Differential Revision: D23566487 Pulled By: sammy-SC fbshipit-source-id: bd95f200b79fa75e2387e402091d58c0f538759c
140 lines
4.1 KiB
Objective-C
140 lines
4.1 KiB
Objective-C
/*
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*/
|
|
|
|
#import "RCTModalHostViewManager.h"
|
|
|
|
#import "RCTBridge.h"
|
|
#import "RCTModalHostView.h"
|
|
#import "RCTModalHostViewController.h"
|
|
#import "RCTShadowView.h"
|
|
#import "RCTUtils.h"
|
|
|
|
@implementation RCTConvert (RCTModalHostView)
|
|
|
|
RCT_ENUM_CONVERTER(
|
|
UIModalPresentationStyle,
|
|
(@{
|
|
@"fullScreen" : @(UIModalPresentationFullScreen),
|
|
#if !TARGET_OS_TV
|
|
@"pageSheet" : @(UIModalPresentationPageSheet),
|
|
@"formSheet" : @(UIModalPresentationFormSheet),
|
|
#endif
|
|
@"overFullScreen" : @(UIModalPresentationOverFullScreen),
|
|
}),
|
|
UIModalPresentationFullScreen,
|
|
integerValue)
|
|
|
|
@end
|
|
|
|
@interface RCTModalHostShadowView : RCTShadowView
|
|
|
|
@end
|
|
|
|
@implementation RCTModalHostShadowView
|
|
|
|
- (void)insertReactSubview:(id<RCTComponent>)subview atIndex:(NSInteger)atIndex
|
|
{
|
|
[super insertReactSubview:subview atIndex:atIndex];
|
|
if ([subview isKindOfClass:[RCTShadowView class]]) {
|
|
((RCTShadowView *)subview).size = RCTScreenSize();
|
|
}
|
|
}
|
|
|
|
@end
|
|
|
|
@interface RCTModalHostViewManager () <RCTModalHostViewInteractor>
|
|
|
|
@property (nonatomic, copy) dispatch_block_t dismissWaitingBlock;
|
|
|
|
@end
|
|
|
|
@implementation RCTModalHostViewManager {
|
|
NSPointerArray *_hostViews;
|
|
}
|
|
|
|
RCT_EXPORT_MODULE()
|
|
|
|
- (UIView *)view
|
|
{
|
|
RCTModalHostView *view = [[RCTModalHostView alloc] initWithBridge:self.bridge];
|
|
view.delegate = self;
|
|
if (!_hostViews) {
|
|
_hostViews = [NSPointerArray weakObjectsPointerArray];
|
|
}
|
|
[_hostViews addPointer:(__bridge void *)view];
|
|
return view;
|
|
}
|
|
|
|
- (void)presentModalHostView:(RCTModalHostView *)modalHostView
|
|
withViewController:(RCTModalHostViewController *)viewController
|
|
animated:(BOOL)animated
|
|
{
|
|
dispatch_block_t completionBlock = ^{
|
|
if (modalHostView.onShow) {
|
|
modalHostView.onShow(nil);
|
|
}
|
|
};
|
|
if (_presentationBlock) {
|
|
_presentationBlock([modalHostView reactViewController], viewController, animated, completionBlock);
|
|
} else {
|
|
__weak typeof(self) weakself = self;
|
|
[[modalHostView reactViewController] presentViewController:viewController
|
|
animated:animated
|
|
completion:^{
|
|
!completionBlock ?: completionBlock();
|
|
__strong typeof(weakself) strongself = weakself;
|
|
!strongself.dismissWaitingBlock
|
|
?: strongself.dismissWaitingBlock();
|
|
strongself.dismissWaitingBlock = nil;
|
|
}];
|
|
}
|
|
}
|
|
|
|
- (void)dismissModalHostView:(RCTModalHostView *)modalHostView
|
|
withViewController:(RCTModalHostViewController *)viewController
|
|
animated:(BOOL)animated
|
|
{
|
|
if (_dismissalBlock) {
|
|
_dismissalBlock([modalHostView reactViewController], viewController, animated, nil);
|
|
} else {
|
|
self.dismissWaitingBlock = ^{
|
|
[viewController.presentingViewController dismissViewControllerAnimated:animated completion:nil];
|
|
};
|
|
if (viewController.presentingViewController) {
|
|
self.dismissWaitingBlock();
|
|
self.dismissWaitingBlock = nil;
|
|
}
|
|
}
|
|
}
|
|
|
|
- (RCTShadowView *)shadowView
|
|
{
|
|
return [RCTModalHostShadowView new];
|
|
}
|
|
|
|
- (void)invalidate
|
|
{
|
|
for (RCTModalHostView *hostView in _hostViews) {
|
|
[hostView invalidate];
|
|
}
|
|
_hostViews = nil;
|
|
}
|
|
|
|
RCT_EXPORT_VIEW_PROPERTY(animationType, NSString)
|
|
RCT_EXPORT_VIEW_PROPERTY(presentationStyle, UIModalPresentationStyle)
|
|
RCT_EXPORT_VIEW_PROPERTY(transparent, BOOL)
|
|
RCT_EXPORT_VIEW_PROPERTY(onShow, RCTDirectEventBlock)
|
|
RCT_EXPORT_VIEW_PROPERTY(identifier, NSNumber)
|
|
RCT_EXPORT_VIEW_PROPERTY(supportedOrientations, NSArray)
|
|
RCT_EXPORT_VIEW_PROPERTY(onOrientationChange, RCTDirectEventBlock)
|
|
|
|
#if TARGET_OS_TV
|
|
RCT_EXPORT_VIEW_PROPERTY(onRequestClose, RCTDirectEventBlock)
|
|
#endif
|
|
|
|
@end
|