Incorporating Swift code into a NativeScript app

I'm attempting to integrate native Swift code into my NativeScript application. Despite following the guidelines provided in the documentation, specifically adding a Swift source file to App_Resources/iOS/src/ and using publicly exposed classes directly in TypeScript code, I am encountering an error stating Cannot find name 'TestClass'.

To reproduce this issue, follow these steps:

  1. Create a new NativeScript project with iOS support using the command
    tns create my-app-name --template tns-template-blank-ts

Note: In my case, I initially generated the app using

vue init nativescript-vue/vue-cli-template testapp
, which seems to be causing problems.

  1. Add a TestClass.swift file to App_Resources/iOS/src/
import Foundation

public class TestClass: NSObject {
    @objc public func echo(param: String) -> String {
        return param
    }
}
  1. Instantiate the class in any TypeScript file using let instance = new TestClass()
  2. Run the command tns debug ios
  3. The compilation will fail with Cannot find name 'TestClass'

I have attempted different approaches such as generating TypeScript typings using

TNS_TYPESCRIPT_DECLARATIONS_PATH="$(pwd)/typings" tns build ios
or declaring the class as any with declare let KeyCommander: any; to rule out TypeScript-related issues. However, neither approach resolved the problem. The first method did not generate typings for my custom class, resulting in TypeScript compilation errors. The second method allowed TypeScript to compile but caused a runtime crash with
JS ERROR ReferenceError: Can't find variable: TestClass
.

I have confirmed that the Swift file is being compiled by intentionally introducing syntax errors that halt the build process.

My NativeScript version is 6.4.0.

What could be missing in this integration?

Update: Upon further investigation, I realized that creating the app using

vue init nativescript-vue/vue-cli-template testapp
leads to the failure mentioned above. Conversely, apps created using the standard tns cli do not encounter this issue, as noted in Tyler Blake's answer. The question now arises: What is causing this discrepancy?

Answer №1

After following the instructions provided, I successfully managed to generate the typings in objc!nsswiftsupport.d.ts. Once you have generated the typings, do you see the file containing the following contents?

declare class TestClass extends NSObject {

    static alloc(): TestClass; // inherited from NSObject

    static new(): TestClass; // inherited from NSObject

    echoWithParam(param: string): string;
}

This indicates that NS is capable of recognizing the Swift code.

To proceed further, simply include tns-platform-declarations, then in the references.d.ts file, insert a line directing to the objc!nsswiftsupport.d.ts file. This will enable intellisense in your TypeScript code.

You can add something like this:

/// <reference path="./typings/objc!nsswiftsupport.d.ts" />

I hope this explanation helps!

Answer №2

After carefully analyzing the templates generated by both tns-cli and vue init, I identified a crucial difference that solved my problem. It turns out that the vue init template contains an outdated version of the nativescript platform. By simply updating the version from

"tns-ios": {
  "version": "6.0.1"
}

to version 6.4.0 (the same as the tns-cli template), the process now works flawlessly according to the documentation.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

How come this mocha test is exceeding its timeout limit when making a basic call with mongoose?

