How to mix UIKit and TVMLKit within one app?
Question
I’m exploring tvOS
and I found that Apple offers nice set of templates written using TVML
. I’d like to know if a tvOS
app that utilises TVML
templates can also use UIKit.
Can I mix UIKit and TVMLKit within one app?
Answer One
Yes, you can. Displaying TVML templates requires you to use an object that controls the JavaScript Context: TVApplicationController
.
1 | var appController: TVApplicationController? |
This object has a UINavigationController
property associated with it. So whenever you see fit, you can call:
1 | let myViewController = UIViewController() |
This allows you to push a Custom UIKit viewcontroller onto the navigation stack. If you want to go back to TVML Templates, just pop the viewController off of the navigation stack.
If what you would like to know is how to communicate between JavaScript and Swift, here is a method that creates a javascript function called pushMyView()
1 | func createPushMyView(){ |
Once you call createPushMyView()
in Swift, you are free to call pushMyView()
in your javascript code and it will push a view controller onto the stack.
Answer Two
If you already have a native UIKit app for tvOS, but would like to extend it by using TVMLKit for some part of it, You can.
Use the TVMLKit as a sub app in your native tvOS app. The following app shows how to do this, by retaining the TVApplicationController
and present the navigationController
from the TVApplicationController
. The TVApplicationControllerContext
is used to transfer data to the JavaScript app, as the url is transferred here :1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24class ViewController: UIViewController, TVApplicationControllerDelegate {
// Retain the applicationController
var appController:TVApplicationController?
static let tvBaseURL = "http://localhost:9001/"
static let tvBootURL = "\(ViewController.tvBaseURL)/application.js"
func buttonPressed(_ sender: UIButton) {
print("button")
// Use TVMLKit to handle interface
// Get the JS context and send it the url to use in the JS app
let hostedContContext = TVApplicationControllerContext()
if let url = URL(string: ViewController.tvBootURL) {
hostedContContext.javaScriptApplicationURL = url
}
// Save an instance to a new Sub application, the controller already knows what window we are running so pass nil
appController = TVApplicationController(context: hostedContContext, window: nil, delegate: self)
// Get the navigationController of the Sub App and present it
let navc = appController!.navigationController
present(navc, animated: true, completion: nil)
}
Reference
This is the end of post