0

我在 Sencha Touch 2.1 中编写了一个应用程序,我在其中嵌入了一个包构建到 Cordova/PhoneGap 2.5.0 并在 xCode 中编译以在 iOS Simulator / iOS 上运行。我已将PGSQLite插件添加到 PhoneGap,并为 Sencha 构建了自己的 PhoneGap/SQLite 代理,我在一些商店中使用了它。*

问题:当我将包构建嵌入PhoneGap 并在iOS 模拟器中运行时,我看到Cordova 在Sencha 初始化之前没有加载。我看到这个是因为我在我的 Sencha 应用程序中对Cordova.exec我在代理初始化中所做的调用导致一个错误,告诉我Cordova找不到该对象。

Cordova.exec稍后在我的应用程序中成功使用来运行 PhoneGap 的 Childbrowser 插件之类的东西,它可以工作。但是Cordova.exec在应用程序执行的早期阶段(即初始化)使用太早,无法保证 Cordova 对象已被实例化。

已经尝试过:我已经尝试过以下方法:

  1. 我尝试简单地将我的 Sencha 应用程序的开发人员构建嵌入到 PhoneGap 中。虽然这可行,但我不想将我的开发版本部署为我发布的应用程序,因为它效率低下并且占用大量空间。然而,我从这个实验中了解到,Sencha Touch 微加载器在包和生产构建上的工作方式在 Sencha 之后加载 PhoneGap。在 Sencha 在包构建中加载后检查 DOM 时,可以清楚地看到这一点。

  2. 我已经将我的app.json文件配置为包含之前的 PhoneGap 和我的插件app.js以及 Sencha Touch 框架。使用我的 JS 文件引用的顺序app.json似乎并没有影响加载顺序。

  3. 我还尝试创建一个脚本加载器,如此所述 (StackOverflow)。然后我为 Cordova 运行脚本加载器,在回调中为我的插件运行脚本加载器,最后在回调中运行 Sencha Touch 微加载器。这导致了一个错误。index.html此外,在 Sencha 构建我的包之后,我必须在我的文件中手动设置它。这似乎是不可接受的。

我在寻找什么:我正在寻找以下问题的答案:

  1. 有没有办法配置 Sencha 的 microloader 或我的 Sencha 应用程序,以便确保在 Sencha 的 microloader 运行之前加载 Cordova?

  2. 有没有办法设置它,以便使用 Sencha Cmd 仍然有效,并且在我构建应用程序后我不必在我的 index.html 文件中破解?

注意:*请不要建议我使用现有的,所谓的 Sencha 的 SQLite 代理。我特别选择了我的方法,因为虽然我很欣赏 Sencha Touch 2 的 SQLite 代理(即this)的现有工作,但它实际上是一个 WebSQL 代理,它不原生存储在 iOS 上的 SQLite 中。我的代理使用 PhoneGap 的 PGSQLite 插件将数据本地存储在 iOS 上的 SQLite 中。当我有机会清理它并从我的代码中解开它时,我计划将它开源。

4

1 回答 1

0

我最终通过构建自定义加载器自己解决了这个问题。我不确定是否有更类似于 Sencha 的方式来做到这一点,但这里是我所做的详细信息,它确实有效,以防其他人想要确保 PhoneGap在运行之前完全加载到包和生产版本中Sencha中的任何东西。(在 PhoneGap 打包 Sencha 应用程序的所有场景中,这可能都是这种情况)。

我的 index.html 文件:

