Skip to content

Commit

Permalink
Fix appear/disappear events for ScreenContainer and address memo… (#354)
Browse files Browse the repository at this point in the history
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).
  • Loading branch information
kmagiera authored Feb 21, 2020
1 parent f2caf02 commit b29e634
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 16 deletions.
41 changes: 28 additions & 13 deletions ios/RNSScreen.m
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -231,18 +237,24 @@ - (void)presentationControllerDidDismiss:(UIPresentationController *)presentatio
}
}

- (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;
}
Expand Down Expand Up @@ -289,12 +301,23 @@ - (void)viewDidDisappear:(BOOL)animated
// 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];
}
Expand All @@ -305,14 +328,6 @@ - (void)notifyFinishTransitioning
_previousFirstResponder = nil;
}

- (void)loadView
{
if (_view != nil) {
self.view = _view;
_view = nil;
}
}

@end

@implementation RNSScreenManager
Expand Down
23 changes: 20 additions & 3 deletions ios/RNSScreenContainer.m
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ - (void)markUpdated:(RNSScreenContainerView *)screen;

@end

@interface RNSScreenContainerView ()
@interface RNSScreenContainerView () <RCTInvalidating>

@property (nonatomic, retain) UIViewController *controller;
@property (nonatomic, retain) NSMutableSet<RNSScreenView *> *activeScreens;
Expand Down Expand Up @@ -54,7 +54,6 @@ - (void)insertReactSubview:(RNSScreenView *)subview atIndex:(NSInteger)atIndex
{
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
Expand All @@ -68,6 +67,11 @@ - (void)removeReactSubview:(RNSScreenView *)subview
return _reactSubviews;
}

- (UIViewController *)reactViewController
{
return _controller;
}

- (void)detachScreen:(RNSScreenView *)screen
{
[screen.controller willMoveToParentViewController:nil];
Expand All @@ -79,6 +83,7 @@ - (void)detachScreen:(RNSScreenView *)screen
- (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];
Expand Down Expand Up @@ -155,10 +160,22 @@ - (void)didUpdateReactSubviews
[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);
Expand Down

0 comments on commit b29e634

Please sign in to comment.