Trying to write a simple assertion for an asynchronous database method: describe('User Repository', () => { describe('findById', () => { it('Returns a user that can be found in the database by ID', async () => { ...

How can I utilize a variable in a v-for loop as a label for a q-btn in Vue.js?

I have a list: myList = [1, 2, 3, 4, 5, 6, 7, 8, 9] I'd like to generate buttons using this list where the label corresponds to the number: <q-btn v-for="number in myList" v-bind:key="number" color="primary" label=&q ...

TypeScript's reliance on dependent types

Is it possible to implement this functionality using TypeScript? There exist objects that define various "actions". export interface IAction { action: string; data: any; otherParam1: number; otherParam2: number; } The 'action' p ...

Stopping WKWebView from automatically underlining plain text as clickable URLs

I am facing an issue with rendering HTML content in a WKWebView. The content I want to display is as follows: <html> <body> <div>Here goes plain text google.com type of content</div> </body> </html> When I view this ...

Execute a function upon tapping the home button in a Swift app

Recently, I've been developing a game using Swift and encountered an issue where the game restarts when the home button is tapped accidentally. I am looking for assistance on how to implement code that calls a function to restart the game when the phy ...

Link a list separated by commas to checkboxes in Angular 9

Within my reactive form, I am binding a checkbox list to an array using the following structure: {id:number, name:string}. TS ngOnInit(): void { this.initFCForm(); this.addCheckboxes(); } initFCForm(): void { this.fcForm = this.formBuilder.group({ fr ...

UITabBars should always be easily reachable from any area within the app

The UIKit guidelines for iOS state that a UITabBar should be "accessible from every location in the application." What exactly does "accessible" mean in this context? Does it simply refer to visibility, or is there more to it than that? I am planning to ...

Retrieve the initial response object from PromiseKit and proceed to the completion block

While making consecutive calls to three services, I encountered an issue when I needed to access a variable from the response of the first service which is userModel. Even though I could retrieve the response from the second service labeled as initModel, a ...

Oops! The program encountered an issue on the production environment, but it's running smoothly

When I execute Webpack using the command node node_modules/webpack/bin/webpack. js --env. prod An error message is displayed below. However, when running in --env. dev mode, the command executes without any issues. Can't resolve './../$$_gen ...

Prevent resizing or zooming on AmCharts4 radar chart

Is there a way to disable the click-drag zooming feature on the AmCharts4 radar chart in my react application? Thank you. View image of the chart ...

Struggling to Find the Correct Location for Implementing a JSON Dictionary Value in iOS Applications

So, I have been working on a method that creates a URL for an image. Initially, it looked like this: -(NSURL*)urlForImageWithId:(NSNumber*)IdPhoto isThumb:(BOOL)isThumb { NSString* urlString = [NSString stringWithFormat:@"%@/%@upload/%@%@.jpg", ...

Discovering the present route within the Vue 2.7 composition API

When working with Vue2, I am able to access the current path using this.$route.path In Vue3, I can utilize useRouter() for similar functionality. However, inVue2.7 composition api, neither of these options is available. ...

Can someone guide me on incorporating static methods into a Mongoose model using TypeScript for Mongoose version 5.11?

When using Mongoose 5.10, I implemented static methods in my Mongoose models with the following pattern: import { Schema, Document, Model, Connection } from "mongoose"; import { v4 } from "uuid"; export interface IFoo extends Document ...

Issue with Vue data table where the row's q-input does not retain the values of the model

For access to the code, please visit the azure link for the built code and check out the source code on github. In this particular scenario, I am utilizing a q-datatable from Quasar Framework. The data is structured in nested form with primary data displ ...

What is the best way to define a default value for a v-text-field in Vuetify within a Nuxt.js project?

As a beginner with vuejs and nuxtjs, I have been introduced to vuetify at my workplace. I am currently trying to set the default value of 0 for v-text-field fields in the application, but unfortunately, I cannot seem to find this information in the vueti ...

Received corrupted file during blob download in Angular 7

When using Angular 7, I am making an API call by posting the URL file and attempting to download it using the 'saveAs' function from the fileSaver library. The file is successfully downloading, but it appears to be corrupted and cannot be opened. ...

Steps to retrieve a date from a form control

html <form [formGroup]="searchForm" (ngSubmit)="search()"> <div class="row"> <div class="col"> <input type="date" class="form-control" formControlName="startD ...

Exploring TypeScript Module Importation and WebPack Integration

Struggling with WebPack's injection of imported dependencies for a TypeScript project. The first challenge is getting TypeScript to recognize the imported module. In the header.ts file, there is a declaration of a module nested under vi.input, export ...

Informing a screen reader in Vue.js through the use of aria-live features

My goal is to make a vue component that dynamically announces information to a screen reader when certain events occur on my website. I have managed to achieve this functionality by having a button populate a span with text containing the attributes aria- ...

What is the best way to determine the left and top coordinates when resizing a draggable image within a container?

I am struggling to correctly scale the image and set the left (x) and top (y) positions. Here is the code from my template: <div id="container" :style="`height: ${height}px;width: ${size}px;overflow: hidden;position: relative;`"> ...