- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
到目前为止,tvOS
支持两种制作电视应用程序的方法,TVML 和 UIKit,并且没有官方提及如何混合使用 TVML(基本上是 XML)用户界面应用程序逻辑和 I/O(如播放、流式传输、iCloud 持久性等)的 native 对应部分。
那么,在新的 tvOS
应用中混合 TVML
和 UIKit
的最佳解决方案是什么?
在下文中,我尝试了一个解决方案,该解决方案遵循从 Apple 论坛改编的代码片段以及有关 JavaScriptCore 到 ObjC/Swift 绑定(bind)的相关问题。这是您的 Swift 项目中的一个简单包装器类。
import UIKit
import TVMLKit
@objc protocol MyJSClass : JSExport {
func getItem(key:String) -> String?
func setItem(key:String, data:String)
}
class MyClass: NSObject, MyJSClass {
func getItem(key: String) -> String? {
return "String value"
}
func setItem(key: String, data: String) {
print("Set key:\(key) value:\(data)")
}
}
委托(delegate)必须符合 TVApplicationControllerDelegate
:
typealias TVApplicationDelegate = AppDelegate
extension TVApplicationDelegate : TVApplicationControllerDelegate {
func appController(appController: TVApplicationController, evaluateAppJavaScriptInContext jsContext: JSContext) {
let myClass: MyClass = MyClass();
jsContext.setObject(myClass, forKeyedSubscript: "objectwrapper");
}
func appController(appController: TVApplicationController, didFailWithError error: NSError) {
let title = "Error Launching Application"
let message = error.localizedDescription
let alertController = UIAlertController(title: title, message: message, preferredStyle:.Alert ) self.appController?.navigationController.presentViewController(alertController, animated: true, completion: { () -> Void in
})
}
func appController(appController: TVApplicationController, didStopWithOptions options: [String : AnyObject]?) {
}
func appController(appController: TVApplicationController, didFinishLaunchingWithOptions options: [String : AnyObject]?) {
}
}
至此javascript就很简单了就好了。查看带有命名参数的方法,您将需要更改 javascript 计数器部分方法名称:
App.onLaunch = function(options) {
var text = objectwrapper.getItem()
// keep an eye here, the method name it changes when you have named parameters, you need camel case for parameters:
objectwrapper.setItemData("test", "value")
}
App. onExit = function() {
console.log('App finished');
}
现在,假设您有一个非常复杂的 js 接口(interface)可以像这样导出
@protocol MXMJSProtocol<JSExport>
- (void)boot:(JSValue *)status network:(JSValue*)network user:(JSValue*)c3;
- (NSString*)getVersion;
@end
@interface MXMJSObject : NSObject<MXMJSProtocol>
@end
@implementation MXMJSObject
- (NSString*)getVersion {
return @"0.0.1";
}
你可以这样做
JSExportAs(boot,
- (void)boot:(JSValue *)status network:(JSValue*)network user:(JSValue*)c3 );
此时在 JS Counter 部分你不会做驼峰式大小写:
objectwrapper.bootNetworkUser(statusChanged,networkChanged,userChanged)
但是你要做的是:
objectwrapper.boot(statusChanged,networkChanged,userChanged)
最后再看看这个界面:
- (void)boot:(JSValue *)status network:(JSValue*)network user:(JSValue*)c3;
传入的值 JSValue* 是一种在 ObjC/Swift
和 JavaScriptCore
之间传递完成处理程序的方法。此时,在 native 代码中,您将使用参数进行所有调用:
dispatch_async(dispatch_get_main_queue(), ^{
NSNumber *state = [NSNumber numberWithInteger:status];
[networkChanged.context[@"setTimeout"]
callWithArguments:@[networkChanged, @0, state]];
});
在我的发现中,我发现如果不在主线程和异步上分派(dispatch),MainThread 将会挂起。因此,我将调用调用完成处理程序回调的 javascript“setTimeout”调用。
所以我在这里使用的方法是:
JSExportAs
处理带有命名参数的方法,避免使用 callMyParam1Param2Param3 等驼峰式 javascript 对应方法JSValue
作为参数来摆脱完成处理程序。在 native 端使用 callWithArguments。在 JS 端使用 javascript 函数;dispatch_async
用于完成处理程序,可能会在 JavaScript 端调用 setTimeout 0 延迟,以避免 UI 卡住。[更新]为了更清楚,我已经更新了这个问题。我正在寻找桥接 TVML
和 UIKit
的技术解决方案,以便
JavaScriptCode
的最佳编程模型JavaScriptCore
到 ObjectiveC
的正确桥梁,并且反之亦然Objective-C
调用 JavaScriptCode
时具有最佳性能最佳答案
这WWDC Video解释如何在 JavaScript 和 Obj-C 之间进行通信
这是我从 Swift 到 JavaScript 的通信方式:
//when pushAlertInJS() is called, pushAlert(title, description) will be called in JavaScript.
func pushAlertInJS(){
//allows us to access the javascript context
appController!.evaluateInJavaScriptContext({(evaluation: JSContext) -> Void in
//get a handle on the "pushAlert" method that you've implemented in JavaScript
let pushAlert = evaluation.objectForKeyedSubscript("pushAlert")
//Call your JavaScript method with an array of arguments
pushAlert.callWithArguments(["Login Failed", "Incorrect Username or Password"])
}, completion: {(Bool) -> Void in
//evaluation block finished running
})
}
这是我从 JavaScript 到 Swift 的通信方式(它需要在 Swift 中进行一些设置):
//call this method once after setting up your appController.
func createSwiftPrint(){
//allows us to access the javascript context
appController?.evaluateInJavaScriptContext({(evaluation: JSContext) -> Void in
//this is the block that will be called when javascript calls swiftPrint(str)
let swiftPrintBlock : @convention(block) (String) -> Void = {
(str : String) -> Void in
//prints the string passed in from javascript
print(str)
}
//this creates a function in the javascript context called "swiftPrint".
//calling swiftPrint(str) in javascript will call the block we created above.
evaluation.setObject(unsafeBitCast(swiftPrintBlock, AnyObject.self), forKeyedSubscript: "swiftPrint" as (NSCopying & NSObjectProtocol)?)
}, completion: {(Bool) -> Void in
//evaluation block finished running
})
}
[更新] 对于那些想知道“pushAlert”在 javascript 端是什么样子的人,我将分享一个在 application.js 中实现的示例
var pushAlert = function(title, description){
var alert = createAlert(title, description);
alert.addEventListener("select", Presenter.load.bind(Presenter));
navigationDocument.pushDocument(alert);
}
// This convenience funnction returns an alert template, which can be used to present errors to the user.
var createAlert = function(title, description) {
var alertString = `<?xml version="1.0" encoding="UTF-8" ?>
<document>
<alertTemplate>
<title>${title}</title>
<description>${description}</description>
</alertTemplate>
</document>`
var parser = new DOMParser();
var alertDoc = parser.parseFromString(alertString, "application/xml");
return alertDoc
}
关于objective-c - 如何将 TVML/JavaScriptCore 桥接到 UIKit/Objective-C (Swift)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33081565/
我正在阅读命令模式,并且看到来自不同站点的示例,这些示例似乎使用桥+命令模式来展示命令模式。 首先,来自维基百科:https://en.wikipedia.org/wiki/Command_patte
我有一个超低延迟程序,需要与 Windows COM 组件交互。最快的方法是什么?使用像 JACOB 这样的 COM 桥,或者编写 native COM 库并使用像 ZeroMQ 这样的消息传递总线发
我正在开发一个应用程序,该应用程序具有托管在 Glassfish 服务器上的 Java Web 界面和作为 Linux 守护进程实现的 C 内核。 我现在最大的问题是如何进行远程过程调用。我需要双向调
我已经在带有KVM的Fedora 17上设置了VM,并为KVM配置了桥接网络。主机和VM均使用手动IP配置,主机的IP为192.168.0.2,VM的为192.168.0.10。 从VM可以毫无问题地
主 GUI 基于 SWT。我正在通过单击按钮从 printPDF 类运行打印操作。 public void startPDFPrint() throws Exception { Display
我开始尝试使用 SWT-AWT 桥,但我无法为位于 Composite 内的 JPanel 找到合适的尺寸。谁能告诉我代码有什么问题吗? import java.awt.BorderLayout; i
这个问题在这里已经有了答案: 关闭 10 年前。 Possible Duplicate: Troubleshooting ClassNotFoundException when using PHP/
我对 Linux 很陌生,但我正在尽力学习。我们有CentOS 6的专用托管服务器。它配置了Apache服务器作为我们的公共(public)网站。现在我们需要在上面安装 PHP JAVA Bridge
关闭。这个问题需要更多focused .它目前不接受答案。 想改进这个问题吗? 更新问题,使其只关注一个问题 editing this post . 关闭 2 年前。 Improve this qu
有没有类似铁轨搭桥 Pylons 的脚手架?我一直在搜索谷歌,但只发现了这个叫做 dbsprockets 的东西,这很好,虽然可能对我的需要来说太多了。我真正需要的是基于 SQLAlchemy 模型的
我正在寻找可用于集成任何源代码控制管理系统的通用 git 桥(如 git-svn、git-p4、git-tfs)模板。 如果没有这样的模板,至少有一些关于如何在 git 端集成基本操作的说明(对于其他
我正在开发一个应用程序,我将在 UIWebView 中同时使用 HTML5 和 native iOS 框架。我知道我可以实现 JavaScript 和 Objective-C 之间的通信。是否有任何库
我目前观察到第 3 方库(即 restfb)正在使用 java.util.logging,我看到这些日志最终出现在 STDOUT 中,即使我没有在我的 logback 中配置 SLF4J 控制台附加程
我正在尝试让 aurelia-materialize 桥接插件工作,但到目前为止无法使用 jspm 完成,所以我尝试使用 webpack。我将 typescript-webpack 框架提取到一个文件
我想使用 java 将 SFTP 客户端连接到 FTP 服务器。我知道这两种技术彼此无关。我想要完成的是通过互联网连接到 FTP 服务器,而不使用两个端口或更改服务器配置。 Java 中有 SFTP-
我有 MS Access 数据库文件,文本字段中带有德语变音符号。当我尝试阅读它们时,我有字符串?字符而不是带有变音符号的字符。我尝试为数据库连接设置不同的字符集,例如 properties.setP
我感觉这是 wpf 中的一个错误。让我知道你们对此有何看法。 为了简单起见,我在 .net 4.0 中制作了演示示例 我有一个 ContentControl,其中 Content 绑定(bind)到
我正在尝试让 PHPJAVA 桥在我目前的 Apache2 设置上工作。 虽然,坦率地说,我不知道从哪里开始。 我已经下载了 JavaBridgeTemplate621.war,但不知道放在哪里。 感
我需要在 php 上运行一些 java 代码所以我找到了这个 http://php-java-bridge.sourceforge.net/pjb/index.php 所以我下载了tomcat,把Ja
我正在使用 OrientDb 并希望通过 PHP 运行 Gremlin 命令。有谁知道是否有任何桥梁或产品可以连接这两种语言? 虽然我知道 OrientDB-PHP 和 OrientDB-REST 包
我是一名优秀的程序员,十分优秀!