mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-03-26 09:14:22 +08:00
Fix appear/disappear events for ScreenContainer and address memo… (#354)
This chnage fixes the way we'd managed parent<>child VC relation. With this change in we hook child VC to parent in didMoveToWindow to match Stack behavior. We also wait with updating child view frame untill the child screen is attached. Finally we utilize RCTInvalidating interface to spot moments when screen controller is unmounted from react such that we can break reference cycle between screen and screen view (we don't do it in invalidate directly as sometimes we need to wait till transition end).
This commit is contained in:
committed by
GitHub
parent
f2caf02d8c
commit
b29e634e26
@@ -8,7 +8,13 @@
|
||||
#import <React/RCTShadowView.h>
|
||||
#import <React/RCTTouchHandler.h>
|
||||
|
||||
@interface RNSScreenView () <UIAdaptivePresentationControllerDelegate>
|
||||
@interface RNSScreen ()
|
||||
|
||||
- (void)invalidate;
|
||||
|
||||
@end
|
||||
|
||||
@interface RNSScreenView () <UIAdaptivePresentationControllerDelegate, RCTInvalidating>
|
||||
@end
|
||||
|
||||
@implementation RNSScreenView {
|
||||
@@ -231,18 +237,24 @@
|
||||
}
|
||||
}
|
||||
|
||||
- (void)invalidate
|
||||
{
|
||||
[_controller invalidate];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation RNSScreen {
|
||||
__weak UIView *_view;
|
||||
__weak id _previousFirstResponder;
|
||||
CGRect _lastViewFrame;
|
||||
BOOL disappeared;
|
||||
BOOL invalidated;
|
||||
}
|
||||
|
||||
- (instancetype)initWithView:(UIView *)view
|
||||
{
|
||||
if (self = [super init]) {
|
||||
_view = view;
|
||||
self.view = view;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@@ -289,12 +301,23 @@
|
||||
// screen dismissed, send event
|
||||
[((RNSScreenView *)self.view) notifyDismissed];
|
||||
}
|
||||
_view = self.view;
|
||||
self.view = nil;
|
||||
disappeared = YES;
|
||||
if (invalidated) {
|
||||
self.view = nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)invalidate
|
||||
{
|
||||
if (disappeared) {
|
||||
self.view = nil;
|
||||
}
|
||||
invalidated = YES;
|
||||
}
|
||||
|
||||
- (void)viewDidAppear:(BOOL)animated
|
||||
{
|
||||
disappeared = NO;
|
||||
[super viewDidAppear:animated];
|
||||
[((RNSScreenView *)self.view) notifyAppear];
|
||||
}
|
||||
@@ -305,14 +328,6 @@
|
||||
_previousFirstResponder = nil;
|
||||
}
|
||||
|
||||
- (void)loadView
|
||||
{
|
||||
if (_view != nil) {
|
||||
self.view = _view;
|
||||
_view = nil;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation RNSScreenManager
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
@end
|
||||
|
||||
@interface RNSScreenContainerView ()
|
||||
@interface RNSScreenContainerView () <RCTInvalidating>
|
||||
|
||||
@property (nonatomic, retain) UIViewController *controller;
|
||||
@property (nonatomic, retain) NSMutableSet<RNSScreenView *> *activeScreens;
|
||||
@@ -54,7 +54,6 @@
|
||||
{
|
||||
subview.reactSuperview = self;
|
||||
[_reactSubviews insertObject:subview atIndex:atIndex];
|
||||
subview.frame = CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height);
|
||||
}
|
||||
|
||||
- (void)removeReactSubview:(RNSScreenView *)subview
|
||||
@@ -68,6 +67,11 @@
|
||||
return _reactSubviews;
|
||||
}
|
||||
|
||||
- (UIViewController *)reactViewController
|
||||
{
|
||||
return _controller;
|
||||
}
|
||||
|
||||
- (void)detachScreen:(RNSScreenView *)screen
|
||||
{
|
||||
[screen.controller willMoveToParentViewController:nil];
|
||||
@@ -79,6 +83,7 @@
|
||||
- (void)attachScreen:(RNSScreenView *)screen
|
||||
{
|
||||
[_controller addChildViewController:screen.controller];
|
||||
screen.controller.view.frame = CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height);
|
||||
[_controller.view addSubview:screen.controller.view];
|
||||
[screen.controller didMoveToParentViewController:_controller];
|
||||
[_activeScreens addObject:screen];
|
||||
@@ -155,10 +160,22 @@
|
||||
[self markChildUpdated];
|
||||
}
|
||||
|
||||
- (void)didMoveToWindow
|
||||
{
|
||||
if (self.window) {
|
||||
[self reactAddControllerToClosestParent:_controller];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)invalidate
|
||||
{
|
||||
[_controller willMoveToParentViewController:nil];
|
||||
[_controller removeFromParentViewController];
|
||||
}
|
||||
|
||||
- (void)layoutSubviews
|
||||
{
|
||||
[super layoutSubviews];
|
||||
[self reactAddControllerToClosestParent:_controller];
|
||||
_controller.view.frame = self.bounds;
|
||||
for (RNSScreenView *subview in _reactSubviews) {
|
||||
subview.frame = CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height);
|
||||
|
||||
Reference in New Issue
Block a user