Example of extending UIViewController in Angular 2 and Nativescript


#1

Hey All,

I am using a 3rd-party Cocoapod plugin in my Nativescript-Angular app called SwiftyCam. The documentation says I need to create a subclass of the UIViewController and replace the declaration with the SwiftyCamController:

SwiftyCam is a drop-in convenience framework. To create a Camera instance, create a new UIViewController subclass. Replace the UIViewController subclass declaration with SwiftyCamViewController:

class MyCameraViewController : SwiftyCamViewController

There is an example for sublcassing in the Nativescript docs, but it only deals with javascript:

http://docs.nativescript.org/runtimes/ios/how-to/ObjC-Subclassing

Let’s say I have a HomePageComponent class, how would I extend or add this SwiftyCamViewController to the UIViewController?


How could I make the camera with customized button overlaying the camera view?
#2

Before you spend time implementing it, generate the typescript definitions and see if it’s classes are even recognized by the runtime.

In your project root:
TNS_TYPESCRIPT_DECLARATIONS_PATH="$(pwd)/typingz" tns build ios
then look for SwifyCam in typingz-x64 folder and when you do paste them here and I’ll show you how to subclass it.


#3
{ Module:
   { FullName: 'SwiftyCam',
     IsPartOfFramework: true,
     IsSystemModule: false,
     Libraries: [ { Library: 'SwiftyCam', IsFramework: true } ] },
  Items:
   [ { Name: '_TtC9SwiftyCam15SwiftyCamButton',
       JsName: 'SwiftyCamButton',
       Filename: '/Users/tskweres/Dev/Catch/platforms/ios/build/device/SwiftyCam.framework/Headers/SwiftyCam-Swift.h',
       Module:
        { FullName: 'SwiftyCam.Swift',
          IsPartOfFramework: true,
          IsSystemModule: false,
          Libraries: null },
       Flags: [ 'IsIosAppExtensionAvailable' ],
       Type: 'Interface',
       InstanceMethods: null,
       StaticMethods: null,
       InstanceProperties: null,
       StaticProperties: null,
       Protocols: null,
       Base: 'UIButton' },
     { Name: 'SwiftyCamVersionNumber',
       JsName: 'SwiftyCamVersionNumber',
       Filename: '/Users/tskweres/Dev/Catch/platforms/ios/build/device/SwiftyCam.framework/Headers/SwiftyCam-umbrella.h',
       Module:
        { FullName: 'SwiftyCam',
          IsPartOfFramework: true,
          IsSystemModule: false,
          Libraries: [ { Library: 'SwiftyCam', IsFramework: true } ] },
       Flags: [ 'IsIosAppExtensionAvailable' ],
       Type: 'Var',
       Signature: { Type: 'Double' } },
     { Name: 'SwiftyCamVersionString',
       JsName: 'SwiftyCamVersionString',
       Filename: '/Users/tskweres/Dev/Catch/platforms/ios/build/device/SwiftyCam.framework/Headers/SwiftyCam-umbrella.h',
       Module:
        { FullName: 'SwiftyCam',
          IsPartOfFramework: true,
          IsSystemModule: false,
          Libraries: [ { Library: 'SwiftyCam', IsFramework: true } ] },
       Flags: [ 'IsIosAppExtensionAvailable' ],
       Type: 'Var',
       Signature: { Type: 'IncompleteArray', ArrayType: { Type: 'UChar' } } },
     { Name: '_TtC9SwiftyCam23SwiftyCamViewController',
       JsName: 'SwiftyCamViewController',
       Filename: '/Users/tskweres/Dev/Catch/platforms/ios/build/device/SwiftyCam.framework/Headers/SwiftyCam-Swift.h',
       Module:
        { FullName: 'SwiftyCam.Swift',
          IsPartOfFramework: true,
          IsSystemModule: false,
          Libraries: null },
       Flags: [ 'IsIosAppExtensionAvailable' ],
       Type: 'Interface',
       InstanceMethods:
        [ { Name: 'startVideoRecording',
            JsName: 'startVideoRecording',
            Filename: '/Users/tskweres/Dev/Catch/platforms/ios/build/device/SwiftyCam.framework/Headers/SwiftyCam-Swift.h',
            Module:
             { FullName: 'SwiftyCam.Swift',
               IsPartOfFramework: true,
               IsSystemModule: false,
               Libraries: null },
            Flags: [ 'IsIosAppExtensionAvailable' ],
            Type: 'Method',
            Signature: [ { Type: 'Void' } ] },
          { Name: 'stopVideoRecording',
            JsName: 'stopVideoRecording',
            Filename: '/Users/tskweres/Dev/Catch/platforms/ios/build/device/SwiftyCam.framework/Headers/SwiftyCam-Swift.h',
            Module:
             { FullName: 'SwiftyCam.Swift',
               IsPartOfFramework: true,
               IsSystemModule: false,
               Libraries: null },
            Flags: [ 'IsIosAppExtensionAvailable' ],
            Type: 'Method',
            Signature: [ { Type: 'Void' } ] },
          { Name: 'switchCamera',
            JsName: 'switchCamera',
            Filename: '/Users/tskweres/Dev/Catch/platforms/ios/build/device/SwiftyCam.framework/Headers/SwiftyCam-Swift.h',
            Module:
             { FullName: 'SwiftyCam.Swift',
               IsPartOfFramework: true,
               IsSystemModule: false,
               Libraries: null },
            Flags: [ 'IsIosAppExtensionAvailable' ],
            Type: 'Method',
            Signature: [ { Type: 'Void' } ] },
          { Name: 'takePhoto',
            JsName: 'takePhoto',
            Filename: '/Users/tskweres/Dev/Catch/platforms/ios/build/device/SwiftyCam.framework/Headers/SwiftyCam-Swift.h',
            Module:
             { FullName: 'SwiftyCam.Swift',
               IsPartOfFramework: true,
               IsSystemModule: false,
               Libraries: null },
            Flags: [ 'IsIosAppExtensionAvailable' ],
            Type: 'Method',
            Signature: [ { Type: 'Void' } ] },
          { Name: 'buttonDidBeginLongPress',
            JsName: 'buttonDidBeginLongPress',
            Filename: '/Users/tskweres/Dev/Catch/platforms/ios/build/device/SwiftyCam.framework/Headers/SwiftyCam-Swift.h',
            Module:
             { FullName: 'SwiftyCam.Swift',
               IsPartOfFramework: true,
               IsSystemModule: false,
               Libraries: null },
            Flags: [ 'IsIosAppExtensionAvailable' ],
            Type: 'Method',
            Signature: [ { Type: 'Void' } ] },
          { Name: 'buttonDidEndLongPress',
            JsName: 'buttonDidEndLongPress',
            Filename: '/Users/tskweres/Dev/Catch/platforms/ios/build/device/SwiftyCam.framework/Headers/SwiftyCam-Swift.h',
            Module:
             { FullName: 'SwiftyCam.Swift',
               IsPartOfFramework: true,
               IsSystemModule: false,
               Libraries: null },
            Flags: [ 'IsIosAppExtensionAvailable' ],
            Type: 'Method',
            Signature: [ { Type: 'Void' } ] },
          { Name: 'buttonWasTapped',
            JsName: 'buttonWasTapped',
            Filename: '/Users/tskweres/Dev/Catch/platforms/ios/build/device/SwiftyCam.framework/Headers/SwiftyCam-Swift.h',
            Module:
             { FullName: 'SwiftyCam.Swift',
               IsPartOfFramework: true,
               IsSystemModule: false,
               Libraries: null },
            Flags: [ 'IsIosAppExtensionAvailable' ],
            Type: 'Method',
            Signature: [ { Type: 'Void' } ] },
          { Name: 'longPressDidReachMaximumDuration',
            JsName: 'longPressDidReachMaximumDuration',
            Filename: '/Users/tskweres/Dev/Catch/platforms/ios/build/device/SwiftyCam.framework/Headers/SwiftyCam-Swift.h',
            Module:
             { FullName: 'SwiftyCam.Swift',
               IsPartOfFramework: true,
               IsSystemModule: false,
               Libraries: null },
            Flags: [ 'IsIosAppExtensionAvailable' ],
            Type: 'Method',
            Signature: [ { Type: 'Void' } ] },
          { Name: 'setMaxiumVideoDuration',
            JsName: 'setMaxiumVideoDuration',
            Filename: '/Users/tskweres/Dev/Catch/platforms/ios/build/device/SwiftyCam.framework/Headers/SwiftyCam-Swift.h',
            Module:
             { FullName: 'SwiftyCam.Swift',
               IsPartOfFramework: true,
               IsSystemModule: false,
               Libraries: null },
            Flags: [ 'IsIosAppExtensionAvailable' ],
            Type: 'Method',
            Signature: [ { Type: 'Double' } ] } ],
       StaticMethods: null,
       InstanceProperties:
        [ { Name: 'allowBackgroundAudio',
            JsName: 'allowBackgroundAudio',
            Filename: '/Users/tskweres/Dev/Catch/platforms/ios/build/device/SwiftyCam.framework/Headers/SwiftyCam-Swift.h',
            Module:
             { FullName: 'SwiftyCam.Swift',
               IsPartOfFramework: true,
               IsSystemModule: false,
               Libraries: null },
            Flags: [ 'IsIosAppExtensionAvailable' ],
            Type: 'Property',
            Getter:
             { Name: 'allowBackgroundAudio',
               JsName: 'allowBackgroundAudio',
               Filename: '/Users/tskweres/Dev/Catch/platforms/ios/build/device/SwiftyCam.framework/Headers/SwiftyCam-Swift.h',
               Module:
                { FullName: 'SwiftyCam.Swift',
                  IsPartOfFramework: true,
                  IsSystemModule: false,
                  Libraries: null },
               Flags: [ 'IsIosAppExtensionAvailable' ],
               Type: 'Method',
               Signature: [ { Type: 'Bool' } ] },
            Setter:
             { Name: 'setAllowBackgroundAudio:',
               JsName: 'setAllowBackgroundAudio',
               Filename: '/Users/tskweres/Dev/Catch/platforms/ios/build/device/SwiftyCam.framework/Headers/SwiftyCam-Swift.h',
               Module:
                { FullName: 'SwiftyCam.Swift',
                  IsPartOfFramework: true,
                  IsSystemModule: false,
                  Libraries: null },
               Flags: [ 'IsIosAppExtensionAvailable' ],
               Type: 'Method',
               Signature: [ { Type: 'Void' }, { Type: 'Bool' } ] } },
          { Name: 'doubleTapCameraSwitch',
            JsName: 'doubleTapCameraSwitch',
            Filename: '/Users/tskweres/Dev/Catch/platforms/ios/build/device/SwiftyCam.framework/Headers/SwiftyCam-Swift.h',
            Module:
             { FullName: 'SwiftyCam.Swift',
               IsPartOfFramework: true,
               IsSystemModule: false,
               Libraries: null },
            Flags: [ 'IsIosAppExtensionAvailable' ],
            Type: 'Property',
            Getter:
             { Name: 'doubleTapCameraSwitch',
               JsName: 'doubleTapCameraSwitch',
               Filename: '/Users/tskweres/Dev/Catch/platforms/ios/build/device/SwiftyCam.framework/Headers/SwiftyCam-Swift.h',
               Module:
                { FullName: 'SwiftyCam.Swift',
                  IsPartOfFramework: true,
                  IsSystemModule: false,
                  Libraries: null },
               Flags: [ 'IsIosAppExtensionAvailable' ],
               Type: 'Method',
               Signature: [ { Type: 'Bool' } ] },
            Setter:
             { Name: 'setDoubleTapCameraSwitch:',
               JsName: 'setDoubleTapCameraSwitch',
               Filename: '/Users/tskweres/Dev/Catch/platforms/ios/build/device/SwiftyCam.framework/Headers/SwiftyCam-Swift.h',
               Module:
                { FullName: 'SwiftyCam.Swift',
                  IsPartOfFramework: true,
                  IsSystemModule: false,
                  Libraries: null },
               Flags: [ 'IsIosAppExtensionAvailable' ],
               Type: 'Method',
               Signature: [ { Type: 'Void' }, { Type: 'Bool' } ] } },
          { Name: 'flashEnabled',
            JsName: 'flashEnabled',
            Filename: '/Users/tskweres/Dev/Catch/platforms/ios/build/device/SwiftyCam.framework/Headers/SwiftyCam-Swift.h',
            Module:
             { FullName: 'SwiftyCam.Swift',
               IsPartOfFramework: true,
               IsSystemModule: false,
               Libraries: null },
            Flags: [ 'IsIosAppExtensionAvailable' ],
            Type: 'Property',
            Getter:
             { Name: 'flashEnabled',
               JsName: 'flashEnabled',
               Filename: '/Users/tskweres/Dev/Catch/platforms/ios/build/device/SwiftyCam.framework/Headers/SwiftyCam-Swift.h',
               Module:
                { FullName: 'SwiftyCam.Swift',
                  IsPartOfFramework: true,
                  IsSystemModule: false,
                  Libraries: null },
               Flags: [ 'IsIosAppExtensionAvailable' ],
               Type: 'Method',
               Signature: [ { Type: 'Bool' } ] },
            Setter:
             { Name: 'setFlashEnabled:',
               JsName: 'setFlashEnabled',
               Filename: '/Users/tskweres/Dev/Catch/platforms/ios/build/device/SwiftyCam.framework/Headers/SwiftyCam-Swift.h',
               Module:
                { FullName: 'SwiftyCam.Swift',
                  IsPartOfFramework: true,
                  IsSystemModule: false,
                  Libraries: null },
               Flags: [ 'IsIosAppExtensionAvailable' ],
               Type: 'Method',
               Signature: [ { Type: 'Void' }, { Type: 'Bool' } ] } },
          { Name: 'isSessionRunning',
            JsName: 'isSessionRunning',
            Filename: '/Users/tskweres/Dev/Catch/platforms/ios/build/device/SwiftyCam.framework/Headers/SwiftyCam-Swift.h',
            Module:
             { FullName: 'SwiftyCam.Swift',
               IsPartOfFramework: true,
               IsSystemModule: false,
               Libraries: null },
            Flags: [ 'IsIosAppExtensionAvailable' ],
            Type: 'Property',
            Getter:
             { Name: 'isSessionRunning',
               JsName: 'isSessionRunning',
               Filename: '/Users/tskweres/Dev/Catch/platforms/ios/build/device/SwiftyCam.framework/Headers/SwiftyCam-Swift.h',
               Module:
                { FullName: 'SwiftyCam.Swift',
                  IsPartOfFramework: true,
                  IsSystemModule: false,
                  Libraries: null },
               Flags: [ 'IsIosAppExtensionAvailable' ],
               Type: 'Method',
               Signature: [ { Type: 'Bool' } ] } },
          { Name: 'isVideoRecording',
            JsName: 'isVideoRecording',
            Filename: '/Users/tskweres/Dev/Catch/platforms/ios/build/device/SwiftyCam.framework/Headers/SwiftyCam-Swift.h',
            Module:
             { FullName: 'SwiftyCam.Swift',
               IsPartOfFramework: true,
               IsSystemModule: false,
               Libraries: null },
            Flags: [ 'IsIosAppExtensionAvailable' ],
            Type: 'Property',
            Getter:
             { Name: 'isVideoRecording',
               JsName: 'isVideoRecording',
               Filename: '/Users/tskweres/Dev/Catch/platforms/ios/build/device/SwiftyCam.framework/Headers/SwiftyCam-Swift.h',
               Module:
                { FullName: 'SwiftyCam.Swift',
                  IsPartOfFramework: true,
                  IsSystemModule: false,
                  Libraries: null },
               Flags: [ 'IsIosAppExtensionAvailable' ],
               Type: 'Method',
               Signature: [ { Type: 'Bool' } ] } },
          { Name: 'lowLightBoost',
            JsName: 'lowLightBoost',
            Filename: '/Users/tskweres/Dev/Catch/platforms/ios/build/device/SwiftyCam.framework/Headers/SwiftyCam-Swift.h',
            Module:
             { FullName: 'SwiftyCam.Swift',
               IsPartOfFramework: true,
               IsSystemModule: false,
               Libraries: null },
            Flags: [ 'IsIosAppExtensionAvailable' ],
            Type: 'Property',
            Getter:
             { Name: 'lowLightBoost',
               JsName: 'lowLightBoost',
               Filename: '/Users/tskweres/Dev/Catch/platforms/ios/build/device/SwiftyCam.framework/Headers/SwiftyCam-Swift.h',
               Module:
                { FullName: 'SwiftyCam.Swift',
                  IsPartOfFramework: true,
                  IsSystemModule: false,
                  Libraries: null },
               Flags: [ 'IsIosAppExtensionAvailable' ],
               Type: 'Method',
               Signature: [ { Type: 'Bool' } ] },
            Setter:
             { Name: 'setLowLightBoost:',
               JsName: 'setLowLightBoost',
               Filename: '/Users/tskweres/Dev/Catch/platforms/ios/build/device/SwiftyCam.framework/Headers/SwiftyCam-Swift.h',
               Module:
                { FullName: 'SwiftyCam.Swift',
                  IsPartOfFramework: true,
                  IsSystemModule: false,
                  Libraries: null },
               Flags: [ 'IsIosAppExtensionAvailable' ],
               Type: 'Method',
               Signature: [ { Type: 'Void' }, { Type: 'Bool' } ] } },
          { Name: 'maximumVideoDuration',
            JsName: 'maximumVideoDuration',
            Filename: '/Users/tskweres/Dev/Catch/platforms/ios/build/device/SwiftyCam.framework/Headers/SwiftyCam-Swift.h',
            Module:
             { FullName: 'SwiftyCam.Swift',
               IsPartOfFramework: true,
               IsSystemModule: false,
               Libraries: null },
            Flags: [ 'IsIosAppExtensionAvailable' ],
            Type: 'Property',
            Getter:
             { Name: 'maximumVideoDuration',
               JsName: 'maximumVideoDuration',
               Filename: '/Users/tskweres/Dev/Catch/platforms/ios/build/device/SwiftyCam.framework/Headers/SwiftyCam-Swift.h',
               Module:
                { FullName: 'SwiftyCam.Swift',
                  IsPartOfFramework: true,
                  IsSystemModule: false,
                  Libraries: null },
               Flags: [ 'IsIosAppExtensionAvailable' ],
               Type: 'Method',
               Signature: [ { Type: 'Double' } ] },
            Setter:
             { Name: 'setMaximumVideoDuration:',
               JsName: 'setMaximumVideoDuration',
               Filename: '/Users/tskweres/Dev/Catch/platforms/ios/build/device/SwiftyCam.framework/Headers/SwiftyCam-Swift.h',
               Module:
                { FullName: 'SwiftyCam.Swift',
                  IsPartOfFramework: true,
                  IsSystemModule: false,
                  Libraries: null },
               Flags: [ 'IsIosAppExtensionAvailable' ],
               Type: 'Method',
               Signature: [ { Type: 'Void' }, { Type: 'Double' } ] } },
          { Name: 'pinchToZoom',
            JsName: 'pinchToZoom',
            Filename: '/Users/tskweres/Dev/Catch/platforms/ios/build/device/SwiftyCam.framework/Headers/SwiftyCam-Swift.h',
            Module:
             { FullName: 'SwiftyCam.Swift',
               IsPartOfFramework: true,
               IsSystemModule: false,
               Libraries: null },
            Flags: [ 'IsIosAppExtensionAvailable' ],
            Type: 'Property',
            Getter:
             { Name: 'pinchToZoom',
               JsName: 'pinchToZoom',
               Filename: '/Users/tskweres/Dev/Catch/platforms/ios/build/device/SwiftyCam.framework/Headers/SwiftyCam-Swift.h',
               Module:
                { FullName: 'SwiftyCam.Swift',
                  IsPartOfFramework: true,
                  IsSystemModule: false,
                  Libraries: null },
               Flags: [ 'IsIosAppExtensionAvailable' ],
               Type: 'Method',
               Signature: [ { Type: 'Bool' } ] },
            Setter:
             { Name: 'setPinchToZoom:',
               JsName: 'setPinchToZoom',
               Filename: '/Users/tskweres/Dev/Catch/platforms/ios/build/device/SwiftyCam.framework/Headers/SwiftyCam-Swift.h',
               Module:
                { FullName: 'SwiftyCam.Swift',
                  IsPartOfFramework: true,
                  IsSystemModule: false,
                  Libraries: null },
               Flags: [ 'IsIosAppExtensionAvailable' ],
               Type: 'Method',
               Signature: [ { Type: 'Void' }, { Type: 'Bool' } ] } },
          { Name: 'tapToFocus',
            JsName: 'tapToFocus',
            Filename: '/Users/tskweres/Dev/Catch/platforms/ios/build/device/SwiftyCam.framework/Headers/SwiftyCam-Swift.h',
            Module:
             { FullName: 'SwiftyCam.Swift',
               IsPartOfFramework: true,
               IsSystemModule: false,
               Libraries: null },
            Flags: [ 'IsIosAppExtensionAvailable' ],
            Type: 'Property',
            Getter:
             { Name: 'tapToFocus',
               JsName: 'tapToFocus',
               Filename: '/Users/tskweres/Dev/Catch/platforms/ios/build/device/SwiftyCam.framework/Headers/SwiftyCam-Swift.h',
               Module:
                { FullName: 'SwiftyCam.Swift',
                  IsPartOfFramework: true,
                  IsSystemModule: false,
                  Libraries: null },
               Flags: [ 'IsIosAppExtensionAvailable' ],
               Type: 'Method',
               Signature: [ { Type: 'Bool' } ] },
            Setter:
             { Name: 'setTapToFocus:',
               JsName: 'setTapToFocus',
               Filename: '/Users/tskweres/Dev/Catch/platforms/ios/build/device/SwiftyCam.framework/Headers/SwiftyCam-Swift.h',
               Module:
                { FullName: 'SwiftyCam.Swift',
                  IsPartOfFramework: true,
                  IsSystemModule: false,
                  Libraries: null },
               Flags: [ 'IsIosAppExtensionAvailable' ],
               Type: 'Method',
               Signature: [ { Type: 'Void' }, { Type: 'Bool' } ] } } ],
       StaticProperties: null,
       Protocols:
        [ 'UIGestureRecognizerDelegate',
          'AVCaptureFileOutputRecordingDelegate' ],
       Base: 'UIViewController' } ] }