<!DOCTYPE HTML>
<html manifest="" lang="en-US">
<head>
    <!-- Load Cordova first. Replace with whatever version you are using -->
    <script type="text/javascript" src="cordova.js"></script>    
    <script type="text/javascript" charset="utf-8">
        function onBodyLoad() {
            // Check for whatever mobile you will run your PhoneGap app
            // on. Below is a list of iOS devices. If you have a ton of
            // devices, you can probably do this more elegantly.
            // The goal here is to only listen to the onDeviceReady event
            // to continue the load process on devices. Otherwise you will
            // be waiting forever (literally) on Desktops.
            if ((navigator.platform == 'iPad') ||
                (navigator.platform == 'iPhone') ||
                (navigator.platform == 'iPod') ||
                (navigator.platform == 'iPhone Simulator') ||
                (navigator.platform == 'iPadSimulator')
               ) {
              // Listening for this event to continue the load process ensures
              // that Cordova is loaded.
              document.addEventListener("deviceready", onDeviceReady, false);
            } else {
                // If we're on Desktops, just proceed with loading Sencha.
                loadScript('loader.js', function() {
                    console.log('Finished loading scripts.');
                });
            }
        };

        // This function is a modified version of the one found on
        // StackOverflow, here: http://stackoverflow.com/questions/756382/bookmarklet-wait-until-javascript-is-loaded#answer-756526
        // Using this allows you to wait to load another script by
        // putting the call to load it in a callback, which is
        // executed only when the script that loadScript is loading has
        // been loaded.
        function loadScript(url, callback)
        {
            var head = document.getElementsByTagName("head")[0];
            var script = document.createElement("script");
            script.src = url;

            // Attach handlers for all browsers
            var done = false;
            script.onload = script.onreadystatechange = function()
            {
                if( !done && ( !this.readyState 
                            || this.readyState == "loaded" 
                            || this.readyState == "complete") )
                {
                    done = true;

                    // Continue your code
                    callback();
                }
            };

            head.appendChild(script);


        }

        function onDeviceReady() {
            console.log("[PhoneGap] Device initialized.");
            console.log("[PhoneGap] Loading plugins.");

            // You can load whatever PhoneGap plugins you want by daisy-chaining
            // callbacks together like I did with pgsqlite and Sencha.
            loadScript('pgsqlite_plugin.js', function() {
                console.log("[Sencha] Adding loader.");

                // The last one to load is the custom Sencha loader.
                loadScript('loader.js', function() {
                    console.log('Finished loading scripts.');
                });
            });

        };
    </script>

    <meta charset="UTF-8">
    <title>Sencha App</title>   
</head>
<!-- Don't forget to call onBodyLoad() in onLoad -->
<body onLoad="onBodyLoad();">
</body>
</html>

接下来,在您的文档根目录中的 loader.js 中创建一个自定义加载器,以及您的 index.html。这个很大程度上基于 Sencha 附带的开发微加载器。给他们很多道具:

console.log("Loader included.");

(function() {
    function write(content) {
        document.write(content);
    }

    function meta(name, content) {
        write('<meta name="' + name + '" content="' + content + '">');
    }

    var global = this;

    if (typeof Ext === 'undefined') {
        var Ext = global.Ext = {};
    }

    var head = document.getElementsByTagName("head")[0];

    var xhr = new XMLHttpRequest();
    xhr.open('GET', 'app.json', false);
    xhr.send(null);

    var options = eval("(" + xhr.responseText + ")"),
        scripts = options.js || [],
        styleSheets = options.css || [],
        i, ln, path;

    meta('viewport', 'width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no');
    meta('apple-mobile-web-app-capable', 'yes');
    meta('apple-touch-fullscreen', 'yes');

    console.log("Loading stylesheets");
    for (i = 0,ln = styleSheets.length; i < ln; i++) {
        path = styleSheets[i];

        if (typeof path != 'string') {
            path = path.path;
        }

        var stylesheet = document.createElement("link");
        stylesheet.rel = "stylesheet";
        stylesheet.href = path;

        head.appendChild(stylesheet);
    }

    for (i = 0,ln = scripts.length; i < ln; i++) {
        path = scripts[i];

        if (typeof path != 'string') {
            path = path.path;
        }

        var script = document.createElement("script");
        script.src = path;
        head.appendChild(script);
    }

})();

请注意,您的 index.html 文件不包含#microloader script元素。那是因为你应该把它拿出来并使用你的自定义加载器。

有了所有这些,您将能够顺利航行,因为在您的 Sencha javascript 开始执行操作之前,您知道整个 PhoneGap 环境已经到位。

于 2013-06-12T01:22:38.877 回答