Skip to content

UITableView Based Extension for iOS

Extension can also be built based on UITableViewCell for iOS in Typescript, and will be added into Form Cell container or Sectioned Table by Mobile Development Kit. In this way, Extension can adapt its layout size as a cell in UITableView in iOS using systemLayoutSizeFitting interface of UITableViewCell.

To use this approach, in extension's Typescript, a handler implementing an interface from ExtensionTableViewCellHandler for iOS is needed. And an extension is required to be defined based on UITableViewCell. The handler handles the registration and configuration of the extension as a UITableViewCell to Form Cell Container or Sectioned Table from Mobile Development Kit.

Basic Implementation Structure

Example implementations for ExtensionTableViewCellHandler and UITableViewCell extension:

interface ExtensionTableViewCellHandler extends NSObjectProtocol {
  getReuseIdentifier(): string;
  registerCellTo(tableView: UITableView);
  configureReusableCell(tableViewCell: UITableViewCell);
}
declare var ExtensionTableViewCellHandler: {
  prototype: ExtensionTableViewCellHandler;
};

class MyExtension extends NSObject implements ExtensionTableViewCellHandler {
  public static ObjCProtocols = [ExtensionTableViewCellHandler];
  public static reuseIdentifier: string = "MyExtensionFormCell";

  public getReuseIdentifier(): string {
    return MyExtension.reuseIdentifier;
  }

  public registerCellTo(tableView: UITableView) {
    tableView.registerClassForCellReuseIdentifier(MyExtensionTableViewCell.class(), MyExtension.reuseIdentifier);
  }

  public configureReusableCell(tableViewCell: UITableViewCell) {
    let cell = <MyExtensionTableViewCell> tableViewCell;
  }
}

class MyExtensionTableViewCell extends UITableViewCell {
  private _extensionView;

  initWithStyleReuseIdentifier(style: UITableViewCellStyle, reuseIdentifier: string): this {
    const cell = <this>super.initWithStyleReuseIdentifier(style, reuseIdentifier);
    this.setup();
    return cell;
  }

  initWithCoder(coder: NSCoder): this {
    const cell = <this>super.initWithCoder(coder);
    this.setup();
    return cell;
  }

  public setup() {
    //Create the extension view
    this.contentView.addSubview(this._extensionView);
  }

  systemLayoutSizeFittingSizeWithHorizontalFittingPriorityVerticalFittingPriority(targetSize: CGSize, horizontalFittingPriority: number, verticalFittingPriority: number): CGSize {
    this.layoutIfNeeded();
    let size = this._extensionView.systemLayoutSizeFittingSizeWithHorizontalFittingPriorityVerticalFittingPriority(this._extensionView.bounds.size, UILayoutPriorityRequired, UILayoutPriorityFittingSizeLevel);
    let calcSize = CGSizeMake(targetSize.width, size.height);

    return calcSize;
  }
}

export class MyExtensionControl extends View {
  private _control;

  public constructor(context: any) {
    super();
    this.createNativeView();
  }

  /**
   * Creates new native controls.
   */
  public createNativeView(): Object {
    this._control = <MyExtension> MyExtension.new();

    //store the native view
    this.setNativeView(this._control);

    //return the stack view
    return this._control;
  }

  /**
   * Initializes properties/listeners of the native view.
   */
  initNativeView(): void {
    super.initNativeView();
  }

  /**
   * Clean up references to the native view and resets nativeView to its original state.
   * If you have changed nativeView in some other way except through setNative callbacks
   * you have a chance here to revert it back to its original state
   * so that it could be reused later.
   */
  disposeNativeView(): void {
  }

  //Must return the native view of the control for FormCell and Section Extension
  public getView(): any {
    return this._control;
  }
}

Last update: June 5, 2024