#4

posted, I appreciate the help sir. I downloaded it in yaml and converted it to JS, let me know if that works for you. I tried the typings but it was throwing an error on build for some reason, but metadata worked


#5

I was able to extend it like this, read code below. However, now I have an issue where the camera doesn’t load and ask for permission, it’s just a blank page. I believe I have to somehow tell the view to wait and then add SwiftyCam to the view after init? I tried using .nativeElement. addChild(cam) but in ngAfterViewInit but that did not work :frowning:

 import { GridLayout } from 'ui/layouts/grid-layout';

declare var SwiftyCamViewController;

export class SwiftyCam extends GridLayout {

    public constructor() {
        super();
        (<any>this)._ios = SwiftyCamViewController.new();
    }

    public onLoaded() {
        super.onLoaded();
    }
}

My Camera Component Page:

import { Component, AfterViewInit, ViewChild, ElementRef } from "@angular/core";
import { registerElement } from "nativescript-angular/element-registry";
import { SwiftyCam } from "../../services/swiftycam/swiftycam";

registerElement("SwiftyCam", () => require("../../services/swiftycam/swiftycam").SwiftyCam);

@Component({
    template: `
      <SwiftyCam></SwiftyCam>
    `
})

export class CameraComponent implements AfterViewInit {

  constructor() {
  }
  ngAfterViewInit() {

  }

}

