javascript - 从 Java 脚本 (TVML) 调用带有完成处理程序的 Swift 函数

标签 javascript swift tvos tvml

我正在开发 tvOS 应用程序(使用 TVML),我正在尝试使用来自 JS 的完成处理程序调用 Swift 函数。

在 TVApplicationControllerDelegate 中,我尝试使用如下代码:

let getVastData : @convention(block) (String,  @escaping (UInt32, [String], String) -> ()) -> Void = {
    (url : String, _ completion:@escaping (_ duration: UInt32, _ addLinks: [String], _ videoLink: String) -> ()) -> Void in
    VastManager.shared.startParsing(with: url, completion)
}

jsContext.setObject(unsafeBitCast(getVastData, to: AnyObject.self), forKeyedSubscript: "getVastData" as (NSCopying & NSObjectProtocol)!)

但我收到错误:“TypeError:getVastData 不是一个函数。(在‘getVastData’中,‘getVastData’是 NSBlock 的一个实例”

你知道我错在哪里或如何使用 JS 的完成处理程序更正调用 Swift 函数吗?

提前致谢, 米洛斯

最佳答案

首先,我们需要在 jsContext 中注册我们的 Swift 方法。我们的 Swift 方法需要接受回调函数,在我们的例子中是对 JavaScipt 值的引用,它将在 Swift 中的操作完成后调用。

let getVastData : @convention(block) (String, JSValue) -> Void = {
    (url : String, completion : JSValue) -> Void in
    VastManager.shared.startParsing(from: url, completion: completion)
}
jsContext.setObject(unsafeBitCast(getVastData, to: AnyObject.self), forKeyedSubscript: "getVastData" as (NSCopying & NSObjectProtocol))

因为我们想异步调用它,所以我们需要存储该引用。我们将使用 JSManagedValue 来存储 JSValue 以避免循环引用。 JSManagedValue 对象包装 JSValue 对象,添加“条件保留”行为以提供值的自动内存管理。在我们的操作完成后,我们可以用参数调用我们的 JavaScript 回调函数。简而言之,我们只是将 JS 值从我们的 TVML JS 传递给 Swift,存储它并稍后调用它。

class VastManager: NSObject {

    var completion: JSManagedValue?
    var url: String?

    public func startParsing(from url: String, completion: JSValue) {
        self.completion = JSManagedValue(value: completion)
        self.url = url
    }
    ...

    func parserDidEndDocument(_ parser: XMLParser) {

        ...

        _ = self.completion?.value?.call(withArguments: [duration, ads, videoUrl])
    }
}

最后,我们可以从 JavaScript 调用我们的 Swift 函数并传递我们的回调函数。

getVastData(vastTag, function(duration, adLinks, videoLink) {
   ...
}
// or
function updatePlayer(duration, adLinks, videoLink) {
   ...
}
getVastData(vastTag, updatePlayer) {
   ...
}

关于javascript - 从 Java 脚本 (TVML) 调用带有完成处理程序的 Swift 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45235021/

相关文章:

javascript - $(item).load() 脚本中断(仅在 IE11 中),适用于开发人员工具

javascript - 在字符串中放置破折号

javascript - 完整的背景图像最初是固定的,然后在 DIV 内容结束时滚动

ios - 如何以编程方式添加多个导航 Controller ?

tvos - TVCardView 的 focusSizeIncrease 不起作用?

javascript - 使用CSS(或JavaScript)代替SMIL

ios - 自动解析导入的图像,存储在 Core Data 中

ios - SKNode.nodesAtPoint 的顺序有保证吗?

swift - tvOS:从 Swift 调用 JavaScript 以实现 TVML 应用程序

xcode - Apple TV 没有出现在 Xcode > 设备和模拟器菜单中