"TypeError: undefined is not an object" when calling JS function from Swift in tvOS app
"TypeError: undefined is not an object" when calling JS function from Swift in tvOS app
在 tvOS 应用程序中从 Swift 调用 JS 函数时出现错误,这让我很困惑。
我已经设置了从 JS 调用 Swift 的函数,但当我尝试从 Swift 调用 JS 函数时,我在 Safari 调试器中收到以下错误:
TypeError: undefined is not an object
(anonymous function)
JSValueToObject
-[JSValue callWithArguments:]
_TFFC13tvOSShortGame11AppDelegate17callPlayVideoInJSFS0_FSST_U_FCSo9JSContextT_
_TTRXFo_oCSo9JSContext_dT__XFdCb_dS__dT__
-[IKAppContext _doEvaluate:]
-[IKAppContext _evaluate:]
__41-[IKAppContext evaluate:completionBlock:]_block_invoke
-[IKAppContext _sourcePerform]
IKRunLoopSourcePerformCallBack
__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__
__CFRunLoopDoSources0
__CFRunLoopRun
CFRunLoopRunSpecific
CFRunLoopRun
-[IKAppContext _jsThreadMain]
__NSThread__start__
_pthread_body
_pthread_body
thread_start
相关swift代码如下:
//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
self.getTempVimeoURL(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
playVideo.callWithArguments([url])
}, completion: {(Bool) -> Void in
//evaluation block finished running
})
}
//4. getTempVimeoURL from videoName
func getTempVimeoURL (videoName : String) -> String {
return "http://techslides.com/demos/sample-videos/small.mp4"
}
以及应该由 swift(我手动创建)调用的 javascript 函数:
playVideo: function (url) {
if(url) {
//2
var player = new Player();
var playlist = new Playlist();
var mediaItem = new MediaItem("video", url);
player.playlist = playlist;
player.playlist.push(mediaItem);
player.present();
}
}
getVimeoURL javascript 函数是在我在 appController didFinishLaunchingWithOptions 中调用 createGetVimeoURL 时创建的。
但我无法弄清楚为什么在调用 callPlayVideoInJS 时会出现 javascript 错误,但这可能很简单!
感谢任何帮助。
您似乎没有使用 objectForKeyedSubscript
访问适当的 JS 方法
改变
let playVideo = evaluation.objectForKeyedSubscript("vimeoVideoURL")
至
let playVideo = evaluation.objectForKeyedSubscript("playVideo")
[更新]
您还需要确保可以从适当的上下文和范围访问您的 playVideo 方法。尝试将您的 playVideo 方法放在 application.js:
var playVideo = function (url) {
...
在 tvOS 应用程序中从 Swift 调用 JS 函数时出现错误,这让我很困惑。
我已经设置了从 JS 调用 Swift 的函数,但当我尝试从 Swift 调用 JS 函数时,我在 Safari 调试器中收到以下错误:
TypeError: undefined is not an object
(anonymous function)
JSValueToObject
-[JSValue callWithArguments:]
_TFFC13tvOSShortGame11AppDelegate17callPlayVideoInJSFS0_FSST_U_FCSo9JSContextT_
_TTRXFo_oCSo9JSContext_dT__XFdCb_dS__dT__
-[IKAppContext _doEvaluate:]
-[IKAppContext _evaluate:]
__41-[IKAppContext evaluate:completionBlock:]_block_invoke
-[IKAppContext _sourcePerform]
IKRunLoopSourcePerformCallBack
__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__
__CFRunLoopDoSources0
__CFRunLoopRun
CFRunLoopRunSpecific
CFRunLoopRun
-[IKAppContext _jsThreadMain]
__NSThread__start__
_pthread_body
_pthread_body
thread_start
相关swift代码如下:
//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
self.getTempVimeoURL(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
playVideo.callWithArguments([url])
}, completion: {(Bool) -> Void in
//evaluation block finished running
})
}
//4. getTempVimeoURL from videoName
func getTempVimeoURL (videoName : String) -> String {
return "http://techslides.com/demos/sample-videos/small.mp4"
}
以及应该由 swift(我手动创建)调用的 javascript 函数:
playVideo: function (url) {
if(url) {
//2
var player = new Player();
var playlist = new Playlist();
var mediaItem = new MediaItem("video", url);
player.playlist = playlist;
player.playlist.push(mediaItem);
player.present();
}
}
getVimeoURL javascript 函数是在我在 appController didFinishLaunchingWithOptions 中调用 createGetVimeoURL 时创建的。
但我无法弄清楚为什么在调用 callPlayVideoInJS 时会出现 javascript 错误,但这可能很简单!
感谢任何帮助。
您似乎没有使用 objectForKeyedSubscript
访问适当的 JS 方法改变
let playVideo = evaluation.objectForKeyedSubscript("vimeoVideoURL")
至
let playVideo = evaluation.objectForKeyedSubscript("playVideo")
[更新] 您还需要确保可以从适当的上下文和范围访问您的 playVideo 方法。尝试将您的 playVideo 方法放在 application.js:
var playVideo = function (url) {
...