#6

Hi @traviss you will need to create a little plugin for this, something like this will work (just tried it and it runs - however camera/video access will only work when run on an actual device - won’t engage a camera in the simulator):

import { ContentView } from 'ui/content-view';

declare var UIView;
declare class SwiftyCamViewController extends UIViewController { }

class MySwifty extends SwiftyCamViewController { 

  viewDidLoad() {
    super.viewDidLoad();
    // you can add swifty buttons here
  }
}

export class SwiftyCam extends ContentView {
  private _ios: UIView;

  constructor() {
    super();
    this._ios = new UIView();
  }  
  public get ios() {
    return this._ios;
  }

  public get _nativeView() {
    return this._ios;
  }

  public onLoaded() {
    let swifty = MySwifty.new();
    this._ios.addSubview(swifty.view);
  }
}

Then when you add as an internal plugin (for example), you can do this:

import { registerElement } from 'nativescript-angular';
registerElement('SwiftyCam', () => require('nativescript-swiftycam').SwiftyCam);

And in your view template:

<StackLayout>
    <SwiftyCam></SwiftyCam>
</StackLayout>

That will show the cam view full screen when the app launches - verified here :slight_smile:

I’ll cover this in detail in an egghead course in progress at moment. I’ll use SwiftyCam as a direct example.


