到目前爲止tvOS
支持兩種製作電視應用,TVML和UIKit的方式,並且沒有官方提及如何混合使用TVML(基本上是XML)的用戶界面和用於應用邏輯的本機計數器部分和I/O(如播放,流媒體,iCloud持久性等)。如何將TVML/JavaScriptCore橋接到UIKit/Objective-C(Swift)?
那麼,哪個是最好的解決方案,將TVML
和UIKit
混合在一個新的tvOS
應用程序中?
在下面,我嘗試了一個解決方案,下面的代碼片段改編自Apple論壇和有關JavaScriptCore到ObjC/Swift綁定的相關問題。 這是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)")
}
}
其中委託必須遵循一個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接口,像出口
@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計數器部分這一點上,你不會做的駱駝情況:
objectwrapper.bootNetworkUser(statusChanged,networkChanged,userChanged)
,但你要做的:
objectwrapper.boot(statusChanged,networkChanged,userChanged)
最後,再看看這個接口:
- (void)boot:(JSValue *)status network:(JSValue*)network user:(JSValue*)c3;
值JSValue *傳遞的是一種方式來傳遞ObjC/Swift
之間完成處理和JavaScriptCore
。在本機代碼這一點你都帶參數調用:
dispatch_async(dispatch_get_main_queue(), ^{
NSNumber *state = [NSNumber numberWithInteger:status];
[networkChanged.context[@"setTimeout"]
callWithArguments:@[networkChanged, @0, state]];
});
在我的發現,我已經看到,如果你沒有在主線程和異步的調度MainThread將掛起。所以我會調用調用完成處理程序回調的javascript「setTimeout」調用。
所以我在這裏使用的方法是:
- 使用
JSExportAs
採取與命名參數方法的汽車,並避免給JavaScript同行一樣callMyParam1Param2Param3 - 使用
JSValue
作爲參數擺脫完成的駱駝處理程序。在本機端使用callWithArguments。在JS端使用javascript函數; dispatch_async
對於完成處理程序,可能會調用setTimeout 0在JavaScript端延遲,以避免UI凍結。
[更新] 我已經爲了更新這個問題更加清晰。我發現一個技術解決方案,以彌合TVML
和UIKit
到
- 瞭解最佳的編程模型
JavaScriptCode
- 有從右邊橋
JavaScriptCore
到ObjectiveC
和 反之亦然 - 有最好的表現時,打電話給
JavaScriptCode
從Objective-C
據我所知,這不是一個問題。如果你發現了一些你想分享的有用信息,請[提問並回答你自己的問題](http://stackoverflow.com/help/self-answer)。另外,我認爲這個話題已經在[tag:tvos]或[tag:apple-tvos]的某處出現了,所以你可能不需要問一個新問題,只需回答一個問題。 – rickster
@rickster如果我會找到這個問題的答案,我會回答它,但到目前爲止沒有。沒有關於「tvOS」和「TVML + UIKIT」的具體問題,所以我不明白你的觀點。是的,也許問題不清楚,我可以指定更好。你的答案是「不具有建設性」,因爲'''tvOS'''是一種全新的技術,對Stackoverflow知之甚少。當然,這是我的觀點,我敢肯定,無論如何這個問題是「建設性的」。 – loretoparisi
如果這篇文章不是試圖提供信息,而且實際上是一個問題......目前還不清楚你想問什麼。也許你可以編輯,使問題更清楚。 – rickster