0

テンプレートと TVML を使用して、独自の読み込みページでアプリを開始し、サービスを呼び出してユーザーのメイン ページを作成します。

内部のサーバーへの呼び出しを開始するとdidFinishLaunchingWithOptions、エラーが発生しますITML <Error>: undefined is not an object - undefined - line:undefined:undefined

このことから、JavaScript 関数が完了する前にサーバーへの非同期呼び出しが終了していると想定し、App.onLaunchサーバーが呼び出される前に待機時間を強制した場合にのみ動作させることができます。

AppDelegate メソッドは次のとおりです。

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        window = UIWindow(frame: UIScreen.mainScreen().bounds)
        let appControllerContext = TVApplicationControllerContext()

        // our "base" is local
        if let jsBootUrl = NSBundle.mainBundle().URLForResource("application", withExtension: "js") {
            appControllerContext.javaScriptApplicationURL = jsBootUrl
        }
        let jsBasePathURL = appControllerContext.javaScriptApplicationURL.URLByDeletingLastPathComponent
        baseUrl = jsBasePathURL?.absoluteString
        appControllerContext.launchOptions["BASEURL"] = jsBasePathURL?.absoluteString

        appController = TVApplicationController(context: appControllerContext, window: window, delegate: self)

        // initiate conversation with the server
        myPageCreator = PageCreator()
        myPageCreator?.delegate = self
        myPageCreator?.startDataCall(baseUrl!)

        return true
    }

これが(ややボイラープレートの)javascript関数です:

App.onLaunch = function(options) {
    var javascriptFiles = [
        `${options.BASEURL}ResourceLoader.js`,
        `${options.BASEURL}Presenter.js`
    ];

    evaluateScripts(javascriptFiles, function(success) {
        if (success) {

            resourceLoader = new ResourceLoader(options.BASEURL);
            var index = resourceLoader.loadResource(`${options.BASEURL}myLoadingPage.xml.js`,
                function(resource) {
                    var doc = Presenter.makeDocument(resource);
                    doc.addEventListener("select", Presenter.load.bind(Presenter));
                    navigationDocument.pushDocument(doc);
                });
        } else {
            /* handle error case here */
        }
    });
}

ここで、 のサーバーへの呼び出しを変更し、didFinishLaunchingWithOptions強制的に待機させると、次のようになります。

        ...
        // race condition hack:
        _ = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: "testing", userInfo: nil, repeats: false)

        return true
    }

    // initiate conversation with the server
    func testing() {
        myPageCreator = PageCreator()
        myPageCreator?.delegate = self
        myPageCreator?.startDataCall(baseUrl!)
    }

.. それが動作します。しかし、私はその解決策が好きではありません!この競合状態が発生しないようにするにはどうすればよいですか?

4

1 に答える 1

0

App.onLaunchがスクリプトの実行を いつ終了したかを知るために、Javascript が Swift と通信する方法が必要です。

didFinishLaunchingWithOptionsメソッドでこのコードを実行します。Javascript でonLaunchDidFinishLoading()を呼び出し、Swift でコールバックを処理できるようになります。

appController.evaluateInJavaScriptContext({(evaluation: JSContext) -> Void in
   let onLaunchDidFinishLoading : @convention(block) () -> Void = {
      () -> Void in
         //when onLaunchDidFinishLoading() is called in Javascript, the code written here will run.
         self.testing()
   }
   evaluation.setObject(unsafeBitCast(onLaunchDidFinishLoading, AnyObject.self), forKeyedSubscript: "onLaunchDidFinishLoading")

   }, completion: {(Bool) -> Void in
})


func testing() {
    myPageCreator = PageCreator()
    myPageCreator?.delegate = self
    myPageCreator?.startDataCall(baseUrl!)
}

テンプレートのロードが完了したら、 App.onLaunch内にonLaunchDidFinishLoading ()を追加するだけです。

App.onLaunch = function(options) {
var javascriptFiles = [
    `${options.BASEURL}ResourceLoader.js`,
    `${options.BASEURL}Presenter.js`
];

evaluateScripts(javascriptFiles, function(success) {
    if (success) {

        resourceLoader = new ResourceLoader(options.BASEURL);
        var index = resourceLoader.loadResource(`${options.BASEURL}myLoadingPage.xml.js`,
            function(resource) {
                var doc = Presenter.makeDocument(resource);
                doc.addEventListener("select", Presenter.load.bind(Presenter));
                navigationDocument.pushDocument(doc);
                //ADD THE FOLLOWING LINE
                onLaunchDidFinishLoading();
            });
    } else {
        /* handle error case here */
    }
});
}
于 2016-01-23T21:19:19.217 に答える