На данный момент tvOS
поддерживает два способа создания телевизионных приложений, TVML и UIKit, и нет официальных упоминаний о том, как смешивать вещи, чтобы создать пользовательский интерфейс TVML (то есть в основном XML) с родной частью для логики приложения, и я /O (например, воспроизведение, потоковая передача, сохранение iCloud и т. д.).
Итак, как лучше всего сочетать 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 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
. В этот момент в нативном коде вы делаете все вызовы с аргументами:
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 на собственной стороне. Используйте функции javascript на стороне JS; dispatch_async
для обработчиков завершения, возможно вызывая setTimeout 0-delayed на стороне JavaScript, чтобы избежать зависания пользовательского интерфейса.
[ОБНОВЛЕНИЕ] Я обновил этот вопрос, чтобы сделать его более понятным. Я нахожу техническое решение для соединения TVML
и UIKit
, чтобы
- Поймите лучшую модель программирования с
JavaScriptCode
- Иметь правый мост от
JavaScriptCore
доObjectiveC
и наоборот - Наилучшие результаты при вызове
JavaScriptCode
изObjective-C
tvOS
иTVML + UIKIT
нет, поэтому я не понимаю вашу точку зрения. Да, возможно вопрос не ясен, и я мог бы уточнить. Ваш ответ не является конструктивным, посколькуtvOS
— это совершенно новая технология, в которой мало знаний о Stackoverflow. Конечно, это моя точка зрения, я уверен, что вопрос в любом случае конструктивен. - person loretoparisi   schedule 26.10.2015