#7

There’s also a way to do this without a view plugin at all. Somewhere in your code, define the custom view controller which extends SwiftyCamViewController:

export class MySwifty extends SwiftyCamViewController { 

  viewDidLoad() {
    super.viewDidLoad();
    // add swifty buttons here
  }
}

In your app.component.ts (or any component) constructor:

let swifty = MySwifty.new();
let appWindow = UIApplication.sharedApplication.keyWindow;
appWindow.rootViewController.presentViewControllerAnimatedCompletion(swifty, true, null);

This will auto present the swifty camera preview layer onto the main view controller.
No XML view elements needed at all with this manual approach.


#8

Interesting, in this last no-XML approach then I’m guessing that the methods for taking a photo would be something as simple as this.StartVideoRecording… and so on?

Also - one of the key aspects of this is being able to customize the UI and add buttons and controls, if I go the no-XML route, will the camera simply overlay the entire view?

I appreciate your help - I will get to finishing this up later tonight after the work day.


#9

Yes, camera layer from SwiftyCam is best used (and meant be used generally) as a full view overlay - given it’s implementation, you’ll probably find it makes most sense as full screen overlay anyway.

Buttons can be constructed and just added manually inside the custom view controller (for example, ‘MySwifty’ above)'s viewDidLoad method.

See this for example of how to manually construct and add buttons with actions, etc.:

