[ Music ]
Good afternoon everyone and welcome
to app development using TVMLKit Part 2.
There are many amazing apps out there
on the App Store based on TVMLKit.
And some have even been customized with styles
to give a unique experience and branding for all your apps.
So today I'm extremely excited to be talking to you,
to tell how you could bring your apps to a whole other level.
And this is done by extending TVMLKit by extending interfaces
This will basically let your app stand out even more
with all your own unique branding.
TVMLKit is a thoughtful framework, we've also tried
to make sure that there is some thought in how it's structured
as such that only two extension points
that you have to worry about.
In the first half of the talk I'm going
to tell you guys how you can extend the user interface
in TVMLKit by extending templates.
In the second half, my colleague Christopher will be explaining
how you can enhance your apps by adding application functionality
So, let's talk about extending templates.
The very first thing that everyone encounters
when they use TVMLKit is this idea of templates,
these are defined in the TVML, TV mark-up language.
They use XML as a way to describe what's on the screen
and when people encounter this, they start by saying huh,
I know this this is a web browser.
I can assure you we are absolutely not a web browser.
What TVMLKit is however, is a powerful templating engine,
but that doesn't mean you are limited to what we provide.
In fact, Apple's own apps use TVMLKit but extend it
in really subtle ways that allow it to coexist with the rest
of the framework and still feel right on tvOS.
Let's look at, take a look at an example,
this is the App Store app.
The App Store theme had a requirement for a unique cell
within a shelf, as you can see they have reused what TVMLKit
provides, an image and three labels.
But over here they have a custom layout
with custom focused behaviors.
Another example that we are all really familiar
with is the concept of the Buy button.
Once again the App Store theme had a requirement
that this button had to reflect the various installation states
of an app.
Whether you're buying the app,
whether the app is being installed or downloaded,
they did all these by reusing what TVMLKit provides.
And that's the common theme we want to stress to you today.
Reuse TVMLKit as much as possible and extend
for the parts that we do not provide.
If you've used TVMLKit it follows a set path when it,
when you inject it into the framework it ends
up on the screen.
TV mark-up language is consists of multiple elements,
all with unique names.
And when it enters the framework it goes to the TVElementFactory.
This is the central registry that knows about all elements
and is able to translate that into data structures
that the rest of the framework understands.
The TVInterfaceFactory is the class we use
to generate user interfaces
and place them currently on the screen.
And this is how TVML ends up on your screen.
So let's look at what happens when we extend templates.
When it comes to extension of templates, it's as simple
as adding your own mark-up in the TVML that you send to us.
It goes through the same process,
it enters the element factory, gets translated,
but when it hits the TVInterfaceFactory,
because we do not know
about your user interfaces, we'll ask you for it.
When you've given us the user interface the TVInterfaceFactory
will put it on the screen itself, very simple.
So now that you have an idea of how everything works,
let's look at things in detail.
There are three steps that you have to worry
about when you want to extend templates,
and the very first thing is to define mark-up.
Mark-up in TVML is basically XML.
And you have an idea of what your user interface looks
like on the screen.
You have to translate that into a structure that kind
of resembles what it should appear
on the screen in mark-up itself.
In our example, we wanted a banner on the stackTemplate.
This banner had an animated background and if you wanted
to be able to control the animations using a switch,
Therefore, this element,
myBanner has a property called animated.
Additionally, we also wanted a button,
but because there is no requirement
for additional functionality,
we could just use what TVML provides,
and this is a form of a button.
So now that you have an idea
of what your user interface is represented in mark-up you have
to tell the framework about it.
And this is as simple
as registering your unique element name with us.
Registration has to be done once before application controller
startup so that we're fully aware of all the elements
that we have to take care of.
It's as simple as telling the TVElementFactory that you want
to associate a TVViewElement class
and your custom, element name.
The TVViewElement is the base data structure that we use
to translate your mark-up into something that the rest
of the framework understands.
Along with TVViewElement,
there are two other subclasses that we use.
TVImageElement deals with images specifically
and TVTextElement has special handling for text itself.
Now that we have registered the elements, this is the next step,
the third step that involves a little work on your end,
but still we try to keep things simple,
with only just two steps.
The very first thing you have to do is
to setup an interface creator that conforms
to the TVInterfaceCreating protocol.
This particular object is the one
that vends your user interface when we ask for it
and there are some call back methods that you have
to implement from the TVInterfaceCreating protocol
declaration that pertains to what sort
of UI you want to return.
The next step is when we call
into your interface creator class,
configure your user interface and return it to us.
As I stressed before, reuse TVMLKit as much as possible
because we have done a lot of work to ensure
that our elements are performing and look
and feel good onto tvOS.
So let's take a look at an example
of what this interface creator looks like.
Over here I have a MyInterfaceCreator class
that conforms to TVInterfaceCreating.
Because we are only interested vetting a view
for the better we are going to implement the makeView element,
existingView call back method.
Once this class has been set up, all you have to do is
to register an instance of it with the TVInterfaceFactory.
Looking at makeView in detail,
we can see that TVMLKit furnishes you with an element
and a optional existingView.
So in the case of the banner, we just need
to inspect the element name itself.
We're particularly interested in the myBanner element name
and when we find something like that,
we create an instance of this view.
Because the myBanner has an element property we can easily
inspect this using the element
that the call back method provides
and then assign it to the view itself.
We also know that we have a button in the view,
and because this is a TVMLKit button, it's as simple
as asking the TVInterfaceFactory for this particular element
and returning the view to all myBanner view.
Finally of course, return your view.
In the case of default framework behavior,
you have to return nil.
Now we've talked a lot about views,
what about view controllers?
TVMLKit has view controllers and they are exposed in a form
of a shelf lockups that expands horizontally or a grid
that expands vertically.
So by using the TVMLKit call back
to return view controllers you can substitute these
for your own view controllers.
The usage is similar to makeView and in this case,
we still furnish you with an element
but an existingViewController
and we expect an existingViewController
to be returned.
Now you're thinking, Aha!
Collection of views.
Collection of views has views that are cells,
so this is how I can customize my own lockups.
Remember this example?
The App Store theme specifically only had a requirement
to have a unique cell.
Of unique custom layouts and focus behaviors,
everything else, as you can see, is extended to UMLKit shelf.
The titles go up and down depending
on whether the focus is on the element beneath it.
So, new in tvOS 10, we are allowing you
to specify your own custom collection view cell.
This allows you to have custom layouts for the cell
and most importantly participate in focus events
when the cell comes into focus.
To do this there are two things you need to do.
The very first thing is to use this new API that we're exposing
that allows you to give us a collectionView CellClass
when we ask for it for a particular element.
And when we build the user interface on the screen,
we would use makeView to allow you to customize,
configure the cell and return it to us.
We would provide you the custom collection view cell that's deep
queued from the collection view using the existing view
So I'd like to invite Parry on stage to give a demonstration
of how this works, Parry.
Thank you, Jeremy.
Hi, my name is Parry and I'm going to demo you how
to use custom cells in TVMLKit.
Now custom cells are really nice,
if you want to use TVMLKit collections like shelves
and grids, but you want to add your own cell
to showcase your content through a custom layout
and focus mechanism.
So I'm going to show you a sample app
that I am working on based on TVMLKit.
And then later on, I'm going to enhance it with custom cells
to make appear better.
So let's get to it.
So I'm going to switch over to my computer,
and I have here Xcode project open for my application
that I'm working on based on TVMLKit.
Now let me talk about this application.
It's an app that lets users browse through their photos.
and the associated XML files are actually hosted on my machine,
and let me go over them right in front of you.
So here's one of the pages from that app that is going
to showcase user's photo albums.
Now you can see it's a stacked template that has a nice banner
with a background image, and it has a shelf
to showcase the albums and each album is basically represented
by a lockup.
Now each one of these lockups embeds an image
from the album that it represents.
Other than some custom styling
to make this lockup a little bigger,
I have not customized TVMLKit at all.
So it's kind of out of stock TVMLKit app.
So let's run this real quick
and see what it looks like right now.
And for that I'm going to switch over to Apple TV.
So there's the app, that's the stacked template document
that I talked about.
So you see the nice banner on the top
and the shelf at the bottom.
And you know, I have to say just
out of the box it looks pretty nice.
It's functional and the bigger lockups do make a lot
But I think it can be a little better.
So, consider this, how about instead of just taking one photo
from the album, to represent it on this page.
What if we chose multiple photos, featured photos
from that album, and use that to put the album on this document?
Now I'm going to just think about it a little.
How about we create a collage of these photos
when the album is not focused, and then fly them
out into a nice grid when the album does get focused?
That will be cool.
But more than that, it'll give a nice context to the user
of what the album is about.
Because the user gets to see more photos from the album.
Now this is a really nice use case
for having custom cells with TVMLKit.
So let me show you how to do it.
So I'm going to switch back, to my computer
and the first thing I want
to do is create a mark-up spec for what I just said.
It's kind of a translation of what your visual representation
of your user interface is in terms of an XML
that TVMLKit can understand.
So I have that here right now, and as you can see,
it's again a stacked template that has a shelf,
but instead of lockups, it has a new element
that I have created called FlyoutCell.
That's the cell that I just described.
I'm calling it flyout because the images just fly out from it.
And as mentioned in the description,
I want multiple photos in this cell, hence,
I have multiple image elements as children.
Now there's one important thing to note,
is that for all custom cells, they have to be accompanied
with three styles, and they are width, height,
and a new style we've added into tvOS 10 called TV focus margin.
Now TVMLKit uses width and height
to give your cells a nice frame, in the collection.
And it uses TV focus margin as a hint
to know how much your cell is going
to grow when it gets focused.
It uses this information to create nice spacing
between shelves, and also to readjust the shelf header
when the cell underneath it gets focused.
So now that we have the spec, what's the next step?
We know we have to add this new element into TVMLKit,
so let's do that real quick.
So for that I'm going to head over to AppDelegate
and in the method application didFinishLaunching WithOptions.
I'm going to quickly drop the code
that I wrote earlier, to do just that.
So using this I've just added my FlyoutCell,
using TVElementFactory to TVMLKit.
Now TVMLKit also wants me to enhance the interface creator
by extending it, so that I can configure my cell myself, right.
So let's do that real quick as well.
So, that's all the configuration required for TVMLKit,
now let's have a look at the implementation of these classes,
starting off with the ExtendedInterfaceCreator.
Now for custom cells you need to implement two APIs.
First, the collectionViewCellClass,
this is required to map your custom elements
to the collectionViewCellClass you want to use for it.
And second, makeView, this one is required
to configure your cell with your element.
So let's quickly fill in these blanks, with a bit of code
that I've written before.
So there goes the mapping for my custom cell
with the collectionViewCellClass that I want to use for it.
And similarly, the mapping to configure
that collectionViewCell with my element.
Now an important thing to note here is
that the existing view parameter would always be valid,
because TVMLKit just dequeued it
from the collection view to get it configured.
So it's always going to be there, for custom cells.
Now before I jump into the configuration of my flyout cell,
let's have a look at the FlyoutCell class itself.
So that's the FlyoutCollectionViewCell class
that I'm using to represent my flyoutCell.
And as you can see, it basically subclasses a
UICollectionViewCell, in itself, it's got nothing to do
with TVMLKit, it's just a cell class.
I can use it in a native app or any other app.
The important point to note here is that it accepts an array
of image views that it uses to configure its contents.
And these image views are the ones that we want to configure
in our extended interface creator
from the TV view element.
So let's head back to extended interface creator
and add that code.
So that's the configuration, it's not much,
but the important part here is this.
I am trading over all the children of the element
and extracting the image elements out of it
and simply reusing TVMLKit to create an image view for me.
Now out of the box, this is really,
really good because what it gives me is downloading
of remote images, it gives me scaling and cropping
to fit the bounds so that the user interface is performing.
And it also gives me some caching
in case I reuse those images somewhere else.
So reusing these TVMLKit views,
and other infrastructure is really beneficial.
I highly encourage it.
So, with that we've configured all the code and everything
in TVMLKit knows about our element.
There's only one thing remaining to do, which is to go back
to the stacked document that I showed earlier,
and replace all the lockups with the FlyoutCell
that I have just added.
So I'm going to head back there, remove all of these lockups,
and add my FlyoutCell.
Now there were three albums,
there are three FlyoutCells still,
each FlyoutCell has, four images in it.
And when you add these cells, don't forget to add the style
as well, that's required, it's a must.
So now that we've added everything, let's rerun this app
and see what it looks like now.
So I'm going to switch over to Apple TV,
and there's the flyout cell.
And you can immediately tell it looks so much better,
then just having one image, it just looks
so much more immersive.
And notice that the cell just fits into TVMLKit,
all the spacing is right, even the header, the album,
it moves up and down as the cell underneath it gets focused.
It just feels like it belongs inside TVMLKit,
although you added it.
So there you have it, custom cells are really easy
to implement, and it lets you add a lot of value
to your application, by reusing what TVMLKit provides
but by also showcasing your content in the way you want.
Thank you, Parry.
I think Parry spend more time building the FlyoutCell
than actually configuring TVMLKit for that.
So before we continue, I'd like to do a quick recap
of what we've seen today.
The very first thing when it comes to extending templates is
to define a custom mark-up that describes your user interface.
Register it with a TVElementFactory so we know
about it and are able to translate it
into TV view elements.
Provide an extended interface creator
so that you can vend this user interface whenever we stop
building the UI on the screen.
And most importantly, use the TVViewElement and its properties
and attributes to configure your user interface before displaying
it on the screen.
So that's all there is
to extending templates, it's really simple.
And we are all really excited
to see what you can build with this.
But before we continue, there are a few important things
that we want you to know.
Your user interface is represented by elements
within the document in TVML.
And this document can be updated at any time.
Take for example a shelf with lockups
as results, in a search template.
and the contents will change,
that's what a document update is.
Now, when we build the user, rebuild the user interface
when document updates happen, we would call into the,
extended interface creator, and it is your job to look
at the update type in the element
and figure out what's changed.
For example, the children might change, and as a good parent,
you don't really want to throw away children,
because that's not a nice thing to do [laughter].
Instead, reuse cells, reuse views as much as possible.
In our initial example for returning the banner,
we weren't really being a good citizen
in the TVMLKit ecosystem, we didn't reuse views at all.
Let's see if we can change this.
It's as simple as changing two lines of code,
in this case we look at the existingView that's part
of the call back and we try to figure
out if this view is a view that we expect,
in this case a MyBanner view.
If it's not, we instantiate a new copy of it.
Now because we have a TVMLKit button, based on TVMLKit,
we have to do the right thing as well, and reuse it by passing it
to the extended, by passing it to the TVInterfaceFactory, in,
the existing view parameter.
Now in this particular example,
because MyBanner is a really simple view,
that is totally fine to update it all the time,
we don't really look at the update type.
But if your view hierarchy is way more complex.
For performance reasons, we highly encourage you to look
at the update type and figure out what has changed.
That's the first line that you have to change and the second.
Now, new in tvOS 10 is this concept
of light and dark appearance.
If you have a custom view that you're using with TVMLKit,
you can listen to trait collection changes to figure
out if you're in light or dark.
We have a session, What's New in tvOS
that absolutely explains what you must do,
and I highly encourage you to check that out.
In the case that you are a good citizen of TVMLKit
and you reuse our components, thank you very much.
We highly encourage you to check the style update hint
from the element update type.
This gives you an idea of whether your view is
in the light or dark appearance,
and this reuses the document update facility
and it's the only avenue available for you
to update your views for light or dark appearance.
Because they are TVMLKit components you have
to reuse them.
And more importantly, you have to forward
into the TVInterfaceFactory so we can do the right thing.
If you have a native app
or rather you have your own view controllers
and you have a TVMLKit based application, you can mix them
with the framework itself.
This is as simple as defining a custom template element,
once again registering it with element factory.
And where we built the user interface
for a particular template via loading,
return your view controller and you're all set to go.
Another way to use TVMLKit with your existing apps, native apps,
is by hosting the navigation controller
that we provide, as a sub application.
You've already learned how
to create a TV application controller,
and I'd like to highlight that in this case you do not have
to specify a window, because you already have one.
Choose the view controller that you're presenting
in navigation controller with.
Once you have a TV application controller,
take its navigation controller and present it.
An alternative to this is to use an instance of UIWindow,
and in this particular example, you would have
to specify the window parameter.
TVMLKit will do the right thing
and bring your window key invisible.
And with that, I'd like to hand over the time to Christopher,
to talk to you about how you can extend application functionality
Hi, I'm Christopher, I'm a TVMLKit engineer.
So we just saw how you can extend the templating engine
in TVMLKit to use custom mark-up,
implement your own views, view controllers,
and collection view cells.
You can also extend the scripting engine of TVMLKit
to implement your own app specific functionality
There are three main ways to inject code
of your TVML application, let's take a look.
at run time.
Second, you can use native code to interact directly
and forth between environments.
Third, you can take native classes
to make them accessible to your scripts using some simple class
Let's go into detail into each one
of these methods starting with the simplest.
When your TVML application loads,
the first thing that's going to happen is, TVMLKit is going
that contains the app.onlaunch call back
for your TVML application.
Startup has to wait until this application.js file is fetched
and evaluated before app.onlaunch can execute.
If you have a large application, it's a good idea to break
up the code into separate files to speed up startup time.
This is a common pattern and TVMLKit supports this
at any point in the application lifecycle.
and functions that get shared globally across your scripts.
Let's take a look at the evaluate scripts global function
that TVMLKit JS provides.
Generally you'd want to call this in your app.onlaunch
but you can actually use it anywhere.
The function takes an array of script URLs
and a completion call back as arguments.
When your completion call back is executed, you'll be able
to use the variables and functions
that were defined in your libraries.
But there are a few things to keep in mind.
When you call evaluate scripts, TVMLKit JS is going
to execute the code, including any side effects
So don't call evaluate scripts multiple times on the same file.
Also, be careful if you have scripts that depend
on other scripts, that you load them in the correct order.
Evaluate scripts fetches the array of script URLs
in parallel, and then executes them in sequence.
If any of the scripts are unavailable,
none of the scripts will execute,
so always check the success argument
to your completion call back to make sure
that your library functionality is available.
And finally, I'd just like to remind everyone
that even though TVMLKit offers many web like APIs,
your TVML application is not a web browser.
that will be helpful to you but some may not be compatible,
especially if they rely on browser functionality
like a global window object or a global document object.
Just keep that in mind.
in your TVML applications, you can actually call
From here you can do things like pipe UI application events
in a class called the TVApplicationController.
to schedule your interactions with it.
In the simplest form, all you have to do is call a method
on this TVApplicationController,
and pass in a block to be evaluated.
When your block executes, you'll get a reference back
to the JS context, from here, you can eval strings
and you can get and set properties
Just make sure that you don't retain this JSContext
or use it anywhere outside of the block.
you also want to be careful
that you don't perform any blocking operations while you're
evaluating this block,
as you may deadlock with the main thread.
Let's take a look at an example of how we would call
Here we're looking at the Swift code
for our TVML app's app delegate.
We've implemented a stub here
for the UIApplication delegate method
to handle custom URL schemes.
all we have to do is ask the appController
When this block executes, we'll have a reference
to the JSContext, from here we can access properties directly
We can take native values or objects and use them
as a function argument.
Here, we're invoking the on open URL global function
of the URL from the UIApplication delegate
Just like that we've exposed new functionality
into our TVMLKit application
Next, let's talk about bridging.
So we just saw how super easy it is to take native values
numbers, and arrays this is already handled
If you want to use your own classes, all you have
to do is follow a few simple class conventions
Let's take a look.
So there are three main steps here.
First, you have to declare a custom protocol
that extends JSExport, extends JSExport,
Second, we're going to define our classes using Swift
and extending this native, this protocol
to expose our native classes.
And third, we're going to take the instance of our classes
or the class itself that we want to expose and use a call back
on the TV application controller delegate
to prepare the JSContext before control gets handed
Let's take a look at an approach of how we would go
about creating a wrapper around store kit if we wanted
to expose something like in app purchase functionality
We start off by defining our protocol,
here's where we'd specify properties or methods
Here we'll just leave it as a stub but you can see
that we've extended JSExport
and defined a protocol called StoreKitWrapperProtocol.
Next, we will create a class for our store kit wrapper
that extends NSObject and implements this custom protocol.
Once again I've left the details stubbed out but this would be
where you'd define your native functionality
And finally, we implement the TVApplicationControllerDelegate
This gets called before app.onlaunch executes
and allows us to expose our custom functionality before
That's really all there is to it.
We've now defined a native class,
we've gone through the steps to make it accessible
So in this session we've seen how you can leverage native
functionality to enhance your TVML applications.
You can extend templates using custom mark-up
for your own views and collection view cells.
You can actually host TVMLKit inside of a native application
or use your own native view controllers inside a TVMLKit.
You can even extend the scripting environment in TVMLKit
to bridge native classes, type application events through,
and load additional libraries.
I hope we've shown you how easy it is
to build app specific functionality
in your TVMLKit apps that's custom to your brand.
TVMLKit is a really simple API for building complex apps
with high quality results and minimal overhead.
I encourage you to check out the TVML guide
and TVML catalog sample applications for more ideas
on how to extend and use TVMLKit.
Please also check out the Apple developer website
for programming guides, sample code, and documentation.
Also, check out these other sessions that happen this year
at WWDC 2016, especially Developing Apps
for TVMLKit Part 1, which has a great demo
of building an app from start to finish.
Thank you, and enjoy the rest of WWDC 2016.
Looking for something specific? Enter a topic above and jump straight to the good stuff.
An error occurred when submitting your query. Please check your Internet connection and try again.