mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-11-05 13:26:48 +08:00
iOS owner pattern changed to use WeakRef in order to prevent memory leaks.
Optimized list-view-tests. Added time per test.
This commit is contained in:
@@ -51,7 +51,7 @@ export class ActionBar extends common.ActionBar {
|
||||
// Set back button text
|
||||
if (previousController) {
|
||||
if (this.navigationButton) {
|
||||
var tapHandler = TapBarItemHandlerImpl.new().initWithOwner(this.navigationButton);
|
||||
var tapHandler = TapBarItemHandlerImpl.initWithOwner(new WeakRef(this.navigationButton));
|
||||
var barButtonItem = UIBarButtonItem.alloc().initWithTitleStyleTargetAction(this.navigationButton.text + "", UIBarButtonItemStyle.UIBarButtonItemStylePlain, tapHandler, "tap");
|
||||
previousController.navigationItem.backBarButtonItem = barButtonItem;
|
||||
}
|
||||
@@ -112,7 +112,7 @@ export class ActionBar extends common.ActionBar {
|
||||
}
|
||||
|
||||
private createBarButtonItem(item: dts.ActionItem): UIBarButtonItem {
|
||||
var tapHandler = TapBarItemHandlerImpl.new().initWithOwner(item);
|
||||
var tapHandler = TapBarItemHandlerImpl.initWithOwner(new WeakRef(item));
|
||||
// associate handler with menuItem or it will get collected by JSC.
|
||||
(<any>item).handler = tapHandler;
|
||||
|
||||
@@ -129,7 +129,7 @@ export class ActionBar extends common.ActionBar {
|
||||
|
||||
return barButtonItem;
|
||||
}
|
||||
|
||||
|
||||
public _onTitlePropertyChanged() {
|
||||
if (!this.page) {
|
||||
return;
|
||||
@@ -141,7 +141,7 @@ export class ActionBar extends common.ActionBar {
|
||||
|
||||
private _navigationBarHeight: number = 0;
|
||||
public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number) {
|
||||
|
||||
|
||||
let width = utils.layout.getMeasureSpecSize(widthMeasureSpec);
|
||||
let widthMode = utils.layout.getMeasureSpecMode(widthMeasureSpec);
|
||||
|
||||
@@ -186,19 +186,19 @@ export class ActionBar extends common.ActionBar {
|
||||
}
|
||||
|
||||
class TapBarItemHandlerImpl extends NSObject {
|
||||
static new(): TapBarItemHandlerImpl {
|
||||
return <TapBarItemHandlerImpl>super.new();
|
||||
}
|
||||
private _owner: WeakRef<dts.ActionItemBase>;
|
||||
|
||||
private _owner: dts.ActionItemBase;
|
||||
|
||||
public initWithOwner(owner: dts.ActionItemBase): TapBarItemHandlerImpl {
|
||||
this._owner = owner;
|
||||
return this;
|
||||
public static initWithOwner(owner: WeakRef<dts.ActionItemBase>): TapBarItemHandlerImpl {
|
||||
let handler = <TapBarItemHandlerImpl>TapBarItemHandlerImpl.new();
|
||||
handler._owner = owner;
|
||||
return handler;
|
||||
}
|
||||
|
||||
public tap(args) {
|
||||
this._owner._raiseTap();
|
||||
let owner = this._owner.get();
|
||||
if (owner) {
|
||||
owner._raiseTap();
|
||||
}
|
||||
}
|
||||
|
||||
public static ObjCExposedMethods = {
|
||||
|
||||
@@ -2,19 +2,19 @@
|
||||
import stateChanged = require("ui/core/control-state-change");
|
||||
|
||||
class TapHandlerImpl extends NSObject {
|
||||
static new(): TapHandlerImpl {
|
||||
return <TapHandlerImpl>super.new();
|
||||
}
|
||||
private _owner: WeakRef<Button>;
|
||||
|
||||
private _owner: Button;
|
||||
|
||||
public initWithOwner(owner: Button): TapHandlerImpl {
|
||||
this._owner = owner;
|
||||
return this;
|
||||
public static initWithOwner(owner: WeakRef<Button>): TapHandlerImpl {
|
||||
let handler = <TapHandlerImpl>TapHandlerImpl.new();
|
||||
handler._owner = owner;
|
||||
return handler;
|
||||
}
|
||||
|
||||
public tap(args) {
|
||||
this._owner._emit(common.Button.tapEvent);
|
||||
let owner = this._owner.get();
|
||||
if (owner) {
|
||||
owner._emit(common.Button.tapEvent);
|
||||
}
|
||||
}
|
||||
|
||||
public static ObjCExposedMethods = {
|
||||
@@ -33,7 +33,7 @@ export class Button extends common.Button {
|
||||
super();
|
||||
this._ios = UIButton.buttonWithType(UIButtonType.UIButtonTypeSystem);
|
||||
|
||||
this._tapHandler = TapHandlerImpl.new().initWithOwner(this);
|
||||
this._tapHandler = TapHandlerImpl.initWithOwner(new WeakRef(this));
|
||||
this._ios.addTargetActionForControlEvents(this._tapHandler, "tap", UIControlEvents.UIControlEventTouchUpInside);
|
||||
|
||||
this._stateChangedHandler = new stateChanged.ControlStateChangeListener(this._ios, (s: string) => {
|
||||
|
||||
@@ -71,7 +71,7 @@ export class DatePicker extends common.DatePicker {
|
||||
this._ios = new UIDatePicker();
|
||||
this._ios.datePickerMode = UIDatePickerMode.UIDatePickerModeDate;
|
||||
|
||||
this._changeHandler = UIDatePickerChangeHandlerImpl.new().initWithOwner(this);
|
||||
this._changeHandler = UIDatePickerChangeHandlerImpl.initWithOwner(new WeakRef(this));
|
||||
this._ios.addTargetActionForControlEvents(this._changeHandler, "valueChanged", UIControlEvents.UIControlEventValueChanged);
|
||||
}
|
||||
|
||||
@@ -81,30 +81,33 @@ export class DatePicker extends common.DatePicker {
|
||||
}
|
||||
|
||||
class UIDatePickerChangeHandlerImpl extends NSObject {
|
||||
static new(): UIDatePickerChangeHandlerImpl {
|
||||
return <UIDatePickerChangeHandlerImpl>super.new();
|
||||
}
|
||||
|
||||
private _owner: DatePicker;
|
||||
private _owner: WeakRef<DatePicker>;
|
||||
|
||||
public initWithOwner(owner: DatePicker): UIDatePickerChangeHandlerImpl {
|
||||
this._owner = owner;
|
||||
return this;
|
||||
public static initWithOwner(owner: WeakRef<DatePicker>): UIDatePickerChangeHandlerImpl {
|
||||
let impl = <UIDatePickerChangeHandlerImpl>UIDatePickerChangeHandlerImpl.new();
|
||||
impl._owner = owner;
|
||||
return impl;
|
||||
}
|
||||
|
||||
public valueChanged(sender: UIDatePicker) {
|
||||
var comps = NSCalendar.currentCalendar().componentsFromDate(NSCalendarUnit.NSCalendarUnitYear | NSCalendarUnit.NSCalendarUnitMonth | NSCalendarUnit.NSCalendarUnitDay, sender.date);
|
||||
|
||||
if (comps.year !== this._owner.year) {
|
||||
this._owner._onPropertyChangedFromNative(common.DatePicker.yearProperty, comps.year);
|
||||
let owner = this._owner.get();
|
||||
if (!owner) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (comps.month !== this._owner.month) {
|
||||
this._owner._onPropertyChangedFromNative(common.DatePicker.monthProperty, comps.month);
|
||||
if (comps.year !== owner.year) {
|
||||
owner._onPropertyChangedFromNative(common.DatePicker.yearProperty, comps.year);
|
||||
}
|
||||
|
||||
if (comps.day !== this._owner.day) {
|
||||
this._owner._onPropertyChangedFromNative(common.DatePicker.dayProperty, comps.day);
|
||||
if (comps.month !== owner.month) {
|
||||
owner._onPropertyChangedFromNative(common.DatePicker.monthProperty, comps.month);
|
||||
}
|
||||
|
||||
if (comps.day !== owner.day) {
|
||||
owner._onPropertyChangedFromNative(common.DatePicker.dayProperty, comps.day);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -235,32 +235,42 @@ export class Frame extends frameCommon.Frame {
|
||||
class UINavigationControllerImpl extends UINavigationController implements UINavigationControllerDelegate {
|
||||
public static ObjCProtocols = [UINavigationControllerDelegate];
|
||||
|
||||
private _owner: Frame;
|
||||
private _owner: WeakRef<Frame>;
|
||||
|
||||
public static initWithOwner(owner: Frame): UINavigationControllerImpl {
|
||||
public static initWithOwner(owner: WeakRef<Frame>): UINavigationControllerImpl {
|
||||
var controller = <UINavigationControllerImpl>UINavigationControllerImpl.new();
|
||||
controller._owner = owner;
|
||||
return controller;
|
||||
}
|
||||
|
||||
get owner(): Frame {
|
||||
return this._owner;
|
||||
return this._owner.get();
|
||||
}
|
||||
|
||||
public viewDidLoad(): void {
|
||||
this._owner.onLoaded();
|
||||
let owner = this._owner.get();
|
||||
if (owner) {
|
||||
owner.onLoaded();
|
||||
}
|
||||
}
|
||||
|
||||
public viewDidLayoutSubviews(): void {
|
||||
trace.write(this._owner + " viewDidLayoutSubviews, isLoaded = " + this._owner.isLoaded, trace.categories.ViewHierarchy);
|
||||
this._owner._updateLayout();
|
||||
let owner = this._owner.get();
|
||||
if (owner) {
|
||||
trace.write(this._owner + " viewDidLayoutSubviews, isLoaded = " + owner.isLoaded, trace.categories.ViewHierarchy);
|
||||
owner._updateLayout();
|
||||
}
|
||||
}
|
||||
|
||||
public navigationControllerWillShowViewControllerAnimated(navigationController: UINavigationController, viewController: UIViewController, animated: boolean): void {
|
||||
// In this method we need to layout the new page otherwise page will be shown empty and update after that which is bad UX.
|
||||
var frame = this._owner;
|
||||
var newEntry: definition.BackstackEntry = viewController[ENTRY];
|
||||
var newPage = newEntry.resolvedPage;
|
||||
let frame = this._owner.get();
|
||||
if (!frame) {
|
||||
return;
|
||||
}
|
||||
|
||||
let newEntry: definition.BackstackEntry = viewController[ENTRY];
|
||||
let newPage = newEntry.resolvedPage;
|
||||
if (!newPage.parent) {
|
||||
if (!frame._currentEntry) {
|
||||
// First navigation
|
||||
@@ -282,14 +292,18 @@ class UINavigationControllerImpl extends UINavigationController implements UINav
|
||||
}
|
||||
|
||||
public navigationControllerDidShowViewControllerAnimated(navigationController: UINavigationController, viewController: UIViewController, animated: boolean): void {
|
||||
var frame: Frame = this._owner;
|
||||
var backStack = frame.backStack;
|
||||
var currentEntry = backStack.length > 0 ? backStack[backStack.length - 1] : null;
|
||||
var newEntry: definition.BackstackEntry = viewController[ENTRY];
|
||||
let frame = this._owner.get();
|
||||
if (!frame) {
|
||||
return;
|
||||
}
|
||||
|
||||
let backStack = frame.backStack;
|
||||
let currentEntry = backStack.length > 0 ? backStack[backStack.length - 1] : null;
|
||||
let newEntry: definition.BackstackEntry = viewController[ENTRY];
|
||||
|
||||
// This code check if navigation happened through UI (e.g. back button or swipe gesture).
|
||||
// When calling goBack on frame isBack will be false.
|
||||
var isBack: boolean = currentEntry && newEntry === currentEntry;
|
||||
let isBack: boolean = currentEntry && newEntry === currentEntry;
|
||||
if (isBack) {
|
||||
try {
|
||||
frame._shouldSkipNativePop = true;
|
||||
@@ -300,7 +314,7 @@ class UINavigationControllerImpl extends UINavigationController implements UINav
|
||||
}
|
||||
}
|
||||
|
||||
var page = frame.currentPage;
|
||||
let page = frame.currentPage;
|
||||
if (page && !navigationController.viewControllers.containsObject(page.ios)) {
|
||||
frame._removeView(page);
|
||||
}
|
||||
@@ -308,7 +322,7 @@ class UINavigationControllerImpl extends UINavigationController implements UINav
|
||||
frame._navigateToEntry = null;
|
||||
frame._currentEntry = newEntry;
|
||||
|
||||
var newPage = newEntry.resolvedPage;
|
||||
let newPage = newEntry.resolvedPage;
|
||||
|
||||
// In iOS we intentionally delay the raising of the 'loaded' event so both platforms behave identically.
|
||||
// The loaded event must be raised AFTER the page is part of the windows hierarchy and
|
||||
@@ -337,7 +351,7 @@ class iOSFrame implements definition.iOSFrame {
|
||||
private _navBarVisibility: string;
|
||||
|
||||
constructor(owner: Frame) {
|
||||
this._controller = UINavigationControllerImpl.initWithOwner(owner);
|
||||
this._controller = UINavigationControllerImpl.initWithOwner(new WeakRef(owner));
|
||||
this._controller.delegate = this._controller;
|
||||
this._controller.automaticallyAdjustsScrollViewInsets = false;
|
||||
//this.showNavigationBar = false;
|
||||
@@ -356,8 +370,9 @@ class iOSFrame implements definition.iOSFrame {
|
||||
this._showNavigationBar = value;
|
||||
this._controller.navigationBarHidden = !value;
|
||||
|
||||
if (change) {
|
||||
this._controller.owner.requestLayout();
|
||||
let owner = this._controller.owner;
|
||||
if (owner && change) {
|
||||
owner.requestLayout();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,28 +7,26 @@ import trace = require("trace");
|
||||
global.moduleMerge(common, exports);
|
||||
|
||||
class UIGestureRecognizerImpl extends NSObject {
|
||||
static new(): UIGestureRecognizerImpl {
|
||||
return <UIGestureRecognizerImpl>super.new();
|
||||
}
|
||||
|
||||
private _owner: GesturesObserver;
|
||||
private _owner: WeakRef<GesturesObserver>;
|
||||
private _type: any;
|
||||
private _callback: Function;
|
||||
private _context: any;
|
||||
|
||||
public initWithOwnerTypeCallback(owner: GesturesObserver, type: any, callback?: Function, thisArg?: any): UIGestureRecognizerImpl {
|
||||
this._owner = owner;
|
||||
this._type = type;
|
||||
public static initWithOwnerTypeCallback(owner: WeakRef<GesturesObserver>, type: any, callback?: Function, thisArg?: any): UIGestureRecognizerImpl {
|
||||
let handler = <UIGestureRecognizerImpl>UIGestureRecognizerImpl.new();
|
||||
handler._owner = owner;
|
||||
handler._type = type;
|
||||
|
||||
if (callback) {
|
||||
this._callback = callback;
|
||||
handler._callback = callback;
|
||||
}
|
||||
|
||||
if (thisArg) {
|
||||
this._context = thisArg;
|
||||
handler._context = thisArg;
|
||||
}
|
||||
|
||||
return this;
|
||||
return handler;
|
||||
}
|
||||
|
||||
public static ObjCExposedMethods = {
|
||||
@@ -36,17 +34,18 @@ class UIGestureRecognizerImpl extends NSObject {
|
||||
};
|
||||
|
||||
public recognize(recognizer: UIGestureRecognizer): void {
|
||||
var callback = this._callback ? this._callback : this._owner.callback;
|
||||
var type = this._type;
|
||||
var target = this._owner.target;
|
||||
let owner = this._owner.get();
|
||||
let callback = this._callback ? this._callback : (owner ? owner.callback : null);
|
||||
let typeParam = this._type;
|
||||
let target = owner ? owner.target : undefined;
|
||||
|
||||
var args = {
|
||||
type: type,
|
||||
type: typeParam,
|
||||
view: target,
|
||||
ios: recognizer,
|
||||
android: undefined,
|
||||
object: target,
|
||||
eventName: definition.toString(type),
|
||||
eventName: definition.toString(typeParam),
|
||||
};
|
||||
|
||||
if (callback) {
|
||||
@@ -209,7 +208,7 @@ export class GesturesObserver extends common.GesturesObserver {
|
||||
}
|
||||
|
||||
function _createUIGestureRecognizerTarget(owner: GesturesObserver, type: definition.GestureTypes, callback?: (args: definition.GestureEventData) => void, thisArg?: any): any {
|
||||
return UIGestureRecognizerImpl.new().initWithOwnerTypeCallback(owner, type, callback, thisArg);
|
||||
return UIGestureRecognizerImpl.initWithOwnerTypeCallback(new WeakRef(owner), type, callback, thisArg);
|
||||
}
|
||||
|
||||
interface RecognizerCache {
|
||||
|
||||
@@ -24,35 +24,44 @@ function onTextWrapPropertyChanged(data: dependencyObservable.PropertyChangeData
|
||||
global.moduleMerge(common, exports);
|
||||
|
||||
class UILabelImpl extends UILabel {
|
||||
static new(): UILabelImpl {
|
||||
return <UILabelImpl>super.new();
|
||||
}
|
||||
|
||||
private _owner: Label;
|
||||
private _owner: WeakRef<Label>;
|
||||
|
||||
public initWithOwner(owner: Label): UILabelImpl {
|
||||
this._owner = owner;
|
||||
return this;
|
||||
public static initWithOwner(owner: WeakRef<Label>): UILabelImpl {
|
||||
let labelImpl = <UILabelImpl>UILabelImpl.new();
|
||||
labelImpl._owner = owner;
|
||||
return labelImpl;
|
||||
}
|
||||
|
||||
public textRectForBoundsLimitedToNumberOfLines(bounds: CGRect, numberOfLines: number): CGRect {
|
||||
var rect = super.textRectForBoundsLimitedToNumberOfLines(bounds, numberOfLines);
|
||||
var textRect = CGRectMake(
|
||||
- (this._owner.borderWidth + this._owner.style.paddingLeft),
|
||||
- (this._owner.borderWidth + this._owner.style.paddingTop),
|
||||
rect.size.width + (this._owner.borderWidth + this._owner.style.paddingLeft + this._owner.style.paddingRight + this._owner.borderWidth),
|
||||
rect.size.height + (this._owner.borderWidth + this._owner.style.paddingTop + this._owner.style.paddingBottom + this._owner.borderWidth)
|
||||
let rect = super.textRectForBoundsLimitedToNumberOfLines(bounds, numberOfLines);
|
||||
let owner = this._owner.get();
|
||||
if (owner) {
|
||||
let size = rect.size;
|
||||
rect = CGRectMake(
|
||||
- (owner.borderWidth + owner.style.paddingLeft),
|
||||
- (owner.borderWidth + owner.style.paddingTop),
|
||||
size.width + (owner.borderWidth + owner.style.paddingLeft + owner.style.paddingRight + owner.borderWidth),
|
||||
size.height + (owner.borderWidth + owner.style.paddingTop + owner.style.paddingBottom + owner.borderWidth)
|
||||
);
|
||||
return textRect;
|
||||
}
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
public drawTextInRect(rect: CGRect): void {
|
||||
var textRect = CGRectMake(
|
||||
(this._owner.borderWidth + this._owner.style.paddingLeft),
|
||||
(this._owner.borderWidth + this._owner.style.paddingTop),
|
||||
rect.size.width - (this._owner.borderWidth + this._owner.style.paddingLeft + this._owner.style.paddingRight + this._owner.borderWidth),
|
||||
rect.size.height - (this._owner.borderWidth + this._owner.style.paddingTop + this._owner.style.paddingBottom + this._owner.borderWidth)
|
||||
);
|
||||
let owner = this._owner.get();
|
||||
let textRect: CGRect;
|
||||
let size = rect.size;
|
||||
if (owner) {
|
||||
textRect = CGRectMake((owner.borderWidth + owner.style.paddingLeft), (owner.borderWidth + owner.style.paddingTop),
|
||||
size.width - (owner.borderWidth + owner.style.paddingLeft + owner.style.paddingRight + owner.borderWidth),
|
||||
size.height - (owner.borderWidth + owner.style.paddingTop + owner.style.paddingBottom + owner.borderWidth));
|
||||
}
|
||||
else {
|
||||
textRect = CGRectMake(0, 0, size.width, size.height);
|
||||
}
|
||||
|
||||
super.drawTextInRect(textRect);
|
||||
}
|
||||
}
|
||||
@@ -63,8 +72,7 @@ export class Label extends common.Label {
|
||||
constructor(options?: definition.Options) {
|
||||
super(options);
|
||||
|
||||
//this._ios = new UILabel();
|
||||
this._ios = UILabelImpl.new().initWithOwner(this);
|
||||
this._ios = UILabelImpl.initWithOwner(new WeakRef(this));
|
||||
this._ios.userInteractionEnabled = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,13 +13,8 @@ export class ListPicker extends common.ListPicker {
|
||||
super();
|
||||
|
||||
this._ios = new UIPickerView();
|
||||
|
||||
var dataSource = ListPickerDataSource.new().initWithOwner(this);
|
||||
|
||||
this._dataSource = dataSource;
|
||||
this._ios.dataSource = this._dataSource;
|
||||
|
||||
this._delegate = ListPickerDelegateImpl.new().initWithOwner(this);
|
||||
this._ios.dataSource = this._dataSource = ListPickerDataSource.initWithOwner(new WeakRef(this));
|
||||
this._delegate = ListPickerDelegateImpl.initWithOwner(new WeakRef(this));
|
||||
}
|
||||
|
||||
public onLoaded() {
|
||||
@@ -55,16 +50,13 @@ export class ListPicker extends common.ListPicker {
|
||||
|
||||
class ListPickerDataSource extends NSObject implements UIPickerViewDataSource {
|
||||
public static ObjCProtocols = [UIPickerViewDataSource];
|
||||
|
||||
private _owner: WeakRef<ListPicker>;
|
||||
|
||||
static new(): ListPickerDataSource {
|
||||
return <ListPickerDataSource>super.new();
|
||||
}
|
||||
|
||||
private _owner: ListPicker;
|
||||
|
||||
public initWithOwner(owner: ListPicker): ListPickerDataSource {
|
||||
this._owner = owner;
|
||||
return this;
|
||||
public static initWithOwner(owner: WeakRef<ListPicker>): ListPickerDataSource {
|
||||
let dataSource = <ListPickerDataSource>ListPickerDataSource.new();
|
||||
dataSource._owner = owner;
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
public numberOfComponentsInPickerView(pickerView: UIPickerView) {
|
||||
@@ -72,35 +64,35 @@ class ListPickerDataSource extends NSObject implements UIPickerViewDataSource {
|
||||
}
|
||||
|
||||
public pickerViewNumberOfRowsInComponent(pickerView: UIPickerView, component: number) {
|
||||
return this._owner.items ? this._owner.items.length : 0;
|
||||
let owner = this._owner.get();
|
||||
return (owner && owner.items) ? owner.items.length : 0;
|
||||
}
|
||||
}
|
||||
|
||||
class ListPickerDelegateImpl extends NSObject implements UIPickerViewDelegate {
|
||||
public static ObjCProtocols = [UIPickerViewDelegate];
|
||||
|
||||
static new(): ListPickerDelegateImpl {
|
||||
return <ListPickerDelegateImpl>super.new();
|
||||
}
|
||||
private _owner: WeakRef<ListPicker>;
|
||||
|
||||
private _owner: ListPicker;
|
||||
|
||||
public initWithOwner(owner: ListPicker): ListPickerDelegateImpl {
|
||||
this._owner = owner;
|
||||
return this;
|
||||
public static initWithOwner(owner: WeakRef<ListPicker>): ListPickerDelegateImpl {
|
||||
let delegate = <ListPickerDelegateImpl>ListPickerDelegateImpl.new();
|
||||
delegate._owner = owner;
|
||||
return delegate;
|
||||
}
|
||||
|
||||
public pickerViewTitleForRowForComponent(pickerView: UIPickerView, row: number, component: number): string {
|
||||
if (this._owner) {
|
||||
return this._owner._getItemAsString(row);
|
||||
let owner = this._owner.get();
|
||||
if (owner) {
|
||||
return owner._getItemAsString(row);
|
||||
}
|
||||
|
||||
return row.toString();
|
||||
}
|
||||
|
||||
public pickerViewDidSelectRowInComponent(pickerView: UIPickerView, row: number, component: number): void {
|
||||
if (this._owner) {
|
||||
this._owner._onPropertyChangedFromNative(common.ListPicker.selectedIndexProperty, row);
|
||||
let owner = this._owner.get();
|
||||
if (owner) {
|
||||
owner._onPropertyChangedFromNative(common.ListPicker.selectedIndexProperty, row);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,13 +18,25 @@ global.moduleMerge(common, exports);
|
||||
var infinity = utils.layout.makeMeasureSpec(0, utils.layout.UNSPECIFIED);
|
||||
|
||||
class ListViewCell extends UITableViewCell {
|
||||
static new(): ListViewCell {
|
||||
return <ListViewCell>super.new();
|
||||
public willMoveToSuperview(newSuperview: UIView): void {
|
||||
let parent: ListView = <ListView>(this.view ? this.view.parent : null);
|
||||
|
||||
// When inside ListView and there is no newSuperview this cell is
|
||||
// removed from native visual tree so we remove it from our tree too.
|
||||
if (parent && !newSuperview) {
|
||||
parent._removeContainer(this);
|
||||
}
|
||||
}
|
||||
|
||||
public get view(): view.View {
|
||||
return this.owner ? this.owner.get() : null
|
||||
}
|
||||
|
||||
public owner: WeakRef<view.View>;
|
||||
}
|
||||
|
||||
function notifyForItemAtIndex(listView: definition.ListView, cell: any, eventName: string, indexPath: NSIndexPath) {
|
||||
var args = <definition.ItemEventData>{ eventName: eventName, object: listView, index: indexPath.row, view: cell.view, ios: cell, android: undefined };
|
||||
function notifyForItemAtIndex(listView: definition.ListView, cell: any, view: view.View, eventName: string, indexPath: NSIndexPath) {
|
||||
let args = <definition.ItemEventData>{ eventName: eventName, object: listView, index: indexPath.row, view: view, ios: cell, android: undefined };
|
||||
listView.notify(args);
|
||||
return args;
|
||||
}
|
||||
@@ -32,35 +44,35 @@ function notifyForItemAtIndex(listView: definition.ListView, cell: any, eventNam
|
||||
class DataSource extends NSObject implements UITableViewDataSource {
|
||||
public static ObjCProtocols = [UITableViewDataSource];
|
||||
|
||||
static new(): DataSource {
|
||||
return <DataSource>super.new();
|
||||
}
|
||||
private _owner: WeakRef<ListView>;
|
||||
|
||||
private _owner: ListView;
|
||||
|
||||
public initWithOwner(owner: ListView): DataSource {
|
||||
this._owner = owner;
|
||||
return this;
|
||||
public static initWithOwner(owner: WeakRef<ListView>): DataSource {
|
||||
let dataSource = <DataSource>DataSource.new();
|
||||
dataSource._owner = owner;
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
public tableViewNumberOfRowsInSection(tableView: UITableView, section: number) {
|
||||
return this._owner.items ? this._owner.items.length : 0;
|
||||
let owner = this._owner.get();
|
||||
return (owner && owner.items) ? owner.items.length : 0;
|
||||
}
|
||||
|
||||
public tableViewCellForRowAtIndexPath(tableView: UITableView, indexPath: NSIndexPath): UITableViewCell {
|
||||
// We call this method because ...ForIndexPath calls tableViewHeightForRowAtIndexPath immediately (before we can prepare and measure it).
|
||||
var cell = tableView.dequeueReusableCellWithIdentifier(CELLIDENTIFIER) || ListViewCell.new();
|
||||
this._owner._prepareCell(cell, indexPath);
|
||||
let cell = <ListViewCell>(tableView.dequeueReusableCellWithIdentifier(CELLIDENTIFIER) || ListViewCell.new());
|
||||
let owner = this._owner.get();
|
||||
if (owner) {
|
||||
owner._prepareCell(cell, indexPath);
|
||||
|
||||
var cellView: view.View = cell.view;
|
||||
if (cellView) {
|
||||
// Arrange cell views. We do it here instead of _layoutCell because _layoutCell is called
|
||||
// from 'tableViewHeightForRowAtIndexPath' method too (in iOS 7.1) and we don't want to arrange the fake cell.
|
||||
var width = utils.layout.getMeasureSpecSize(this._owner.widthMeasureSpec);
|
||||
var cellHeight = this._owner.getHeight(indexPath.row);
|
||||
view.View.layoutChild(this._owner, cellView, 0, 0, width, cellHeight);
|
||||
let cellView: view.View = cell.view;
|
||||
if (cellView) {
|
||||
// Arrange cell views. We do it here instead of _layoutCell because _layoutCell is called
|
||||
// from 'tableViewHeightForRowAtIndexPath' method too (in iOS 7.1) and we don't want to arrange the fake cell.
|
||||
let width = utils.layout.getMeasureSpecSize(owner.widthMeasureSpec);
|
||||
let cellHeight = owner.getHeight(indexPath.row);
|
||||
view.View.layoutChild(owner, cellView, 0, 0, width, cellHeight);
|
||||
}
|
||||
}
|
||||
|
||||
return cell;
|
||||
}
|
||||
}
|
||||
@@ -68,45 +80,52 @@ class DataSource extends NSObject implements UITableViewDataSource {
|
||||
class UITableViewDelegateImpl extends NSObject implements UITableViewDelegate {
|
||||
public static ObjCProtocols = [UITableViewDelegate];
|
||||
|
||||
static new(): UITableViewDelegateImpl {
|
||||
return <UITableViewDelegateImpl>super.new();
|
||||
}
|
||||
private _owner: WeakRef<ListView>;
|
||||
private _measureCell: ListViewCell;
|
||||
|
||||
private _owner: ListView;
|
||||
private _measureCell: UITableViewCell;
|
||||
|
||||
public initWithOwner(owner: ListView): UITableViewDelegateImpl {
|
||||
this._owner = owner;
|
||||
return this;
|
||||
public static initWithOwner(owner: WeakRef<ListView>): UITableViewDelegateImpl {
|
||||
let delegate = <UITableViewDelegateImpl>UITableViewDelegateImpl.new();
|
||||
delegate._owner = owner;
|
||||
return delegate;
|
||||
}
|
||||
|
||||
public tableViewWillDisplayCellForRowAtIndexPath(tableView: UITableView, cell: UITableViewCell, indexPath: NSIndexPath) {
|
||||
if (indexPath.row === this._owner.items.length - 1) {
|
||||
this._owner.notify(<observable.EventData>{ eventName: LOADMOREITEMS, object: this._owner });
|
||||
let owner = this._owner.get();
|
||||
if (owner && (indexPath.row === owner.items.length - 1)) {
|
||||
owner.notify(<observable.EventData>{ eventName: LOADMOREITEMS, object: owner });
|
||||
}
|
||||
}
|
||||
|
||||
public tableViewWillSelectRowAtIndexPath(tableView: UITableView, indexPath: NSIndexPath): NSIndexPath {
|
||||
var cell = tableView.cellForRowAtIndexPath(indexPath);
|
||||
notifyForItemAtIndex(this._owner, cell, ITEMTAP, indexPath);
|
||||
let cell = <ListViewCell>tableView.cellForRowAtIndexPath(indexPath);
|
||||
let owner = this._owner.get();
|
||||
if (owner) {
|
||||
notifyForItemAtIndex(owner, cell, cell.view, ITEMTAP, indexPath);
|
||||
}
|
||||
cell.highlighted = false;
|
||||
return indexPath;
|
||||
}
|
||||
|
||||
public tableViewHeightForRowAtIndexPath(tableView: UITableView, indexPath: NSIndexPath): number {
|
||||
var height = undefined;
|
||||
if (utils.ios.MajorVersion >= 8) {
|
||||
height = this._owner.getHeight(indexPath.row);
|
||||
let owner = this._owner.get();
|
||||
if (!owner) {
|
||||
return 44;
|
||||
}
|
||||
|
||||
let height = undefined;
|
||||
if (utils.ios.MajorVersion >= 8) {
|
||||
height = owner.getHeight(indexPath.row);
|
||||
}
|
||||
|
||||
if (utils.ios.MajorVersion < 8 || height === undefined) {
|
||||
// in iOS 7.1 (or iOS8+ after call to scrollToRowAtIndexPath:atScrollPosition:animated:) this method is called before tableViewCellForRowAtIndexPath so we need fake cell to measure its content.
|
||||
var cell = this._measureCell;
|
||||
let cell = this._measureCell;
|
||||
if (!cell) {
|
||||
this._measureCell = tableView.dequeueReusableCellWithIdentifier(CELLIDENTIFIER) || ListViewCell.new();
|
||||
cell = this._measureCell;
|
||||
}
|
||||
|
||||
height = this._owner._prepareCell(cell, indexPath);
|
||||
height = owner._prepareCell(cell, indexPath);
|
||||
}
|
||||
|
||||
return height;
|
||||
@@ -134,7 +153,7 @@ export class ListView extends common.ListView {
|
||||
private _heights: Array<number>;
|
||||
private _preparingCell: boolean = false;
|
||||
private _isDataDirty: boolean = false;
|
||||
|
||||
private _map: Map<ListViewCell, view.View>;
|
||||
widthMeasureSpec: number = 0;
|
||||
|
||||
constructor() {
|
||||
@@ -145,14 +164,10 @@ export class ListView extends common.ListView {
|
||||
this._ios.autoresizingMask = UIViewAutoresizing.UIViewAutoresizingNone;
|
||||
this._ios.estimatedRowHeight = DEFAULT_HEIGHT;
|
||||
|
||||
var dataSource = DataSource.new().initWithOwner(this);
|
||||
|
||||
this._dataSource = dataSource;
|
||||
this._ios.dataSource = this._dataSource;
|
||||
|
||||
this._delegate = UITableViewDelegateImpl.new().initWithOwner(this);
|
||||
|
||||
this._ios.dataSource = this._dataSource = DataSource.initWithOwner(new WeakRef(this));
|
||||
this._delegate = UITableViewDelegateImpl.initWithOwner(new WeakRef(this));
|
||||
this._heights = new Array<number>();
|
||||
this._map = new Map<ListViewCell, view.View>();
|
||||
}
|
||||
|
||||
public onLoaded() {
|
||||
@@ -225,22 +240,34 @@ export class ListView extends common.ListView {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public _prepareCell(tableCell: UITableViewCell, indexPath: NSIndexPath): number {
|
||||
var cell: any = tableCell;
|
||||
var cellHeight: number;
|
||||
public _prepareCell(cell: ListViewCell, indexPath: NSIndexPath): number {
|
||||
let cellHeight: number;
|
||||
|
||||
try {
|
||||
this._preparingCell = true;
|
||||
if (!cell.view) {
|
||||
cell.view = this._getItemTemplateContent(indexPath.row);
|
||||
let view = cell.view;
|
||||
if (!view) {
|
||||
view = this._getItemTemplateContent(indexPath.row);
|
||||
}
|
||||
|
||||
var args = notifyForItemAtIndex(this, cell, ITEMLOADING, indexPath);
|
||||
var view = cell.view = args.view || this._getDefaultItemContent(indexPath.row);
|
||||
let args = notifyForItemAtIndex(this, cell, view, ITEMLOADING, indexPath);
|
||||
view = args.view || this._getDefaultItemContent(indexPath.row);
|
||||
|
||||
// If cell is reused be have old content - remove it first.
|
||||
if (!cell.view) {
|
||||
cell.owner = new WeakRef(view);
|
||||
}
|
||||
else if (cell.view !== view) {
|
||||
this._removeContainer(cell);
|
||||
(<UIView>cell.view._nativeView).removeFromSuperview();
|
||||
cell.owner = new WeakRef(view);
|
||||
}
|
||||
|
||||
this._prepareItem(view, indexPath.row);
|
||||
if (view && !view.parent && view.ios) {
|
||||
cell.contentView.addSubview(view.ios);
|
||||
this._map.set(cell, view);
|
||||
// We expect that views returned from itemLoading are new (e.g. not reused).
|
||||
if (view && !view.parent && view._nativeView) {
|
||||
cell.contentView.addSubview(view._nativeView);
|
||||
this._addView(view);
|
||||
}
|
||||
|
||||
@@ -251,4 +278,9 @@ export class ListView extends common.ListView {
|
||||
}
|
||||
return cellHeight;
|
||||
}
|
||||
|
||||
public _removeContainer(cell: ListViewCell): void {
|
||||
this._removeView(cell.view)
|
||||
this._map.delete(cell);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,35 +11,30 @@ import observable = require("data/observable");
|
||||
global.moduleMerge(pageCommon, exports);
|
||||
|
||||
class UIViewControllerImpl extends UIViewController {
|
||||
static new(): UIViewControllerImpl {
|
||||
return <UIViewControllerImpl>super.new();
|
||||
}
|
||||
|
||||
private _owner: Page;
|
||||
private _owner: WeakRef<Page>;
|
||||
|
||||
public initWithOwner(owner: Page): UIViewControllerImpl {
|
||||
this._owner = owner;
|
||||
this.automaticallyAdjustsScrollViewInsets = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
public didRotateFromInterfaceOrientation(fromInterfaceOrientation: number) {
|
||||
trace.write(this._owner + " didRotateFromInterfaceOrientation(" + fromInterfaceOrientation + ")", trace.categories.ViewHierarchy);
|
||||
}
|
||||
|
||||
public viewDidLoad() {
|
||||
trace.write(this._owner + " viewDidLoad", trace.categories.ViewHierarchy);
|
||||
public static initWithOwner(owner: WeakRef<Page>): UIViewControllerImpl {
|
||||
let controller = <UIViewControllerImpl>UIViewControllerImpl.new();
|
||||
controller._owner = owner;
|
||||
controller.automaticallyAdjustsScrollViewInsets = false;
|
||||
return controller;
|
||||
}
|
||||
|
||||
public viewDidLayoutSubviews() {
|
||||
trace.write(this._owner + " viewDidLayoutSubviews, isLoaded = " + this._owner.isLoaded, trace.categories.ViewHierarchy);
|
||||
if (!this._owner.isLoaded) {
|
||||
let owner = this._owner.get();
|
||||
if (!owner) {
|
||||
return;
|
||||
}
|
||||
|
||||
trace.write(owner + " viewDidLayoutSubviews, isLoaded = " + owner.isLoaded, trace.categories.ViewHierarchy);
|
||||
if (!owner.isLoaded) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._owner._isModal) {
|
||||
if (owner._isModal) {
|
||||
let isTablet = device.deviceType === DeviceType.Tablet;
|
||||
let isFullScreen = !this._owner._UIModalPresentationFormSheet || !isTablet;
|
||||
let isFullScreen = !owner._UIModalPresentationFormSheet || !isTablet;
|
||||
let frame = isFullScreen ? UIScreen.mainScreen().bounds : this.view.frame;
|
||||
let origin = frame.origin;
|
||||
let size = frame.size;
|
||||
@@ -62,7 +57,7 @@ class UIViewControllerImpl extends UIViewController {
|
||||
let bottom = height;
|
||||
let statusBarHeight = uiUtils.ios.getStatusBarHeight();
|
||||
let statusBarVisible = !UIApplication.sharedApplication().statusBarHidden;
|
||||
let backgroundSpanUnderStatusBar = this._owner.backgroundSpanUnderStatusBar;
|
||||
let backgroundSpanUnderStatusBar = owner.backgroundSpanUnderStatusBar;
|
||||
if (statusBarVisible && !backgroundSpanUnderStatusBar) {
|
||||
height -= statusBarHeight;
|
||||
}
|
||||
@@ -70,9 +65,9 @@ class UIViewControllerImpl extends UIViewController {
|
||||
let widthSpec = utils.layout.makeMeasureSpec(width, mode);
|
||||
let heightSpec = utils.layout.makeMeasureSpec(height, mode);
|
||||
|
||||
View.measureChild(null, this._owner, widthSpec, heightSpec);
|
||||
View.measureChild(null, owner, widthSpec, heightSpec);
|
||||
let top = ((backgroundSpanUnderStatusBar && isFullScreen) || utils.ios.MajorVersion < 8 || !isFullScreen) ? 0 : statusBarHeight;
|
||||
View.layoutChild(null, this._owner, 0, top, width, bottom);
|
||||
View.layoutChild(null, owner, 0, top, width, bottom);
|
||||
|
||||
if (utils.ios.MajorVersion < 8) {
|
||||
if (!backgroundSpanUnderStatusBar && (!isTablet || isFullScreen)) {
|
||||
@@ -88,31 +83,41 @@ class UIViewControllerImpl extends UIViewController {
|
||||
trace.write(this._owner + ", native frame = " + NSStringFromCGRect(this.view.frame), trace.categories.Layout);
|
||||
}
|
||||
else {
|
||||
this._owner._updateLayout();
|
||||
owner._updateLayout();
|
||||
}
|
||||
}
|
||||
|
||||
public viewWillAppear() {
|
||||
trace.write(this._owner + " viewWillAppear", trace.categories.Navigation);
|
||||
this._owner._enableLoadedEvents = true;
|
||||
let owner = this._owner.get();
|
||||
if (!owner) {
|
||||
return;
|
||||
}
|
||||
|
||||
trace.write(owner + " viewWillAppear", trace.categories.Navigation);
|
||||
owner._enableLoadedEvents = true;
|
||||
|
||||
// In iOS we intentionally delay the raising of the 'loaded' event so both platforms behave identically.
|
||||
// The loaded event must be raised AFTER the page is part of the windows hierarchy and
|
||||
// frame.topmost().currentPage is set to the page instance.
|
||||
// https://github.com/NativeScript/NativeScript/issues/779
|
||||
if (!this._owner._isModal) {
|
||||
this._owner._delayLoadedEvent = true;
|
||||
if (!owner._isModal) {
|
||||
owner._delayLoadedEvent = true;
|
||||
}
|
||||
|
||||
this._owner.onLoaded();
|
||||
this._owner._enableLoadedEvents = false;
|
||||
owner.onLoaded();
|
||||
owner._enableLoadedEvents = false;
|
||||
}
|
||||
|
||||
public viewDidDisappear() {
|
||||
trace.write(this._owner + " viewDidDisappear", trace.categories.Navigation);
|
||||
this._owner._enableLoadedEvents = true;
|
||||
this._owner.onUnloaded();
|
||||
this._owner._enableLoadedEvents = false;
|
||||
let owner = this._owner.get();
|
||||
if (!owner) {
|
||||
return;
|
||||
}
|
||||
|
||||
trace.write(owner + " viewDidDisappear", trace.categories.Navigation);
|
||||
owner._enableLoadedEvents = true;
|
||||
owner.onUnloaded();
|
||||
owner._enableLoadedEvents = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,7 +130,7 @@ export class Page extends pageCommon.Page {
|
||||
|
||||
constructor(options?: definition.Options) {
|
||||
super(options);
|
||||
this._ios = UIViewControllerImpl.new().initWithOwner(this);
|
||||
this._ios = UIViewControllerImpl.initWithOwner(new WeakRef(this));
|
||||
}
|
||||
|
||||
public requestLayout(): void {
|
||||
|
||||
@@ -57,24 +57,26 @@ global.moduleMerge(common, exports);
|
||||
class UISearchBarDelegateImpl extends NSObject implements UISearchBarDelegate {
|
||||
public static ObjCProtocols = [UISearchBarDelegate];
|
||||
|
||||
static new(): UISearchBarDelegateImpl {
|
||||
return <UISearchBarDelegateImpl>super.new();
|
||||
}
|
||||
|
||||
private _owner: SearchBar;
|
||||
private _owner: WeakRef<SearchBar>;
|
||||
private _searchText: string;
|
||||
|
||||
public initWithOwner(owner: SearchBar): UISearchBarDelegateImpl {
|
||||
this._owner = owner;
|
||||
return this;
|
||||
public static initWithOwner(owner: WeakRef<SearchBar>): UISearchBarDelegateImpl {
|
||||
let delegate = <UISearchBarDelegateImpl>UISearchBarDelegateImpl.new();
|
||||
delegate._owner = owner;
|
||||
return delegate;
|
||||
}
|
||||
|
||||
public searchBarTextDidChange(searchBar: UISearchBar, searchText: string) {
|
||||
this._owner._onPropertyChangedFromNative(common.SearchBar.textProperty, searchText);
|
||||
let owner = this._owner.get();
|
||||
if (!owner) {
|
||||
return;
|
||||
}
|
||||
|
||||
owner._onPropertyChangedFromNative(common.SearchBar.textProperty, searchText);
|
||||
|
||||
// This code is needed since sometimes searchBarCancelButtonClicked is not called!
|
||||
if (searchText === "" && this._searchText !== searchText) {
|
||||
this._owner._emit(common.SearchBar.clearEvent);
|
||||
owner._emit(common.SearchBar.clearEvent);
|
||||
}
|
||||
|
||||
this._searchText = searchText;
|
||||
@@ -82,12 +84,22 @@ class UISearchBarDelegateImpl extends NSObject implements UISearchBarDelegate {
|
||||
|
||||
public searchBarCancelButtonClicked(searchBar: UISearchBar) {
|
||||
searchBar.resignFirstResponder();
|
||||
this._owner._emit(common.SearchBar.clearEvent);
|
||||
let owner = this._owner.get();
|
||||
if (!owner) {
|
||||
return;
|
||||
}
|
||||
|
||||
owner._emit(common.SearchBar.clearEvent);
|
||||
}
|
||||
|
||||
public searchBarSearchButtonClicked(searchBar: UISearchBar) {
|
||||
searchBar.resignFirstResponder();
|
||||
this._owner._emit(common.SearchBar.submitEvent);
|
||||
let owner = this._owner.get();
|
||||
if (!owner) {
|
||||
return;
|
||||
}
|
||||
|
||||
owner._emit(common.SearchBar.submitEvent);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,7 +113,7 @@ export class SearchBar extends common.SearchBar {
|
||||
|
||||
this._ios = new UISearchBar();
|
||||
|
||||
this._delegate = UISearchBarDelegateImpl.new().initWithOwner(this);
|
||||
this._delegate = UISearchBarDelegateImpl.initWithOwner(new WeakRef(this));
|
||||
}
|
||||
|
||||
public onLoaded() {
|
||||
@@ -121,7 +133,7 @@ export class SearchBar extends common.SearchBar {
|
||||
|
||||
get ios(): UISearchBar {
|
||||
return this._ios;
|
||||
}
|
||||
}
|
||||
|
||||
private static findTextField(view: UIView) {
|
||||
for (let i = 0, l = view.subviews.count; i < l; i++) {
|
||||
|
||||
@@ -86,7 +86,7 @@ export class SegmentedBar extends common.SegmentedBar {
|
||||
super();
|
||||
this._ios = UISegmentedControl.new();
|
||||
|
||||
this._selectionHandler = SelectionHandlerImpl.new().initWithOwner(this);
|
||||
this._selectionHandler = SelectionHandlerImpl.initWithOwner(new WeakRef(this));
|
||||
this._ios.addTargetActionForControlEvents(this._selectionHandler, "selected", UIControlEvents.UIControlEventValueChanged);
|
||||
}
|
||||
|
||||
@@ -96,22 +96,23 @@ export class SegmentedBar extends common.SegmentedBar {
|
||||
}
|
||||
|
||||
class SelectionHandlerImpl extends NSObject {
|
||||
static new(): SelectionHandlerImpl {
|
||||
return <SelectionHandlerImpl>super.new();
|
||||
}
|
||||
|
||||
private _owner: SegmentedBar;
|
||||
private _owner: WeakRef<SegmentedBar>;
|
||||
|
||||
public initWithOwner(owner: SegmentedBar): SelectionHandlerImpl {
|
||||
this._owner = owner;
|
||||
return this;
|
||||
public static initWithOwner(owner: WeakRef<SegmentedBar>): SelectionHandlerImpl {
|
||||
let handler = <SelectionHandlerImpl>SelectionHandlerImpl.new();
|
||||
handler._owner = owner;
|
||||
return handler;
|
||||
}
|
||||
|
||||
public selected(sender: UISegmentedControl) {
|
||||
this._owner.selectedIndex = sender.selectedSegmentIndex;
|
||||
let owner = this._owner.get();
|
||||
if (owner) {
|
||||
owner.selectedIndex = sender.selectedSegmentIndex;
|
||||
}
|
||||
}
|
||||
|
||||
public static ObjCExposedMethods = {
|
||||
"selected": { returns: interop.types.void, params: [UISegmentedControl] }
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -25,19 +25,20 @@ function onMaxValuePropertyChanged(data: dependencyObservable.PropertyChangeData
|
||||
global.moduleMerge(common, exports);
|
||||
|
||||
class SliderChangeHandlerImpl extends NSObject {
|
||||
static new(): SliderChangeHandlerImpl {
|
||||
return <SliderChangeHandlerImpl>super.new();
|
||||
|
||||
private _owner: WeakRef<Slider>;
|
||||
|
||||
public static initWithOwner(owner: WeakRef<Slider>): SliderChangeHandlerImpl {
|
||||
let handler = <SliderChangeHandlerImpl>SliderChangeHandlerImpl.new();
|
||||
handler._owner = owner;
|
||||
return handler;
|
||||
}
|
||||
|
||||
private _owner: Slider;
|
||||
|
||||
public initWithOwner(owner: Slider): SliderChangeHandlerImpl {
|
||||
this._owner = owner;
|
||||
return this;
|
||||
}
|
||||
|
||||
public sliderValueChanged(sender: UISlider) {
|
||||
this._owner._onPropertyChangedFromNative(common.Slider.valueProperty, sender.value);
|
||||
let owner = this._owner.get();
|
||||
if (owner) {
|
||||
owner._onPropertyChangedFromNative(common.Slider.valueProperty, sender.value);
|
||||
}
|
||||
}
|
||||
|
||||
public static ObjCExposedMethods = {
|
||||
@@ -57,7 +58,7 @@ export class Slider extends common.Slider {
|
||||
this._ios.minimumValue = 0;
|
||||
this._ios.maximumValue = this.maxValue;
|
||||
|
||||
this._changeHandler = SliderChangeHandlerImpl.new().initWithOwner(this);
|
||||
this._changeHandler = SliderChangeHandlerImpl.initWithOwner(new WeakRef(this));
|
||||
this._ios.addTargetActionForControlEvents(this._changeHandler, "sliderValueChanged", UIControlEvents.UIControlEventValueChanged);
|
||||
}
|
||||
|
||||
|
||||
@@ -13,19 +13,20 @@ function onCheckedPropertyChanged(data: dependencyObservable.PropertyChangeData)
|
||||
global.moduleMerge(common, exports);
|
||||
|
||||
class SwitchChangeHandlerImpl extends NSObject {
|
||||
static new(): SwitchChangeHandlerImpl {
|
||||
return <SwitchChangeHandlerImpl>super.new();
|
||||
}
|
||||
|
||||
private _owner: Switch;
|
||||
private _owner: WeakRef<Switch>;
|
||||
|
||||
public initWithOwner(owner: Switch): SwitchChangeHandlerImpl {
|
||||
this._owner = owner;
|
||||
return this;
|
||||
public static initWithOwner(owner: WeakRef<Switch>): SwitchChangeHandlerImpl {
|
||||
let handler = <SwitchChangeHandlerImpl>SwitchChangeHandlerImpl.new();
|
||||
handler._owner = owner;
|
||||
return handler;
|
||||
}
|
||||
|
||||
public valueChanged(sender: UISwitch) {
|
||||
this._owner._onPropertyChangedFromNative(common.Switch.checkedProperty, sender.on);
|
||||
let owner = this._owner.get();
|
||||
if (owner) {
|
||||
owner._onPropertyChangedFromNative(common.Switch.checkedProperty, sender.on);
|
||||
}
|
||||
}
|
||||
|
||||
public static ObjCExposedMethods = {
|
||||
@@ -41,7 +42,7 @@ export class Switch extends common.Switch {
|
||||
super();
|
||||
this._ios = new UISwitch();
|
||||
|
||||
this._handler = SwitchChangeHandlerImpl.new().initWithOwner(this);
|
||||
this._handler = SwitchChangeHandlerImpl.initWithOwner(new WeakRef(this));
|
||||
this._ios.addTargetActionForControlEvents(this._handler, "valueChanged", UIControlEvents.UIControlEventValueChanged);
|
||||
}
|
||||
|
||||
|
||||
@@ -13,22 +13,21 @@ import color = require("color");
|
||||
global.moduleMerge(common, exports);
|
||||
|
||||
class UITabBarControllerImpl extends UITabBarController {
|
||||
static new(): UITabBarControllerImpl {
|
||||
return <UITabBarControllerImpl>super.new();
|
||||
}
|
||||
|
||||
private _owner: TabView;
|
||||
private _owner: WeakRef<TabView>;
|
||||
|
||||
public initWithOwner(owner: TabView): UITabBarControllerImpl {
|
||||
this._owner = owner;
|
||||
return this;
|
||||
public static initWithOwner(owner: WeakRef<TabView>): UITabBarControllerImpl {
|
||||
let handler = <UITabBarControllerImpl>UITabBarControllerImpl.new();
|
||||
handler._owner = owner;
|
||||
return handler;
|
||||
}
|
||||
|
||||
public viewDidLayoutSubviews(): void {
|
||||
trace.write("TabView.UITabBarControllerClass.viewDidLayoutSubviews();", trace.categories.Debug);
|
||||
super.viewDidLayoutSubviews();
|
||||
if (this._owner.isLoaded) {
|
||||
this._owner._updateLayout();
|
||||
let owner = this._owner.get();
|
||||
if (owner && owner.isLoaded) {
|
||||
owner._updateLayout();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -36,42 +35,42 @@ class UITabBarControllerImpl extends UITabBarController {
|
||||
class UITabBarControllerDelegateImpl extends NSObject implements UITabBarControllerDelegate {
|
||||
public static ObjCProtocols = [UITabBarControllerDelegate];
|
||||
|
||||
static new(): UITabBarControllerDelegateImpl {
|
||||
return <UITabBarControllerDelegateImpl>super.new();
|
||||
}
|
||||
private _owner: WeakRef<TabView>;
|
||||
|
||||
private _owner: TabView;
|
||||
|
||||
public initWithOwner(owner: TabView): UITabBarControllerDelegateImpl {
|
||||
this._owner = owner;
|
||||
return this;
|
||||
public static initWithOwner(owner: WeakRef<TabView>): UITabBarControllerDelegateImpl {
|
||||
let delegate = <UITabBarControllerDelegateImpl>UITabBarControllerDelegateImpl.new();
|
||||
delegate._owner = owner;
|
||||
return delegate;
|
||||
}
|
||||
|
||||
public tabBarControllerDidSelectViewController(tabBarController: UITabBarController, viewController: UIViewController): void {
|
||||
trace.write("TabView.UITabBarControllerDelegateClass.tabBarControllerDidSelectViewController(" + tabBarController + ", " + viewController + ");", trace.categories.Debug);
|
||||
this._owner._onViewControllerShown(viewController);
|
||||
let owner = this._owner.get();
|
||||
if (owner) {
|
||||
owner._onViewControllerShown(viewController);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class UINavigationControllerDelegateImpl extends NSObject implements UINavigationControllerDelegate {
|
||||
public static ObjCProtocols = [UINavigationControllerDelegate];
|
||||
|
||||
static new(): UINavigationControllerDelegateImpl {
|
||||
return <UINavigationControllerDelegateImpl>super.new();
|
||||
}
|
||||
private _owner: WeakRef<TabView>;
|
||||
|
||||
private _owner: TabView;
|
||||
|
||||
public initWithOwner(owner: TabView): UINavigationControllerDelegateImpl {
|
||||
this._owner = owner;
|
||||
return this;
|
||||
public static initWithOwner(owner: WeakRef<TabView>): UINavigationControllerDelegateImpl {
|
||||
let delegate = <UINavigationControllerDelegateImpl>UINavigationControllerDelegateImpl.new();
|
||||
delegate._owner = owner;
|
||||
return delegate;
|
||||
}
|
||||
|
||||
navigationControllerDidShowViewControllerAnimated(navigationController: UINavigationController, viewController: UIViewController, animated: boolean): void {
|
||||
trace.write("TabView.UINavigationControllerDelegateClass.navigationControllerDidShowViewControllerAnimated(" + navigationController + ", " + viewController + ", " + animated + ");", trace.categories.Debug);
|
||||
// We don't need Edit button in More screen.
|
||||
navigationController.navigationBar.topItem.rightBarButtonItem = null;
|
||||
this._owner._onViewControllerShown(viewController);
|
||||
let owner = this._owner.get();
|
||||
if (owner) {
|
||||
owner._onViewControllerShown(viewController);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,11 +116,9 @@ export class TabView extends common.TabView {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this._ios = UITabBarControllerImpl.new().initWithOwner(this);
|
||||
|
||||
this._delegate = UITabBarControllerDelegateImpl.new().initWithOwner(this);
|
||||
|
||||
this._moreNavigationControllerDelegate = UINavigationControllerDelegateImpl.new().initWithOwner(this);
|
||||
this._ios = UITabBarControllerImpl.initWithOwner(new WeakRef(this));
|
||||
this._delegate = UITabBarControllerDelegateImpl.initWithOwner(new WeakRef(this));
|
||||
this._moreNavigationControllerDelegate = UINavigationControllerDelegateImpl.initWithOwner(new WeakRef(this));
|
||||
//This delegate is set on the last line of _addTabs method.
|
||||
}
|
||||
|
||||
|
||||
@@ -16,85 +16,99 @@ global.moduleMerge(common, exports);
|
||||
class UITextFieldDelegateImpl extends NSObject implements UITextFieldDelegate {
|
||||
public static ObjCProtocols = [UITextFieldDelegate];
|
||||
|
||||
static new(): UITextFieldDelegateImpl {
|
||||
return <UITextFieldDelegateImpl>super.new();
|
||||
private _owner: WeakRef<TextField>;
|
||||
private firstEdit: boolean;
|
||||
|
||||
public static initWithOwner(owner: WeakRef<TextField>): UITextFieldDelegateImpl {
|
||||
let delegate = <UITextFieldDelegateImpl>UITextFieldDelegateImpl.new();
|
||||
delegate._owner = owner;
|
||||
return delegate;
|
||||
}
|
||||
|
||||
private _owner: TextField;
|
||||
private firstEdit: boolean;
|
||||
|
||||
public initWithOwner(owner: TextField): UITextFieldDelegateImpl {
|
||||
this._owner = owner;
|
||||
return this;
|
||||
}
|
||||
|
||||
public textFieldShouldBeginEditing(textField: UITextField): boolean {
|
||||
this.firstEdit = true;
|
||||
return this._owner.editable;
|
||||
let owner = this._owner.get();
|
||||
if (owner) {
|
||||
return owner.editable;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public textFieldDidEndEditing(textField: UITextField) {
|
||||
if (this._owner.updateTextTrigger === enums.UpdateTextTrigger.focusLost) {
|
||||
this._owner._onPropertyChangedFromNative(textBase.TextBase.textProperty, textField.text);
|
||||
}
|
||||
let owner = this._owner.get();
|
||||
if (owner) {
|
||||
if (owner.updateTextTrigger === enums.UpdateTextTrigger.focusLost) {
|
||||
owner._onPropertyChangedFromNative(textBase.TextBase.textProperty, textField.text);
|
||||
}
|
||||
|
||||
this._owner.dismissSoftInput();
|
||||
owner.dismissSoftInput();
|
||||
}
|
||||
}
|
||||
|
||||
public textFieldShouldClear(textField: UITextField) {
|
||||
this.firstEdit = false;
|
||||
this._owner._onPropertyChangedFromNative(textBase.TextBase.textProperty, "");
|
||||
let owner = this._owner.get();
|
||||
if (owner) {
|
||||
owner._onPropertyChangedFromNative(textBase.TextBase.textProperty, "");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public textFieldShouldReturn(textField: UITextField): boolean {
|
||||
// Called when the user presses the return button.
|
||||
this._owner.dismissSoftInput();
|
||||
this._owner.notify({ eventName: TextField.returnPressEvent, object: this._owner });
|
||||
let owner = this._owner.get();
|
||||
if (owner) {
|
||||
owner.dismissSoftInput();
|
||||
owner.notify({ eventName: TextField.returnPressEvent, object: owner });
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public textFieldShouldChangeCharactersInRangeReplacementString(textField: UITextField, range: NSRange, replacementString: string): boolean {
|
||||
if (this._owner.updateTextTrigger === enums.UpdateTextTrigger.textChanged) {
|
||||
if (textField.secureTextEntry && this.firstEdit) {
|
||||
this._owner._onPropertyChangedFromNative(textBase.TextBase.textProperty, replacementString);
|
||||
}
|
||||
else {
|
||||
var newText = NSString.alloc().initWithString(textField.text).stringByReplacingCharactersInRangeWithString(range, replacementString);
|
||||
this._owner._onPropertyChangedFromNative(textBase.TextBase.textProperty, newText);
|
||||
let owner = this._owner.get();
|
||||
if (owner) {
|
||||
if (owner.updateTextTrigger === enums.UpdateTextTrigger.textChanged) {
|
||||
if (textField.secureTextEntry && this.firstEdit) {
|
||||
owner._onPropertyChangedFromNative(textBase.TextBase.textProperty, replacementString);
|
||||
}
|
||||
else {
|
||||
let newText = NSString.alloc().initWithString(textField.text).stringByReplacingCharactersInRangeWithString(range, replacementString);
|
||||
owner._onPropertyChangedFromNative(textBase.TextBase.textProperty, newText);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.firstEdit = false;
|
||||
|
||||
this.firstEdit = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class UITextFieldImpl extends UITextField {
|
||||
static new(): UITextFieldImpl {
|
||||
return <UITextFieldImpl>super.new();
|
||||
}
|
||||
|
||||
private _owner: TextField;
|
||||
private _owner: WeakRef<TextField>;
|
||||
|
||||
public initWithOwner(owner: TextField): UITextFieldImpl {
|
||||
this._owner = owner;
|
||||
return this;
|
||||
public static initWithOwner(owner: WeakRef<TextField>): UITextFieldImpl {
|
||||
let handler = <UITextFieldImpl>UITextFieldImpl.new();
|
||||
handler._owner = owner;
|
||||
return handler;
|
||||
}
|
||||
|
||||
private _getTextRectForBounds(bounds: CGRect): CGRect {
|
||||
if (!this._owner) {
|
||||
let owner = this._owner ? this._owner.get() : null;
|
||||
|
||||
if (!owner) {
|
||||
return bounds;
|
||||
}
|
||||
|
||||
return CGRectMake(
|
||||
this._owner.borderWidth + this._owner.style.paddingLeft,
|
||||
this._owner.borderWidth + this._owner.style.paddingTop,
|
||||
bounds.size.width - (this._owner.borderWidth + this._owner.style.paddingLeft + this._owner.style.paddingRight + this._owner.borderWidth),
|
||||
bounds.size.height - (this._owner.borderWidth + this._owner.style.paddingTop + this._owner.style.paddingBottom + this._owner.borderWidth)
|
||||
);
|
||||
let size = bounds.size;
|
||||
return CGRectMake(owner.borderWidth + owner.style.paddingLeft, owner.borderWidth + owner.style.paddingTop,
|
||||
size.width - (owner.borderWidth + owner.style.paddingLeft + owner.style.paddingRight + owner.borderWidth),
|
||||
size.height - (owner.borderWidth + owner.style.paddingTop + owner.style.paddingBottom + owner.borderWidth)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public textRectForBounds(bounds: CGRect): CGRect {
|
||||
return this._getTextRectForBounds(bounds);
|
||||
}
|
||||
@@ -111,8 +125,8 @@ export class TextField extends common.TextField {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this._ios = UITextFieldImpl.new().initWithOwner(this);
|
||||
this._delegate = UITextFieldDelegateImpl.new().initWithOwner(this);
|
||||
this._ios = UITextFieldImpl.initWithOwner(new WeakRef(this));
|
||||
this._delegate = UITextFieldDelegateImpl.initWithOwner(new WeakRef(this));
|
||||
}
|
||||
|
||||
public onLoaded() {
|
||||
|
||||
@@ -38,7 +38,7 @@ export class TimePicker extends common.TimePicker {
|
||||
this._ios = new UIDatePicker();
|
||||
this._ios.datePickerMode = UIDatePickerMode.UIDatePickerModeTime;
|
||||
|
||||
this._changeHandler = UITimePickerChangeHandlerImpl.new().initWithOwner(this);
|
||||
this._changeHandler = UITimePickerChangeHandlerImpl.initWithOwner(new WeakRef(this));
|
||||
this._ios.addTargetActionForControlEvents(this._changeHandler, "valueChanged", UIControlEvents.UIControlEventValueChanged);
|
||||
}
|
||||
|
||||
@@ -48,30 +48,33 @@ export class TimePicker extends common.TimePicker {
|
||||
}
|
||||
|
||||
class UITimePickerChangeHandlerImpl extends NSObject {
|
||||
static new(): UITimePickerChangeHandlerImpl {
|
||||
return <UITimePickerChangeHandlerImpl>super.new();
|
||||
}
|
||||
|
||||
private _owner: TimePicker;
|
||||
private _owner: WeakRef<TimePicker>;
|
||||
|
||||
public initWithOwner(owner: TimePicker): UITimePickerChangeHandlerImpl {
|
||||
this._owner = owner;
|
||||
return this;
|
||||
public static initWithOwner(owner: WeakRef<TimePicker>): UITimePickerChangeHandlerImpl {
|
||||
let handler = <UITimePickerChangeHandlerImpl>UITimePickerChangeHandlerImpl.new();
|
||||
handler._owner = owner;
|
||||
return handler;
|
||||
}
|
||||
|
||||
public valueChanged(sender: UIDatePicker) {
|
||||
var comps = NSCalendar.currentCalendar().componentsFromDate(NSCalendarUnit.NSCalendarUnitHour | NSCalendarUnit.NSCalendarUnitMinute, sender.date);
|
||||
|
||||
if (comps.hour !== this._owner.hour) {
|
||||
this._owner._onPropertyChangedFromNative(common.TimePicker.hourProperty, comps.hour);
|
||||
let owner = this._owner.get();
|
||||
if (!owner) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (comps.minute !== this._owner.minute) {
|
||||
this._owner._onPropertyChangedFromNative(common.TimePicker.minuteProperty, comps.minute);
|
||||
var comps = NSCalendar.currentCalendar().componentsFromDate(NSCalendarUnit.NSCalendarUnitHour | NSCalendarUnit.NSCalendarUnitMinute, sender.date);
|
||||
|
||||
if (comps.hour !== owner.hour) {
|
||||
owner._onPropertyChangedFromNative(common.TimePicker.hourProperty, comps.hour);
|
||||
}
|
||||
|
||||
if (comps.minute !== owner.minute) {
|
||||
owner._onPropertyChangedFromNative(common.TimePicker.minuteProperty, comps.minute);
|
||||
}
|
||||
}
|
||||
|
||||
public static ObjCExposedMethods = {
|
||||
'valueChanged': { returns: interop.types.void, params: [UIDatePicker] }
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -6,21 +6,19 @@ global.moduleMerge(common, exports);
|
||||
class UIWebViewDelegateImpl extends NSObject implements UIWebViewDelegate {
|
||||
public static ObjCProtocols = [UIWebViewDelegate];
|
||||
|
||||
static new(): UIWebViewDelegateImpl {
|
||||
return <UIWebViewDelegateImpl>super.new();
|
||||
}
|
||||
private _owner: WeakRef<WebView>;
|
||||
|
||||
private _owner: WebView;
|
||||
|
||||
public initWithOwner(owner: WebView): UIWebViewDelegateImpl {
|
||||
this._owner = owner;
|
||||
return this;
|
||||
public static initWithOwner(owner: WeakRef<WebView>): UIWebViewDelegateImpl {
|
||||
let delegate = <UIWebViewDelegateImpl>UIWebViewDelegateImpl.new();
|
||||
delegate._owner = owner;
|
||||
return delegate;
|
||||
}
|
||||
|
||||
public webViewShouldStartLoadWithRequestNavigationType(webView: UIWebView, request: NSURLRequest, navigationType: number) {
|
||||
if (request.URL) {
|
||||
let owner = this._owner.get();
|
||||
if (owner && request.URL) {
|
||||
trace.write("UIWebViewDelegateClass.webViewShouldStartLoadWithRequestNavigationType(" + request.URL.absoluteString + ", " + navigationType + ")", trace.categories.Debug);
|
||||
this._owner._onLoadStarted(request.URL.absoluteString);
|
||||
owner._onLoadStarted(request.URL.absoluteString);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -32,17 +30,25 @@ class UIWebViewDelegateImpl extends NSObject implements UIWebViewDelegate {
|
||||
|
||||
public webViewDidFinishLoad(webView: UIWebView) {
|
||||
trace.write("UIWebViewDelegateClass.webViewDidFinishLoad(" + webView.request.URL + ")", trace.categories.Debug);
|
||||
this._owner._onLoadFinished(webView.request.URL.absoluteString);
|
||||
let owner = this._owner.get();
|
||||
if (owner) {
|
||||
owner._onLoadFinished(webView.request.URL.absoluteString);
|
||||
}
|
||||
}
|
||||
|
||||
public webViewDidFailLoadWithError(webView: UIWebView, error: NSError) {
|
||||
var url = this._owner.url;
|
||||
if (webView.request && webView.request.URL) {
|
||||
url = webView.request.URL.absoluteString;
|
||||
}
|
||||
let owner = this._owner.get();
|
||||
if (owner) {
|
||||
var url = owner.url;
|
||||
if (webView.request && webView.request.URL) {
|
||||
url = webView.request.URL.absoluteString;
|
||||
}
|
||||
|
||||
trace.write("UIWebViewDelegateClass.webViewDidFailLoadWithError(" + error.localizedDescription + ")", trace.categories.Debug);
|
||||
this._owner._onLoadFinished(url, error.localizedDescription);
|
||||
trace.write("UIWebViewDelegateClass.webViewDidFailLoadWithError(" + error.localizedDescription + ")", trace.categories.Debug);
|
||||
if (owner) {
|
||||
owner._onLoadFinished(url, error.localizedDescription);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +60,7 @@ export class WebView extends common.WebView {
|
||||
super();
|
||||
|
||||
this._ios = new UIWebView();
|
||||
this._delegate = UIWebViewDelegateImpl.new().initWithOwner(this);
|
||||
this._delegate = UIWebViewDelegateImpl.initWithOwner(new WeakRef(this));
|
||||
}
|
||||
|
||||
public onLoaded() {
|
||||
|
||||
Reference in New Issue
Block a user