Repository: NativeScript/NativeScript
File: ui/html-view/html-view.ios.ts (TypeScript)

Code before:
﻿import common = require("ui/html-view/html-view-common");
import definition = require("ui/html-view");
import dependencyObservable = require("ui/core/dependency-observable");
import proxy = require("ui/core/proxy");
import utils = require("utils/utils");
import types = require("utils/types");
import viewModule = require("ui/core/view");

function onHtmlPropertyChanged(data: dependencyObservable.PropertyChangeData) {
    var view = <HtmlView>data.object;
    if (!view.ios) {
        return;
    }

    if (types.isString(data.newValue)) {
        var htmlString = NSString.stringWithString(data.newValue);
        var nsData = htmlString.dataUsingEncoding(NSUnicodeStringEncoding);
        view.ios.attributedText = NSAttributedString.alloc().initWithDataOptionsDocumentAttributesError(nsData, <any>{ [NSDocumentTypeDocumentAttribute]: NSHTMLTextDocumentType }, null);
    } else {
        view.ios.attributedText = NSAttributedString.new();
    }
}

// register the setNativeValue callback
(<proxy.PropertyMetadata>common.HtmlView.htmlProperty.metadata).onSetNativeValue = onHtmlPropertyChanged;

global.moduleMerge(common, exports);

export class HtmlView extends common.HtmlView {
    private _ios: UITextView;

    constructor(options?: definition.Options) {
        super(options);
        this._ios = UITextView.new();

        this._ios.scrollEnabled = false;
        this._ios.editable = false;
        this._ios.selectable = true;
        this._ios.userInteractionEnabled  = true;
        this._ios.dataDetectorTypes = 255; // Future Proof this; valid max in iOS is currently 15; however ALL = MAX UNSIGNED INT which isn't valid in JavaScript
    }

    get ios(): UITextView {
        return this._ios;
    }

    get _nativeView(): UITextView {
        return this._ios;
    }

    public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number): void {
        var nativeView = this._nativeView;
        if (nativeView) {

            var width = utils.layout.getMeasureSpecSize(widthMeasureSpec);
            var widthMode = utils.layout.getMeasureSpecMode(widthMeasureSpec);

            var height = utils.layout.getMeasureSpecSize(heightMeasureSpec);
            var heightMode = utils.layout.getMeasureSpecMode(heightMeasureSpec);

            if (widthMode === utils.layout.UNSPECIFIED) {
                width = Number.POSITIVE_INFINITY;
            }

            if (heightMode === utils.layout.UNSPECIFIED) {
                height = Number.POSITIVE_INFINITY;
            }

            var nativeSize = nativeView.sizeThatFits(CGSizeMake(width, height));
            var labelWidth = nativeSize.width;

            labelWidth = Math.min(labelWidth, width);

            var measureWidth = Math.max(labelWidth, this.minWidth);
            var measureHeight = Math.max(nativeSize.height, this.minHeight);

            var widthAndState = viewModule.View.resolveSizeAndState(measureWidth, width, widthMode, 0);
            var heightAndState = viewModule.View.resolveSizeAndState(measureHeight, height, heightMode, 0);

            this.setMeasuredDimension(widthAndState, heightAndState);
        }
    }
} 

Review comment (performance):
The code readability should be the one we should optimize for because this is not a compute intensive code :smile:  

Regarding the question itself we should ask someone with deeper knowledge about iOS runtime. @fealebenpae can you elaborate if there will be any marshalling penalty if the enum is used instead of the integer value?


Code after:
﻿import common = require("ui/html-view/html-view-common");
import definition = require("ui/html-view");
import dependencyObservable = require("ui/core/dependency-observable");
import proxy = require("ui/core/proxy");
import utils = require("utils/utils");
import types = require("utils/types");
import viewModule = require("ui/core/view");

function onHtmlPropertyChanged(data: dependencyObservable.PropertyChangeData) {
    var view = <HtmlView>data.object;
    if (!view.ios) {
        return;
    }

    if (types.isString(data.newValue)) {
        var htmlString = NSString.stringWithString(data.newValue);
        var nsData = htmlString.dataUsingEncoding(NSUnicodeStringEncoding);
        view.ios.attributedText = NSAttributedString.alloc().initWithDataOptionsDocumentAttributesError(nsData, <any>{ [NSDocumentTypeDocumentAttribute]: NSHTMLTextDocumentType }, null);
    } else {
        view.ios.attributedText = NSAttributedString.new();
    }
}

// register the setNativeValue callback
(<proxy.PropertyMetadata>common.HtmlView.htmlProperty.metadata).onSetNativeValue = onHtmlPropertyChanged;

global.moduleMerge(common, exports);

export class HtmlView extends common.HtmlView {
    private _ios: UITextView;

    constructor(options?: definition.Options) {
        super(options);
        this._ios = UITextView.new();

        this._ios.scrollEnabled = false;
        this._ios.editable = false;
        this._ios.selectable = true;
        this._ios.userInteractionEnabled  = true;
        this._ios.dataDetectorTypes = UIDataDetectorTypes.UIDataDetectorTypeAll;
    }

    get ios(): UITextView {
        return this._ios;
    }

    get _nativeView(): UITextView {
        return this._ios;
    }

    public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number): void {
        var nativeView = this._nativeView;
        if (nativeView) {

            var width = utils.layout.getMeasureSpecSize(widthMeasureSpec);
            var widthMode = utils.layout.getMeasureSpecMode(widthMeasureSpec);

            var height = utils.layout.getMeasureSpecSize(heightMeasureSpec);
            var heightMode = utils.layout.getMeasureSpecMode(heightMeasureSpec);

            if (widthMode === utils.layout.UNSPECIFIED) {
                width = Number.POSITIVE_INFINITY;
            }

            if (heightMode === utils.layout.UNSPECIFIED) {
                height = Number.POSITIVE_INFINITY;
            }

            var nativeSize = nativeView.sizeThatFits(CGSizeMake(width, height));
            var labelWidth = nativeSize.width;

            labelWidth = Math.min(labelWidth, width);

            var measureWidth = Math.max(labelWidth, this.minWidth);
            var measureHeight = Math.max(nativeSize.height, this.minHeight);

            var widthAndState = viewModule.View.resolveSizeAndState(measureWidth, width, widthMode, 0);
            var heightAndState = viewModule.View.resolveSizeAndState(measureHeight, height, heightMode, 0);

            this.setMeasuredDimension(widthAndState, heightAndState);
        }
    }
}