Good luck!


#10

I’m trying your code above and when I save and it compiles I get the typescript errors:

app/services/swiftycam/swiftycam.ts(6,47): error TS2507: Type 'any' is not a constructor function type.

app/services/swiftycam/swiftycam.ts(11,11): error TS2339: Property 'viewDidLoad' does not exist on type 'SwiftyCamViewController'.

app/services/swiftycam/swiftycam.ts(17,17): error TS2304: Cannot find name 'UIView'.

app/services/swiftycam/swiftycam.ts(32,27): error TS2339: Property 'new' does not exist on type 'typeof MySwifty'.

Should I be importing or declaring UIView and UIViewController differently?


#11

If you just want to get the .js output, set noEmitOnError: false in your tsconfig.json


#12

Thanks that gets me the compiled JS file though I still see the errors. So I implemented the code above from @wwwalkerrun , and I have a CameraComponent which is a page with a route in my app etc, and on that page I have:

import { Component, AfterViewInit, ViewChild, ElementRef } from "@angular/core";
import { registerElement } from "nativescript-angular/element-registry";
import { SwiftyCam } from "../../services/swiftycam/swiftycam";

registerElement("SwiftyCam", () => require("../../services/swiftycam/swiftycam").SwiftyCam);

@Component({
    template: `
    <StackLayout>
      <SwiftyCam></SwiftyCam>
    </StackLayout>
    `
})

