Как отладить имя привязки импорта, которое не найдено

#nativescript

#nativescript

Вопрос:

У меня есть приложение NativeScript, к которому я пытаюсь добавить поддержку iBeacon с помощью плагина iBeacon. Приложение успешно создается и синхронизируется с моим телефоном (я использую SideKick). При запуске приложения возникает фатальное исключение javascript. Об ошибке javascript сообщается на:

 file:///app/tns_modules/tns-core-modules/ui/builder/builder.js:244:56: JS ERROR Error: Building UI from XML. @file:///app/app-root.xml:18:9
  

В этой строке определяется страница, которая пытается получить доступ к коду iBeacon:

 <Frame defaultPage="views/search/search-page"></Frame>
  

и конкретная ошибка:

 Importing binding name 'BeaconLocationOptions' is not found.
  

Я предполагаю, что это происходит как часть следующего оператора import:

 import {NativescriptIbeacon, BeaconCallback, BeaconLocationOptions, BeaconLocationOptionsIOSAuthType, BeaconLocationOptionsAndroidAuthType, BeaconRegion, Beacon } from 'nativescript-ibeacon';
  

Приведенная выше инструкция import — это то, что задокументировано как часть документации iBeacon.

В моем проекте есть каталог nativescript-ibeacon под node_modules. Похоже, что конкретный файл ios находится там:

 /Users/edscott/NativeScript/beacon-test/node_modules/nativescript-ibeacon/nativescript-ibeacon.ios.js
  

Я не уверен, проблема ли это в моем коде или проблема с конфигурацией — возможно, чего-то не хватает, что мешает правильному развертыванию файлов ibeacon на устройстве.

Мой код написан на javascript, но я установил плагин typescript. Похоже, что этот плагин iBeacon предполагает, что приложение написано на typescript.

Я ищу помощи в определении того, что попробовать дальше.

К вашему сведению…Я попытался извлечь исходные файлы из node_modules и включить их непосредственно в мой проект. После решения многих проблем с помощью этого подхода я в конечном итоге столкнулся с той же проблемой — проблема с импортом кода при запуске на устройстве.

Ниже приведен код, использующий плагин iBeacon:

 const observableModule = require("tns-core-modules/data/observable");
import {NativescriptIbeacon, BeaconCallback, BeaconLocationOptions, BeaconLocationOptionsIOSAuthType, BeaconLocationOptionsAndroidAuthType, BeaconRegion, Beacon } from 'nativescript-ibeacon';

function SearchViewModel() {

    let callback = {
        onBeaconManagerReady() {
            // start ranging and/or monitoring only when the beacon manager is ready
            this.nativescriptIbeacon.startRanging(this.region);
            this.nativescriptIbeacon.startMonitoring(this.region);
        },
        didRangeBeaconsInRegion: function(region, beacons) {
            console.log("didRangeBeaconsInRegion");
        },
        didFailRangingBeaconsInRegion: function(region, errorCode, errorDescription) {
            console.log("didFailRangingBeaconsInRegion");
        }
    };

    let options = {
        iOSAuthorisationType: BeaconLocationOptionsIOSAuthType.Always,
        androidAuthorisationType: BeaconLocationOptionsAndroidAuthType.Coarse,
        androidAuthorisationDescription: "Location permission needed"
    };

    let nativescriptIbeacon = new NativescriptIbeacon(callback, options);

    let region = new BeaconRegion("HelloID", "2f234454-cf6d-4a0f-adf2-f4911ba9ffa6");

    const viewModel = observableModule.fromObject({
        "beaconData": "not set yet",  

        "onTapStart": function() {
            this.set("beaconData", "started");
            console.log("tapped start");

            if (!nativescriptIbeacon.isAuthorised()) {
                console.log("NOT Authorised");
                nativescriptIbeacon.requestAuthorization()
                    .then(() => {
                        console.log("Authorised by the user");
                        nativescriptIbeacon.bind();

                    }, (e) => {
                        console.log("Authorisation denied by the user");
                    })
            } else {
                console.log("Already authorised");
                nativescriptIbeacon.bind();
            }            
        },

        "onTapStop": function() {
            this.set("beaconData", "stopped");
            console.log("tapped stop");

            nativescriptIbeacon.stopRanging(region);
            nativescriptIbeacon.stopMonitoring(region);
            nativescriptIbeacon.unbind();
        }
    });

    return viewModel;
}

module.exports = SearchViewModel;
  

Комментарии:

1. Можете ли вы показать нам, как вы используете BeaconLocationOptions в своем коде?

2. Я добавил код в основное сообщение выше. Я не использую все, что включено в инструкцию import. Однако, когда я удаляю элементы из импорта, ошибка просто перемещается на другой элемент в списке импортированных элементов. В частности, если я удаляю BeaconLocationOptions из импорта, я получаю ту же ошибку для BeaconLocationOptionsIOSAuthType.

Ответ №1:

Здесь я создал для вас игровую площадку.

Если вы посмотрите на пример, я импортирую NativescriptIbeacon из основной папки, а rest — из общей папки.

P.S. Этот плагин зависит от nativescript-разрешения

 import { NativescriptIbeacon } from '../nativescript-ibeacon';
import {
    BeaconRegion, Beacon, BeaconCallback,
    BeaconLocationOptions, BeaconLocationOptionsIOSAuthType, BeaconLocationOptionsAndroidAuthType
} from "../nativescript-ibeacon/nativescript-ibeacon.common";
  

Этот ответ решил мою проблему вместе с другой модификацией. После разделения импорта у меня все еще была та же ошибка. Затем я прочитал следующую страницу о модулях:
https://docs.nativescript.org/core-concepts/android-runtime/getting-started/modules
На основе этого утверждения:

Если идентификатор модуля, переданный в require(moduleName), не начинается с ‘/’, ‘../’ или ‘./’, то NativeScript выполнит поиск модуля в папке tns_modules

Я предположил, что, возможно, только require выполняет правильный поиск в tns_modules. Я переработал импорт, чтобы вместо этого использовать require, и это сработало. Мои изменения приведены ниже. Возможно, есть более эффективный способ сделать это, но у меня это сработало.

 const nsb = require("nativescript-ibeacon/nativescript-ibeacon.js");
const nsbc = require("nativescript-ibeacon/nativescript-ibeacon.common.js");
const NativescriptIbeacon = nsb.NativescriptIbeacon;
const BeaconCallback = nsbc.BeaconCallback;
const BeaconLocationOptions = nsbc.BeaconLocationOptions;
const BeaconLocationOptionsIOSAuthType = nsbc.BeaconLocationOptionsIOSAuthType;
const BeaconLocationOptionsAndroidAuthType = nsbc.BeaconLocationOptionsAndroidAuthType
const BeaconRegion = nsbc.BeaconRegion;
const Beacon = nsbc.Beacon;