David Cordero

iOS and tvOS developer at @Zattoo. Amateur Triathlete. Passionate about coding and lifelong learning.

Extending TVML with Custom Templates

07 Jun 2018 » swift, tvos

TVML templates are the base of every App based on TVMLKit. They ease the creation of Apps following the UI patterns of tvOS.

Apple provides a set of TVML templates, exactly 18 of them: alertTemplate, catalogTemplate, compilationTemplate, descritiveAlertTemplate, divTemplate, formTemplate, listTemplate, loadingTemplate, mainTemplate, menuBarTemplate, oneupTemplate, paradeTemplate, productBundleTemplate, productTemplate, ratingTemplate, searchTemplate, showcaseTemplate and stackTemplate

The divTemplate is by far the most flexible one. It basically allows throwing into it most of the TVML components and to align them with a high level of flexibility. But it also has some limitations, for example not being scrollable.

So, what to do if none of the templates provided by Apple fits our requirements?

For example, let’s imagine that we would like to create the following screen in our App.

image

This is a good example of a very simple screen, that could not be easily represented with any of the 18 templates provided by Apple.

So, at this point we would have two options:

  • To create a hybrid App, mixing up TVML and UIKit, as we saw in [TVML and UIKit as happy roommates](https://medium.com/@dcordero/tvml-and-uikit-as-happy-roommates-15e204ad46ba)

  • To create our custom TVML Template, as we will see right now.*

    ** This second method has not been officially documented by Apple. This post is the result of some investigation with the public API of TVMLKit. On the other hand, this has been validated and approved as a legitimate method by Apple Engineers in WWDC Labs 2018 and it was described as something that they would like to document officially in the near future.*

Creation of our screen as ViewController

The first step would be to create the desired screen using UIKit, which is a very easy task using a UITableView or even UITableViewController if you wish.

You can find below a possible implementation based on UITableView:

<iframe src=”https://medium.com/media/3955b874da4ec9a4c63d5252c407ec12” frameborder=0></iframe>

Notice that due to the fact that UITableViewCells are barely customizable in tvOS, I made use of TvOSCustomizableTableViewCell to get the desired layout.

TVInterfaceFactory and TVInterfaceCreating

Once that we created a ViewController to represent the desired screen, the next step would be to expose it as a TVML template.

Whenever we need to extend TVML, TVInterfaceFactory (implementing TVInterfaceCreating) is the way to go.

So let’s start creating our custom subclass of TVInferfaceFactory from which we will return an instance of our viewController, whenever TVMLKit asks for it with via its template name (greetingSelectorTemplate).

<iframe src=”https://medium.com/media/9cd53893b101d6697f07413b20658acc” frameborder=0></iframe>

(Notice that a previously created instance might be received in the parameter existingViewController for its reusability.)

We also need to inform the system about the existence of our custom TvInterfaceFactory. To do so, we need to define extendedIntefaceCreator in the shared instance of TvInterfaceFactory.

This should be done only once, so it might be added to AppDelegate, for example.

<iframe src=”https://medium.com/media/1c9b56aeb895ba3576e351201b1e57b3” frameborder=0></iframe>

And that is all that we need to do. From now on we can create a TVML document using our custom template id (**greetingSelectorTempale) **getting as a result our brand new custom ViewController.

<?xml version="1.0" encoding="UTF-8" ?>
<document>
  <greetingSelectorTemplate>
  </greetingSelectorTemplate>
</document>

Custom TVML attributes and styles

So far, we are able to present a ViewController implemented in UIKit as a TVML template, but it will be always presented with exactly the same appearance, without any option to customize its layout and with the same listed elements on it.

Let’s iterate our example to support the customization of the title with a value provided from TVML:

override func makeViewController(element: TVViewElement, existingViewController: UIViewController?) -> UIViewController? {

    guard element.name == CustomInterfaceFactory.templateName else { return nil }
    let greetingsViewController = GreetingSelectorViewController()

    if let title = element.attributes?["title"] {
      greetingsViewController.title = title
    }

return greetingsViewController
}

And that is all that we need to do, from now on we can customize the title of our template from our TVML document, by just adding a title property to its definition.

<?xml version="1.0" encoding="UTF-8" ?>
<document>
  <greetingSelectorTemplate title="My custom Title">
  </greetingSelectorTemplate>
</document>

Further customization

Our custom template is now like any other native template. That means that we could customize it in the same way as the templates provided by Apple.

So, apart from customizing the title, we might add internal elements or styling attributes. It is out of the scope of the current post, nevertheless if you are interested about this, I strongly recommend this great post by Alex Guretzki.

Show me the code

In the following URL, you can find an example of a custom TVML Template (confettiTemplate), using the method previously described:

https://github.com/dcordero/CustomTVMLTemplate

Conclusion

TVML is a quite limited framework, and it is easy to face its limitations on the first steps of your project, especially when trying to represent some information in a different way than its set of predefined templates.

Nevertheless, as we have seen, this should not be a limitation, and we could create our custom suite of templates matching our desired layouts.

If we do it properly, thinking of reusability, we might end up with a very useful set of custom templates that could save a lot of time in future developments.

Feel free to follow me on github, twitter or dcordero.me if you have any further question.