export class CameraComponent implements AfterViewInit {

  constructor() {

  }

  ngAfterViewInit() {

  }

}

And I get:

Error: Uncaught (in promise): Error: Error in ./CameraComponent class CameraComponent - inline template:2:6 caused by: Could not load view for: SwiftyCam.Error: Extends is supported only for native classes.


#13

Could it be my version of Swift in the Podfile? What does your podfile look like?


#14

Is this posted on a repo anywhere? I’d love to take a look at where you’re at with this.


#15

Sorry man - started a new gig this week so haven’t had much time on this.

I literally have a hello-world app with 2 component routes and this on one of them and this service:

export class MySwifty extends SwiftyCamViewController { 

  viewDidLoad() {
    super.viewDidLoad();
    // add swifty buttons here
  }
}

component:

let swifty = MySwifty.new();
let appWindow = UIApplication.sharedApplication.keyWindow;
appWindow.rootViewController.presentViewControllerAnimatedCompletion(swifty, true, null);

It works and inits the camera just like you said :slight_smile: Now I just need to figure out:

  1. how to add buttons to the screen
  2. map the Swifty methods to those buttons ( flash, take photo, hold down for video etc )
  3. Navigate away from the camera and back to the camera
    4…

I basically want to create the exact demo that’s in the Swifty Repo - https://github.com/Awalz/SwiftyCam

