diff --git a/.gitignore b/.gitignore index 991763a9a..6cd38c8e6 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ libs node_modules package platforms +!tns-core-modules/platforms reports tags diff --git a/tns-core-modules/application/application.ios.ts b/tns-core-modules/application/application.ios.ts index a84397b4d..87a852358 100644 --- a/tns-core-modules/application/application.ios.ts +++ b/tns-core-modules/application/application.ios.ts @@ -131,16 +131,26 @@ class IOSApplication implements IOSApplicationDefinition { // TODO: Expose Window module so that it can we styled from XML & CSS this._window.backgroundColor = utils.ios.getter(UIColor, UIColor.whiteColor); + this.notifyAppStarted(notification); + + } + + public notifyAppStarted(notification?: NSNotification) { const args: LaunchEventData = { eventName: launchEvent, object: this, - ios: notification.userInfo && notification.userInfo.objectForKey("UIApplicationLaunchOptionsLocalNotificationKey") || null + ios: notification && notification.userInfo && notification.userInfo.objectForKey("UIApplicationLaunchOptionsLocalNotificationKey") || null }; notify(args); notify({ eventName: "loadAppCss", object: this, cssFile: getCssFileName() }); - this.setWindowContent(args.root); + // this._window will be undefined when NS app is embedded in a native one + if (this._window) { + this.setWindowContent(args.root); + } else { + this._window = UIApplication.sharedApplication.delegate.window; + } } @profile @@ -235,6 +245,7 @@ class IOSApplication implements IOSApplicationDefinition { this._window.makeKeyAndVisible(); } } + } const iosApp = new IOSApplication(); @@ -296,7 +307,14 @@ export function start(entry?: string | NavigationEntry) { if (rootController) { const controller = getViewController(rootView); rootView._setupAsRootView({}); - rootController.presentViewControllerAnimatedCompletion(controller, true, null); + let embedderDelegate = NativeScriptEmbedder.sharedInstance().delegate; + if (embedderDelegate) { + embedderDelegate.performSelectorWithObject("presentNativeScriptApp:", controller); + } else { + let visibleVC = utils.ios.getVisibleViewController(rootController); + visibleVC.presentViewControllerAnimatedCompletion(controller, true, null); + } + iosApp.notifyAppStarted(); } } } diff --git a/tns-core-modules/platforms/README.md b/tns-core-modules/platforms/README.md new file mode 100644 index 000000000..daac1d36d --- /dev/null +++ b/tns-core-modules/platforms/README.md @@ -0,0 +1 @@ +## Platform specific native code \ No newline at end of file diff --git a/tns-core-modules/platforms/ios/src/NativeScriptEmbedder.h b/tns-core-modules/platforms/ios/src/NativeScriptEmbedder.h new file mode 100644 index 000000000..1a35943b2 --- /dev/null +++ b/tns-core-modules/platforms/ios/src/NativeScriptEmbedder.h @@ -0,0 +1,26 @@ +// +// NativeScriptEmbedder.h +// NativeScript +// +// Created by Teodor Dermendzhiev on 6/19/18. +// +#include + +// When embedding NativeScript application embedder needs to conform to this protocol +// in order to have control over the NativeScript UIViewController +// otherwise NativeScript application is presented over the topmost UIViewController. +@protocol NativeScriptEmbedderDelegate +- (id)presentNativeScriptApp:(UIViewController*)vc; +@end + +@interface NativeScriptEmbedder : NSObject + +@property(nonatomic, retain, readonly) id delegate; + ++ (NativeScriptEmbedder *)sharedInstance; + +- (void)setDelegate:(id )aDelegate; + + +@end + diff --git a/tns-core-modules/platforms/ios/src/NativeScriptEmbedder.m b/tns-core-modules/platforms/ios/src/NativeScriptEmbedder.m new file mode 100644 index 000000000..b19fe206f --- /dev/null +++ b/tns-core-modules/platforms/ios/src/NativeScriptEmbedder.m @@ -0,0 +1,19 @@ +#import "NativeScriptEmbedder.h" + +@implementation NativeScriptEmbedder + ++ (NativeScriptEmbedder *)sharedInstance { + static NativeScriptEmbedder *sharedInstance = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[NativeScriptEmbedder alloc] init]; + }); + + return sharedInstance; +} + +- (void)setDelegate:(id )aDelegate { + _delegate = aDelegate; +} + +@end diff --git a/tns-core-modules/platforms/ios/src/module.modulemap b/tns-core-modules/platforms/ios/src/module.modulemap new file mode 100644 index 000000000..a360bf684 --- /dev/null +++ b/tns-core-modules/platforms/ios/src/module.modulemap @@ -0,0 +1,4 @@ +module NativeScriptEmbedder { + header "NativeScriptEmbedder.h" + export * +} \ No newline at end of file diff --git a/tns-core-modules/tns-core-modules.d.ts b/tns-core-modules/tns-core-modules.d.ts index 3e5b0b7ef..2160ec3fa 100644 --- a/tns-core-modules/tns-core-modules.d.ts +++ b/tns-core-modules/tns-core-modules.d.ts @@ -160,3 +160,14 @@ interface Array { //Dialogs declare function alert(message?: any): void; declare function confirm(message?: string): boolean; + +// Embedding +declare interface NativeScriptEmbedderDelegate /* NSObject */ { + presentNativeScriptApp(any/* UIViewController*/): any; + performSelectorWithObject(string, any): any; +} + +declare class NativeScriptEmbedder { + public static sharedInstance(): NativeScriptEmbedder; + public delegate: NativeScriptEmbedderDelegate; +} diff --git a/tns-core-modules/utils/utils.d.ts b/tns-core-modules/utils/utils.d.ts index 3cb7a8675..5f095b4d4 100644 --- a/tns-core-modules/utils/utils.d.ts +++ b/tns-core-modules/utils/utils.d.ts @@ -247,6 +247,13 @@ export module ios { * iOS - this folder is read-only and contains the app and all its resources. */ export function getCurrentAppPath(): string; + + /** + * Gets the currently visible(topmost) UIViewController. + * @param rootViewController The root UIViewController instance to start searching from (normally window.rootViewController). + * Returns the visible UIViewController. + */ + export function getVisibleViewController(rootViewController: any/* UIViewController*/ ): any/* UIViewController*/; } /** diff --git a/tns-core-modules/utils/utils.ios.ts b/tns-core-modules/utils/utils.ios.ts index 19d96af2a..77da535b7 100644 --- a/tns-core-modules/utils/utils.ios.ts +++ b/tns-core-modules/utils/utils.ios.ts @@ -116,6 +116,25 @@ export module ios { return NSString.stringWithString(NSString.pathWithComponents(paths)).stringByStandardizingPath; } + + export function getVisibleViewController(rootViewController: UIViewController): UIViewController { + if (rootViewController.presentedViewController) { + return getVisibleViewController(rootViewController.presentedViewController); + } + + if (rootViewController.isKindOfClass(UINavigationController.class())) { + return getVisibleViewController((rootViewController).visibleViewController); + } + + if (rootViewController.isKindOfClass(UITabBarController.class())) { + let selectedTab = (rootViewController).selectedViewController; + return getVisibleViewController(rootViewController); + } + + return rootViewController; + + } + } export function GC() {