Skip to content

Commit edb9566

Browse files
committed
fix(iOS): viewController stability for modal handling
1 parent 04233b6 commit edb9566

File tree

1 file changed

+54
-44
lines changed

1 file changed

+54
-44
lines changed

tns-core-modules/ui/core/view/view.ios.ts

Lines changed: 54 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Definitions.
1+
// Definitions.
22
import { Point, View as ViewDefinition, dip } from ".";
33
import { ViewBase } from "../view-base";
44
import { booleanConverter, Property } from "../view";
@@ -8,8 +8,9 @@ import {
88
traceEnabled, traceWrite, traceCategories, traceError, traceMessageType, getAncestor
99
} from "./view-common";
1010

11-
import { ios as iosBackground, Background } from "../../styling/background";
11+
import { topmost } from "../../frame/frame-stack";
1212
import { ios as iosUtils } from "../../../utils/utils";
13+
import { ios as iosBackground, Background } from "../../styling/background";
1314
import {
1415
Visibility,
1516
visibilityProperty, opacityProperty,
@@ -362,57 +363,66 @@ export class View extends ViewCommon {
362363
}
363364

364365
protected _showNativeModalView(parent: View, context: any, closeCallback: Function, fullscreen?: boolean, animated?: boolean, stretched?: boolean) {
366+
const that = this;
367+
const superCall = super._showNativeModalView;
365368
const parentWithController = ios.getParentWithViewController(parent);
366369
if (!parentWithController) {
367370
traceWrite(`Could not find parent with viewController for ${parent} while showing modal view.`,
368371
traceCategories.ViewHierarchy, traceMessageType.error)
369372
return;
370373
}
371374

372-
const parentController = parentWithController.viewController;
373-
if (!parentController.view || !parentController.view.window) {
374-
traceWrite("Parent page is not part of the window hierarchy. Close the current modal page before showing another one!",
375-
traceCategories.ViewHierarchy, traceMessageType.error);
376-
return;
377-
}
378-
379-
this._setupAsRootView({});
380-
381-
super._showNativeModalView(parentWithController, context, closeCallback, fullscreen, stretched);
382-
let controller = this.viewController;
383-
if (!controller) {
384-
const nativeView = this.ios || this.nativeViewProtected;
385-
controller = ios.UILayoutViewController.initWithOwner(new WeakRef(this));
386-
387-
if (nativeView instanceof UIView) {
388-
controller.view.addSubview(nativeView);
389-
}
390-
391-
this.viewController = controller;
392-
}
393-
394-
if (fullscreen) {
395-
controller.modalPresentationStyle = UIModalPresentationStyle.FullScreen;
396-
} else {
397-
controller.modalPresentationStyle = UIModalPresentationStyle.FormSheet;
398-
}
399-
400-
this.horizontalAlignment = "stretch";
401-
this.verticalAlignment = "stretch";
375+
const openNow = function() {
376+
that._setupAsRootView({});
377+
378+
superCall(parentWithController, context, closeCallback, fullscreen, stretched);
379+
let controller = that.viewController;
380+
if (!controller) {
381+
const nativeView = that.ios || that.nativeViewProtected;
382+
controller = ios.UILayoutViewController.initWithOwner(new WeakRef(that));
383+
384+
if (nativeView instanceof UIView) {
385+
controller.view.addSubview(nativeView);
386+
}
387+
388+
that.viewController = controller;
389+
}
390+
391+
if (fullscreen) {
392+
controller.modalPresentationStyle = UIModalPresentationStyle.FullScreen;
393+
} else {
394+
controller.modalPresentationStyle = UIModalPresentationStyle.FormSheet;
395+
}
396+
397+
that.horizontalAlignment = "stretch";
398+
that.verticalAlignment = "stretch";
399+
400+
that._raiseShowingModallyEvent();
401+
animated = animated === undefined ? true : !!animated;
402+
(<any>controller).animated = animated;
403+
parentController.presentViewControllerAnimatedCompletion(controller, animated, null);
404+
const transitionCoordinator = iosUtils.getter(parentController, parentController.transitionCoordinator);
405+
if (transitionCoordinator) {
406+
UIViewControllerTransitionCoordinator.prototype.animateAlongsideTransitionCompletion
407+
.call(transitionCoordinator, null, () => that._raiseShownModallyEvent());
408+
} else {
409+
// Apparently iOS 9+ stops all transitions and animations upon application suspend and transitionCoordinator becomes null here in this case.
410+
// Since we are not waiting for any transition to complete, i.e. transitionCoordinator is null, we can directly raise our shownModally event.
411+
// Take a look at https://github.com/NativeScript/NativeScript/issues/2173 for more info and a sample project.
412+
that._raiseShownModallyEvent();
413+
}
414+
};
402415

403-
this._raiseShowingModallyEvent();
404-
animated = animated === undefined ? true : !!animated;
405-
(<any>controller).animated = animated;
406-
parentController.presentViewControllerAnimatedCompletion(controller, animated, null);
407-
const transitionCoordinator = iosUtils.getter(parentController, parentController.transitionCoordinator);
408-
if (transitionCoordinator) {
409-
UIViewControllerTransitionCoordinator.prototype.animateAlongsideTransitionCompletion
410-
.call(transitionCoordinator, null, () => this._raiseShownModallyEvent());
416+
let parentController = parentWithController.viewController;
417+
if (!parentController.view || !parentController.view.window) {
418+
// close first
419+
parentController.dismissModalViewControllerAnimated(false);
420+
// give it a moment to fully close before opening again
421+
setTimeout(function() {
422+
openNow();
423+
}, 300);
411424
} else {
412-
// Apparently iOS 9+ stops all transitions and animations upon application suspend and transitionCoordinator becomes null here in this case.
413-
// Since we are not waiting for any transition to complete, i.e. transitionCoordinator is null, we can directly raise our shownModally event.
414-
// Take a look at https://github.com/NativeScript/NativeScript/issues/2173 for more info and a sample project.
415-
this._raiseShownModallyEvent();
425+
openNow();
416426
}
417427
}
418428

0 commit comments

Comments
 (0)