In any event - not much to report back yet, but I’ll have time to tinker more this weekend. If you get something going and want to share a repo hit me up on the slack channel, I can help map the methods and whatnot just need some guidance and like 1 example from the native side


#16

When trying to implement the tap event the app crashes and I get in the console:

unrecognized selector sent to instance


#17

Unrecognized selector is usually something related to the arguments you are passing to particular methods. Can you provide the code you are using to handle the tap event and how you have that wired?


#18

ahh - forgot to expose the tap method, I was trying out the code above

name: "MessagesMainController",
    exposedMethods: {
        "tap": {
            returns: interop.types.void
        }
    }

#19

Hey
I’m currently struggling with the same problem. I have to create my own UIViewController in an Angular / Typescript plugin. If I follow the documentation I get the error that UIViewController.extend() I guess that’s because the documentation only is for plain JavaScript?

When I try to subclass it with extends UIViewController as in your example it looks much better. Now I have to expose an own event handler as in your example tap() so I tried to add the the exposedMethods to my class but then I get a Identifier expected for interop.types.void. Where do I have to place it? Could you please post a full example of your Class which extends a Native class?

Thanks for your help!
Cheers
Michael


#20

Finally I’ve figured it out. Here an example (that worked for me):


export class ExampleViewController extends UIViewController {

