Skip to content
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

fix: change update logic #600

Merged
merged 2 commits into from
Aug 18, 2020
Merged
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
33 changes: 26 additions & 7 deletions ios/RNSScreenStack.m
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,13 @@ @implementation RNSScreenStackView {
UINavigationController *_controller;
NSMutableArray<RNSScreenView *> *_reactSubviews;
__weak RNSScreenStackManager *_manager;
BOOL _hasLayout;
}

- (instancetype)initWithManager:(RNSScreenStackManager*)manager
{
if (self = [super init]) {
_hasLayout = NO;
_manager = manager;
_reactSubviews = [NSMutableArray new];
_presentedModals = [NSMutableArray new];
Expand Down Expand Up @@ -157,24 +159,41 @@ - (void)didUpdateReactSubviews
// set yet, however the layout call is already enqueued on ui thread. Enqueuing update call on the
// ui queue will guarantee that the update will run after layout.
dispatch_async(dispatch_get_main_queue(), ^{
[self updateContainer];
self->_hasLayout = YES;
[self maybeAddToParentAndUpdateContainer];
});
}

- (void)didMoveToWindow
{
[super didMoveToWindow];
if (self.window) {
// when stack is attached to a window we do two things:
// 1) we run updateContainer – we do this because we want push view controllers to be installed
// before the VC is mounted. If we do that after it is added to parent the push updates operations
// are going to be blocked by UIKit.
[self maybeAddToParentAndUpdateContainer];
}

- (void)maybeAddToParentAndUpdateContainer
{
if (self.window && !_hasLayout) {
// We wait with adding to parent controller until the stack is mounted and has its initial
// layout done.
// If we add it before layout, some of the items (specifically items from the navigation bar),
// won't be able to position properly. Also the position and size of such items, even if it
// happens to change, won't be properly updated (this is perhaps some internal issue of UIKit).
// If we add it when window is not attached, some of the view transitions will be bloced (i.e.
// modal transitions) and the internal view controler's state will get out of sync with what's
// on screen without us knowing.
return;
}
[self updateContainer];
if (_controller.parentViewController == nil) {
// when stack hasn't been added to parent VC yet we do two things:
// 1) we run updateContainer (the one above) – we do this because we want push view controllers to
// be installed before the VC is mounted. If we do that after it is added to parent the push
// updates operations are going to be blocked by UIKit.
// 2) we add navigation VS to parent – this is needed for the VC lifecycle events to be dispatched
// properly
// 3) we again call updateContainer – this time we do this to open modal controllers. Modals
// won't open in (1) because they require navigator to be added to parent. We handle that case
// gracefully in setModalViewControllers and can retry opening at any point.
[self updateContainer];
[self reactAddControllerToClosestParent:_controller];
[self updateContainer];
}
Expand Down