Files
NativeScript/application/application.ios.ts
2015-08-03 17:11:10 +03:00

220 lines
7.7 KiB
TypeScript

import appModule = require("application/application-common");
import frame = require("ui/frame");
import utils = require("utils/utils");
import types = require("utils/types");
import view = require("ui/core/view");
import definition = require("application");
import enums = require("ui/enums");
global.moduleMerge(appModule, exports);
export var mainModule: string;
class Window extends UIWindow {
private _content: view.View;
initWithFrame(frame: CGRect): UIWindow {
var window = super.initWithFrame(frame);
if (window) {
window.autoresizingMask = UIViewAutoresizing.UIViewAutoresizingNone;
}
return window;
}
public get content(): view.View {
return this._content;
}
public set content(value: view.View) {
this._content = value;
}
public layoutSubviews(): void {
utils.ios._layoutRootView(this._content, UIScreen.mainScreen().bounds);
}
}
class NotificationReceiver extends NSObject {
private _onReceiveCallback: (notification: NSNotification) => void;
static new(): NotificationReceiver {
return <NotificationReceiver>super.new();
}
public initWithCallback(onReceiveCallback: (notification: NSNotification) => void): NotificationReceiver {
this._onReceiveCallback = onReceiveCallback;
return this;
}
public onReceive(notification: NSNotification): void {
this._onReceiveCallback(notification);
}
public static ObjCExposedMethods = {
"onReceive": { returns: interop.types.void, params: [NSNotification] }
};
}
class IOSApplication implements definition.iOSApplication {
public rootController: any;
private _delegate: typeof UIApplicationDelegate;
private _registeredObservers = {};
private _currentOrientation = UIDevice.currentDevice().orientation;
private _window: Window;
constructor() {
this.addNotificationObserver(UIApplicationDidFinishLaunchingNotification, this.didFinishLaunchingWithOptions);
this.addNotificationObserver(UIApplicationDidBecomeActiveNotification, this.didBecomeActive);
this.addNotificationObserver(UIApplicationDidEnterBackgroundNotification, this.didEnterBackground);
this.addNotificationObserver(UIApplicationWillTerminateNotification, this.willTerminate);
this.addNotificationObserver(UIApplicationDidReceiveMemoryWarningNotification, this.didReceiveMemoryWarning);
this.addNotificationObserver(UIDeviceOrientationDidChangeNotification, this.oreintationDidChange);
}
get nativeApp(): UIApplication {
return UIApplication.sharedApplication();
}
get delegate(): typeof UIApplicationDelegate {
return this._delegate;
}
set delegate(value: typeof UIApplicationDelegate) {
if (this._delegate !== value) {
this._delegate = value;
}
}
public addNotificationObserver(notificationName: string, onReceiveCallback: (notification: NSNotification) => void) {
var observer = NotificationReceiver.new().initWithCallback(onReceiveCallback);
NSNotificationCenter.defaultCenter().addObserverSelectorNameObject(observer, "onReceive", notificationName, null);
this._registeredObservers[notificationName] = observer;
}
public removeNotificationObserver(notificationName: string) {
var observer = this._registeredObservers[notificationName];
if (observer) {
NSNotificationCenter.defaultCenter().removeObserverNameObject(observer, notificationName, null);
}
}
private didFinishLaunchingWithOptions(notification: NSNotification) {
this._window = <Window>Window.alloc().initWithFrame(UIScreen.mainScreen().bounds);
this._window.backgroundColor = UIColor.whiteColor();
if (exports.onLaunch) {
exports.onLaunch();
}
exports.notify({
eventName: definition.launchEvent,
object: this,
ios: notification.userInfo && notification.userInfo.objectForKey("UIApplicationLaunchOptionsLocalNotificationKey") || null
});
var topFrame = frame.topmost();
if (!topFrame) {
if (mainModule) {
topFrame = new frame.Frame();
topFrame.navigate(mainModule);
} else {
// TODO: Throw an exception?
// throw new Error("A Frame must be used to navigate to a Page.");
return;
}
}
this._window.content = topFrame;
this.rootController = this._window.rootViewController = topFrame.ios.controller;
this._window.makeKeyAndVisible();
}
private didBecomeActive(notification: NSNotification) {
if (exports.onResume) {
exports.onResume();
}
exports.notify({ eventName: definition.resumeEvent, object: this, ios: UIApplication.sharedApplication() });
}
private didEnterBackground(notification: NSNotification) {
if (exports.onSuspend) {
exports.onSuspend();
}
exports.notify({ eventName: definition.suspendEvent, object: this, ios: UIApplication.sharedApplication() });
}
private willTerminate(notification: NSNotification) {
if (exports.onExit) {
exports.onExit();
}
exports.notify({ eventName: definition.exitEvent, object: this, ios: UIApplication.sharedApplication() });
}
private didReceiveMemoryWarning(notification: NSNotification) {
if (exports.onLowMemory) {
exports.onLowMemory();
}
exports.notify({ eventName: definition.lowMemoryEvent, object: this, android: undefined, ios: UIApplication.sharedApplication() });
}
private oreintationDidChange(notification: NSNotification) {
var orientation = UIDevice.currentDevice().orientation;
if (this._currentOrientation !== orientation) {
this._currentOrientation = orientation;
var newValue;
switch (orientation) {
case UIDeviceOrientation.UIDeviceOrientationLandscapeRight:
case UIDeviceOrientation.UIDeviceOrientationLandscapeLeft:
newValue = enums.DeviceOrientation.landscape;
break;
case UIDeviceOrientation.UIDeviceOrientationPortrait:
case UIDeviceOrientation.UIDeviceOrientationPortraitUpsideDown:
newValue = enums.DeviceOrientation.portrait;
break;
default:
newValue = enums.DeviceOrientation.unknown;
break;
}
exports.notify(<definition.OrientationChangedEventData>{
eventName: definition.orientationChangedEvent,
ios: this,
newValue: newValue,
object: this
});
}
}
}
exports.ios = new IOSApplication();
exports.start = function () {
appModule.loadCss();
try {
// The "UIApplicationMain" enters a modal loop and the call will not return while the application is running.
// This try-catch block here will catch JavaScript errors but no Objective C ones.
// TODO: We need to implement better error handling for our native calls and to use the "error" parameter of the iOS APIs.
UIApplicationMain(0, null, null, exports.ios && exports.ios.delegate ? NSStringFromClass(exports.ios.delegate) : null);
}
catch (error) {
// At this point the main application loop is exited and no UI May be created.
if (!types.isFunction(exports.onUncaughtError)) {
return;
}
exports.onUncaughtError(error);
definition.notify({ eventName: definition.uncaughtErrorEvent, object: <any>definition.ios, ios: error });
}
}