    private navigationBar: UINavigationBar;
 
    public viewDidLoad() {
        super.viewDidLoad();
 
        this.navigationBar = UINavigationBar.new();
 
        // Init Navigation-Bar
        let barButtonItem = UINavigationItem.alloc().init();

        let cancelButton = UIBarButtonItem.alloc().initWithTitleStyleTargetAction("Cancel", UIBarButtonItemStyle.Plain, this, "cancel");
        barButtonItem.leftBarButtonItem = cancelButton;

        let saveButton = UIBarButtonItem.alloc().initWithTitleStyleTargetAction("Save", UIBarButtonItemStyle.Done, this, "save");
        barButtonItem.rightBarButtonItem = saveButton;

        this.navigationBar.items = NSArray.arrayWithObject(barButtonItem);
        this.view.addSubview(this.navigationBar);
    }

    // ---------------------------------------------------
    // These methods need to be exposed otherwise the runtime wouldn't find them
    // ---------------------------------------------------

    public cancel(sender: UIButton): void {
        alert("Cancel");
    }

    public save(sender: UIButton): void {
        alert("Save");
    }

    public static ObjCExposedMethods = {
        "cancel": {returns: interop.types.void, params: [UIButton]},
        "save": {returns: interop.types.void, params: [UIButton]}
    };
}