"TypeError: Undefined Is Not An Object" When Calling JS Function From Swift In TvOS App

- 1 answer

I am getting an error when calling a JS function from Swift in a tvOS app that has me stumped.

I have set up functions to call Swift from JS that work fine, but when trying to call a JS function from Swift I get the below error in the Safari debugger:

TypeError: undefined is not an object
(anonymous function)
-[JSValue callWithArguments:]
-[IKAppContext _doEvaluate:]
-[IKAppContext _evaluate:]
__41-[IKAppContext evaluate:completionBlock:]_block_invoke
-[IKAppContext _sourcePerform]
-[IKAppContext _jsThreadMain]

The relevant swift code is below:

//From JS to Swift
//call this method once after setting up your appController.
func createGetVimeoURL(){

    //allows us to access the javascript context
    appController?.evaluateInJavaScriptContext({(evaluation: JSContext) -> Void in

        //this is the block that will be called when javascript calls getVimeoURL(str)
        let getVimeoURL : @convention(block) (String) -> Void = {
            (videoName : String) -> Void in

            //5. return the vimeo url to the JS code for the passed in videoName

        //this creates a function in the javascript context called "getVimeoURL".
        //calling getVimeoURL(str) in javascript will call the block we created above.
        evaluation.setObject(unsafeBitCast(getVimeoURL, AnyObject.self), forKeyedSubscript: "getVimeoURL")
        }, completion: {(Bool) -> Void in
            //evaluation block finished running

//From Swift to JS
//when callPlayVideoInJS() is called, playVideo(url) will be called in JavaScript.
func callPlayVideoInJS(url : String){

    //allows us to access the javascript context
    appController!.evaluateInJavaScriptContext({(evaluation: JSContext) -> Void in

        //get a handle on the "playVideo" method that you've implemented in JavaScript
        let playVideo = evaluation.objectForKeyedSubscript("playVideo")

        //Call your JavaScript method with an array of arguments

        }, completion: {(Bool) -> Void in
            //evaluation block finished running

//4. getTempVimeoURL from videoName
func getTempVimeoURL (videoName : String) -> String {
        return  ""      

And the javascript function that should get called by swift (which I create manually):

playVideo: function (url) {
  if(url) {
    var player = new Player();
    var playlist = new Playlist();
    var mediaItem = new MediaItem("video", url);

    player.playlist = playlist;

The getVimeoURL javascript function is created when I call createGetVimeoURL in appController didFinishLaunchingWithOptions.

But I can't work out why I get the javascript error when I call callPlayVideoInJS, but it is probably something simple!

Any help appreciated.



It looks like you aren't accessing the appropriate JS method using objectForKeyedSubscript


let playVideo = evaluation.objectForKeyedSubscript("vimeoVideoURL")


let playVideo = evaluation.objectForKeyedSubscript("playVideo")

[UPDATE] You also need to make sure your playVideo method is accessible from the appropriate context and scope. Try putting your playVideo method in application.js:

var playVideo = function (url) {