Learn about the new features in Xcode playgrounds such as inline results, auxiliary sources and resources, multiple pages, and markup for formatted text. Find out how to explore programming problems in a playground, and create engaging experiences for teaching and learning.
SAM: Good morning.
So thank you all for coming to today's session
on authoring rich Playground.
My name is Sam, and I'm an engineer on the Xcode team.
So Playgrounds have been out for about a year now,
and we've been absolutely blown away
by what you guys have done with them.
We've seen everything from people writing their first
"Hello, world" all the way
up to people writing entire books in Playgrounds.
The response has just been amazing.
So today we're going to be covering a couple of things.
We're going to be talking about some of the new features
that were added to Playground since last year,
and we're also going to cover some of the existing features
that have been updated.
And we'll also cover some tips and tricks
that can help you author really, really rich Playgrounds,
Playgrounds that you want to share
with the rest of the world.
And as a bit of a bonus, we're also going
to be solving a problem that's common among WWDC attendees,
and that is how to explore San Francisco.
So what is the problem?
Well, San Francisco is a big place.
There's a whole lot to see, but really you're not going
to find a lot of time to do it between the sessions
and the labs and writing your next great apps.
And you probably have a flight to catch at the very end
of the week, so there's an endpoint here.
And as engineers, we want to be as efficient
as we can possibly be when we solve problems,
which in the context of this problem means we just don't want
to walk any further than we have to.
So how are we going to solve this problem?
Well, once we know the places that we want to visit,
we're going to start out at Moscone Center,
traverse all the places that we're going to see
in the quickest way possible before we finally have to jet
out for San Francisco International Airport.
Now to do this we're going to be building a Playground.
So without further ado, let's get into that.
Okay, so I've got a Playground already kind of set
up for us here, and we'll just take a quick moment to go
through what we've got.
So first up we've got a struct here for place.
So places are going to be what we want to see when we're
in San Francisco, and they're going to have a name as a string
and a location as a CLLocationCoordinate2D.
Next up we've got a struct for city.
So in the context of our problem this is going
to represent San Francisco.
And we can think of this as a collection of places.
It's our own type to hold these things.
So internally we've got an array of places,
and then we've got a function here
that we can add places to our city.
So let's go ahead and just create our city.
We're going to call it San Francisco.
And like I said, we need to start our journey somewhere.
So we're going to go ahead and create a place
for Moscone Center, which is where we're going to start.
So let's create Moscone there.
And then finally we're just going
to add the place to our city.
So those of you who are familiar with Playgrounds are going
to remember that for each line of code that executes,
we get a result in the results sidebar over here.
So we can see that our add place function is called, and it looks
like we are passing in Moscone Center to that.
But if you look at it further
down where we've created our city and our place,
all we're getting is the type.
So this is handy, but we kind of want
to be a bit more descriptive, especially if we're going
to be creating a few more places.
If we see place after place after place, we're not going
to be able to differentiate these things.
So for our places, the most descriptive thing is the name.
So how do we get the name to be returned in our results sidebar?
Well for that we've got a new protocol,
and that is called Custom String Convertible.
So what I can do is I'll extend my struct here for place to say
that I'm going
to be implementing Custom String Convertible.
And you can see now I've got an area here
because they're not actually conforming to the protocol yet.
So to actually conform to the protocol we just need
to implement a re [unintelligible] property
And that's going to return a string.
And for us, we want to return the name of our place
because that's the most descriptive thing.
So you can see now, if we look back down to
where we created our place,
we've got Moscone Center here instead of just the type name.
So what does this mean for our city?
Well probably the most descriptive thing there is
to return the list of places that are currently in the city
so we can see how our journey is progressing.
So we're going to go ahead and do the exact same thing
for city, just implement Custom String Convertible there.
And go ahead and return the description.
And for that we're going to return to places.description,
so the description of our array of places.
So now you can see when we first created San Francisco,
we don't actually have anything in it
yet so we get an empty array here.
But then when we add our place to it, we get Moscone Center.
So when we create more and more places we're going to see more
and more in our results sidebar.
So one of the cool things
about Playgrounds is you're always able to kind
of get a deeper look and get more information about a result
by clicking this Quick Look here right next to the result.
So I click that for Moscone Center.
We see a bit more information about our place.
So we've got the name and we've got the latitude and longitude.
This is superhandy to debug but, I don't know, latitude
and longitude doesn't really help me.
I'm not that great at cartography.
I don't know how to position these things in the world.
So I kind of want to see something a bit more visual,
something that just kind
of screams out, yeah, that's a place.
And to me nothing screams "place" more
than just a big blue dot with a name underneath,
something I would put on a map.
So how are we going to do that?
Well normally when we kind of want
to do something a bit custom and visual, we create a view.
So we're going to go ahead
and just create a UI View subclass here.
And we've got some of that already set up.
And let's just take a quick moment to look
through what we've got there.
So we've got a class here called View.
It's going to be a UI View subclass.
And just internally we've got another view that's going
to be our big blue dot view.
And then we've got a name label that's going
to show the name of our place.
And then when we create this thing, we're just going
to let it decide how big it wants to be.
And finally in layout subviews we're just going
to position these things so that blue dot's on top
and the text is below.
So we'll create one of these just to see how it looks first,
and we're going to pop open the Quick Look.
Cool, that's starting to be a bit more like a place,
like I can see that appearing on a map.
But how do we actually join these things up so
when we Quick Look our place, we actually see our view returned?
Well for that we've got another new protocol,
and that protocol is called Custom Playground
So what Custom Playground Quick Lookable does is
if you implement the required method there, it will allow you
to return another type to appear as the Quick Look
for your type or any other type.
So that could be something like a Bezier path or a color.
But for our case we want to return our view.
So what I'm going to go ahead
and do is just create an extension for our place and say
that that's going
to be implementing Custom Playground Quick Lookable.
And so again, we've got an error here
because we're not actually conforming to that yet.
So we'll just add the conformance there
by implementing the Custom Playground Quick Look method.
And so inside that method we're just going
to return a Playground Quick Look that's reflecting the view.
Now because we're an extension on place, we have access
to the name of our place, so we can just go ahead and throw
that into the initializer there.
So now, when we Quick Look our place again, we should see,
cool, we've got Moscone Center there and everything is starting
to look a bit more like a place.
But we've kind of ended up in a bit
of code here that's just hanging
around in the rest of our Playground.
And we kind of want to move this just out of the way
because no one else really cares about this.
It's not really helping us to show what we're trying to do.
So for this we're just going to go ahead and,
well first we're going to delete this place view here
because we don't need that.
And we're going to grab the view here that we declared
and we're going to just go ahead and put that directly
in our extension on place.
Clean up some white space here.
And so when the Playground reexecutes you should just see,
cool, exactly what we saw before but now
that view code is all just embedded within our extension
so it's nice and clean.
What does this mean for our city?
So if we're following the kind of pattern that we want
to see what's in our city at the moment, then we kind of want
to see what places are in our city.
And so this is going to happen by default.
So if we click on the Quick Look for Moscone Center,
we can see we've got a place in there.
And we can see the Moscone Center, little blue dot
in there, but as we add more places, it's not going
to help us all that much.
It's just going to be listed up.
We kind of want to visualize how these things are positioned
to each other based on their location
so we can start working out, well if we're at Moscone Center,
you know, we're probably not going to go directly
to Golden Gate Bridge, we'll probably go to something
like Coit Tower first.
So for that we're going to create another extension.
This time on City.
It's going to be again, Custom Playground Quick Lookable,
and we'll do that here.
I've got a bit of code ready for that.
And we'll just walk through this real quickly.
So it's an extension on City,
same way I implemented Custom Playground Quick Lookable.
We have conformed to that
by implementing the Custom Playground Quick Look
And then inside we're just going to create a view,
work out where these things would be positioned
within that view based on their latitude and longitude pair.
So now when we Quick Look our city we should see, cool,
Moscone Center on the eastern side there
by a little blank map, but we're starting to build up a picture
about what we're actually going to be seeing while we're here.
So now that we've got this kind of in place,
we're going to add a few more places.
But before we do that, I kind of want
to keep this map view here just open all the time,
or at least visual.
I'm opening and closing it a lot when I want to check my code.
Well for that we've got this cool little thing called an
So right next to this Quick Look button if I click Show Result,
that's just going to go ahead and throw
that Quick Look directly under the line of code
that generated it so I can keep working on my Playground
and see it constantly running
and see what's actually happening.
And the cool thing is it's kind of small right now
so we can actually just grab it and drag it
out like we would any other window and make it as big
or as small as we want.
So cool, we can start working on the rest of our Playground,
adding our places to that,
and we should see them pop up in our map.
So what do we want to see?
I've heard Golden Gate Bridge is pretty cool and famous,
so I'm going to go ahead and check that out.
We'll add that to the places that we want to see.
And when the Playground reexecutes we'll see that based
on the location of our Golden Gate Bridge,
we're going to be putting that in the northwest,
which if my knowledge
of San Francisco geography is correct, I think that's true.
What else do we want to see?
Sutro Tower, how about that?
That's kind of like something out of War of the Worlds,
going to chuck that in and put that in the places as well,
going to chuck in Sutro Tower.
And the Playground reexecute
and then we'll see Sutro Tower down south.
So we're starting to get a really good picture
of how our places are built up, and as we add more and more
of these things we can see,
based on where their location is, how we're going
to be getting between them.
I'm just going to go ahead and switch back to slides now.
So you may have noticed that our Playground got a little bit long
towards the end of that.
We had some view code and some extensions, and there's a lot
of stuff that wasn't really helping us to kind
of describe the problem.
It was not that great.
So what we kind of want to do is pull a lot of that code directly
out of the main body of the Playground but still keep it
around so we can use it.
So to show you how we're going to do that,
I'd like to invite my colleague Connor up to the stage.
CONNOR: Thank you, Sam.
My name is Connor and I'm an engineer on the Xcode team.
Today I'll be talking to you
about how you can make your Playgrounds more powerful
and making them even more focused on the problem at hand.
In order to do this, let's dive straight into a demo
where I'll take a look at the Playground that Sam just started
and add support for finding the best path
through San Francisco while making it more focused.
Let's head over to the demo machine now.
Okay, so here we are in Xcode.
And if you noticed, we've got basically the same Playground
that Sam was just showing you.
We start off by creating a city for San Francisco.
We create a few places, and then we add those places to the city,
ending up with this great inline result showing you what we've
built up so far.
If you notice though, there is one major difference,
and that's that the entire Playground now fits
on one screen.
I'm still using my custom city in place structs, though.
And even though Swift compiler's pretty great, it isn't able
to actually create structs out of thin air yet.
So what we're using instead is a feature which we added
in Xcode 6.3 called Auxiliary Sources.
The auxiliary sources are additional Swift source files,
which are embedded inside of your Playground,
and they're precompiled into a separate swift module.
Because they don't need to be interactive,
they can perform better than the Playground itself.
Additionally, since they're in a separate module,
you can use access control to ensure that only the bits
of your Auxiliary Sources which you want to be made visible
to the Playground are exposed, so you can hide a bunch
of internal implementation details
in the auxiliary sources.
To find them, we'll go ahead and open up the navigator.
In your PC, we've got the Playground at the top.
And then inside
of the Playground we've got thr sources folder.
In the sources folder we've just got a collection
of Swift source files.
I can open one up, and here we've got city.swift,
and it's basically the same struct that Sam was just working
on with a few minor modifications.
First, I'd mark it as public because we want the city
to be able to be used by the main Playground itself.
I've also added support for travel times to the city
so that we can actually keep track of the time needed to get
between each place in the city.
If we look at place.swift, we see the same basic stuff here.
So same struct that we had before, just modified
to become public and with a few modifications to work
with the updated city struct.
I have a couple of other auxiliary source files,
which I'm not going to dive into.
One has to do with property list serialization,
and the other one is kind of a grab bag of utilities
that I've just pulled together from other projects
that I've worked on, and it will help me
out when I'm implementing our algorithm.
Let's switch back to the main Playground now.
And so here we see that we have, you know, the start of a city.
We're starting to build something up,
but I want to visit more than just these two places,
and we also want to have all the travel times between places.
I could add all of that in code, but that wouldn't be great
because we'd have a bunch of code at the top
of the Playground, which isn't really instructive
to what we're trying to show.
So instead I'm going to take advantage of another feature
that we have in Playgrounds called Embedded Resources.
The embedded resources are files which are copied
into the Playground itself and are made available
to the Playground when it runs
as the resources of the main bundle.
And they live in the navigator as well,
in this little Resources folder.
What I'm going to do is I'm going to drag in a plist
from the Finder that defines the city of San Francisco.
So I'll go ahead and do that.
I've got the SanFrancisco.plist.
I can drag it in here,
and it will get copied inside the Playground file.
This means that we don't have to worry
about any external file references breaking
when you decide that you want
to share your Playground with someone else.
It's all just in there so you can send it as a discreet unit.
Let's take a look at what this plist looks like.
And so first we've got an array of places.
Each place is just mapping a latitude
and a longitude to a name.
And then let's scroll down a bit in this file.
We'll see here that we've got an array of travel times.
And a travel time is just mapping two places to the time
and minutes needed to get between those places,
these times gathered using the trans directions in iOS 9.
Now even though I'm calling these destination and origin,
I am making this a little bit simpler and assuming
that the time it takes to get from point A
to point B is the same as the time to get from point B
to point A, so these are actually bidirectional
Switch back to the main Playground now.
And instead of having all this code here, I'm just going
to select a bunch of it and delete it and replace it
with a call to load my city of San Francisco.
So start out by calling this initializer on city,
call contents of property list at URL.
And what it will do is that it will just simply look
at the main bundle to get the URL for a particular resource,
this San Francisco plist.
We know that we've just added this into the Playground,
so I'll force unwrap that optional
so I can pass it to my initializer.
Additionally, this initializer has been updated
to take advantage of Swift 2's error handling feature.
So I'll indicate to the compiler
that I know it can throw an error with the Try keyword
and add an exclamation point at the end because I don't want
to add a bunch of error handling code that's not instructive
for what I'm trying to show in this Playground.
Additionally, I know that this plist is correct, so it's okay
for me to load it this way.
We can show this inline now.
And let's make it a little bit bigger.
So here we've got our city now.
We've got the Moscone Center, Coit Tower, Fisherman's Warf,
the Painted Ladies, Sutro Tower, Golden Gate Park,
Golden Gate Bridge, and not pictured in our map
but still there is the San Francisco International Airport.
And you can see all the connections leading
to the airport.
So great, we've got a city that we can work with now.
But now that I look at it,
I think I'd like to make this Quick Look a little bit nicer
by adding in some icons for all the places that I'll visit.
And it just so happens that on my desktop I've got this
And if I open that up you can see, here we've got a bunch
of icons for each of these places.
So I'll just go ahead and take those and drag them
into the Resources folder as well.
Just like the plist, they'll be copied in there
and be made available to my Playground.
I do need to update my Quick Look to take advantage
of these images, though.
So I'm going to go ahead and open up the place.swift file
in the Assistant editor by option clicking on it.
I will then find this location view,
and instead of initializing it to just the blue circle,
we're going to update this to take advantage of the images.
So I can take all that code and we will update our place view.
We'll start off by getting the image associated with that,
create an image view, and then set a couple
of properties before returning it.
Now when I save this file, Xcode will notice
that the auxiliary sources have changed
and will automatically recompile their Swift module.
Once the compile finishes, we'll rerun the Playground itself
and so the Quick Look will update automatically.
I didn't have to do anything more
than just make an edit and save to disc.
So great. That Quick Look looks a lot better.
Let's switch back to the standard editor
and start working on our algorithm.
I'm also going to hide the navigator
because I don't need it and I'd like the extra space.
So we're implementing a brute force algorithm to find our way
through San Francisco.
And in order to get that started,
we need to just get all the paths through San Francisco.
So we'll start with this
and what we do is we just call this all paths
through city method on our city struct, telling it that we want
to start at the Moscone Center and that we want
to end at the airport.
And if you look in the sidebar at the right,
we see that we have 720 paths.
I'll then implement the algorithm itself,
and here we're just starting with a couple of variables
which will hold our results, one being for the best travel time
and one for the best path.
We'll then iterate over all the paths through the city,
getting the travel time for each path.
We'll then compare that to our best travel time,
updating our result variables if necessary.
Finally, at the end we can see here the best travel time
through the city so we'll show that inline and we'll see
that it will take 235 minutes to get between all these places
if we never stopped and somehow managed to make all
of our transit connections.
We can also add the path itself inline, and so we can see
that we'll start off at the Moscone Center,
which is what we expected.
We'll then head over to Painted Ladies and Sutro Tower.
Then up to Golden Gate Park and Golden Gate Bridge.
Then we'll head ove to Fisherman's Warf
and Coit Tower before heading
down to the San Francisco International Airport
to catch our flight.
So great, I've got all the information that I need
to go see the sights so let's switch back
to slides now to take care of that.
So I just showed you how you can use the auxiliary sources
and the embedded resources features in Playgrounds
to make your Playgrounds more powerful while keeping them
incredibly focused on the task
that you're trying to actually achieve.
I think I have something pretty interesting here,
and I'd like to share it with people
when I get back home from the conference.
But it's not quite polished enough that I'd be ready
to show it to other people.
We've added a bunch of great features in Xcode 7, though,
which makes sharing your Playground
with the world even better than before.
So now I'd like to invite my colleague Matt up on stage
to show you about that.
MATT: Thank you so much, Connor.
My name is Matt and I'm also an engineer on the Xcode team.
And I think Connor and Sam have done a wonderful job
of putting together a really awesome Playground
that shows people how to get around San Francisco
in the best way possible.
But it really isn't ready to be shared with the world,
so I'm going to show you a few tips and tricks you can do
to make your Playground richer and more engaging
so you can put it out there on the Internet
and people will love it.
So you can see here we have the Playground
as Connor just finished working with it.
And we have a very simple algorithm that Connor wrote,
which walks through all the possible paths in the city
of San Francisco and compares them to one another.
And it was great for you guys
because we had Connor here explaining every step of the way
as he was implementing it.
However, when we share this with the world,
unfortunately not everyone was here at WWDC.
So we'd like to add a little bit of information, a little bit
of context, so that people
who view this Playground later will understand exactly how we
So we introduced a new feature
in Xcode 6.3 called Playground Markup Comments.
And that allows you to annotate your Playground
with rich prose formatted in beautiful displays
so that people can better understand exactly how you got
to the Playground that you arrived at.
So just to give us a little bit more space I'm going to start
by putting away our Quick Look here, and I'm going
to replace the comment at the top of the Playground
with a little bit of information about exploring San Francisco.
Now you can see this looks a lot like a comment
that you would put anywhere else in your source file,
but the biggest difference
that differentiates a rich markup comment
from another comment is the colon.
We've got a colon after the first asterisk in the comment,
and we can actually do that as well with single-line comments.
So add a colon over here as well.
And when I go up to the Editor menu
and choose Show Rendered Markup, you'll see that this rerenders
and now we have these beautiful rich blocks of text
that we can use when we want
to explain what's happening in our Playground.
We can actually format them a little bit more as well.
So if I switch back to the raw markup, I can use a number sign
to indicate that we'd like a heading to indicate
"Exploring San Francisco."
And I could use, for example, asterisks around
"most efficient," to indicate
that we want this to be in italics.
So if I render this again,
you'll see that now we've got a nice, big, bold heading
that explains exactly what we're going to be talking about.
So that's a great start.
I'd also like to annotate a little bit more
about the other things that are happening in this Playground.
For instance, all paths.
All paths through the city is a little bit vague
and it's a little bit mysterious,
so I'd like to add a little bit of information
about how those paths were computed.
And the algorithm itself could probably use a little bit
of explanation as well.
So we'll document the algorithm.
And if I switch back once more to the rendered markup,
you'll see now we're starting to get something
that looks much more like almost a book,
something that a user could sit down with,
walk through, and understand.
We've even got a nice bolded list, which we use
by inserting an asterisk at the start of each line.
So that's pretty awesome.
But it isn't quite rich enough.
We want to take it just a little bit further.
So to do that, we're going to do a feature
that we introduced a long time ago on Playgrounds
that is now even better on Xcode 7, and that's Live Views.
So I've taking the liberty of writing a live view.
I've put it into the auxiliary sources already, and we're going
to start by showing it alongside this Playground
to visualize exactly how this algorithm works.
So the first step to using Live Views is that you need
to import XCPlayground, which is a module that has a bunch
of really awesome functions that allow you
to do some pretty cool stuff with Playgrounds.
Now you're also welcome to do this in your auxiliary sources
and create, for instance, a helper method
that shows your live view.
You don't need to do that in the main Playground.
But I'm going to do it right here just
so it's must clearer how it all works.
Once we've got our city of San Francisco we're ready
to show it, so I'm going to instantiate a view controller
with our new city view controller, and I'm going
to pass in the city of San Francisco.
I'm then going to use the XCPShowView function,
give it the name of a city,
and pass in our view controller's view.
So if now I switch over and show our Assistant editor
after the Playground reexecutes, we'll see a live view
that looks just like the city of San Francisco.
And you can see that we've taken the idea of the rich Quick Looks
that we've already added and we've laid them
out onto something that looks a little bit more realistic
so people won't be quite so disoriented.
So that's the first step.
But we also want to show how the algorithm itself works,
and to do that we're going to add a little bit of code
that updates the live view as we're walking
through our algorithm.
So we have a loop here that iterates through all the paths
and all paths, and I'm going to replace that with the method
on my view controller called Visualize Path Iteration.
And I've written that to use a trailing closure
so I can actually update it so that it looks almost exactly
like the loop code that we originally had.
And I'm also going to add a line in here
so we can tell the view code controller once we've found a
better path, we want to show that better path,
especially on our map.
So it will execute through once more,
and when it does you can see now we're visualizing all the paths
as we traverse them through the city of San Francisco.
And this is great because now people
who are reading this program can really see exactly how we got
to our answer of how to find the best route through the city.
You might notice something, though,
and that's that it's checking a lot of paths.
It's actually checking 720 paths, as Connor pointed
out earlier, and that's quite a few.
In fact by default, live views run for 30 seconds,
which you can change with this control
down in the bottom right of the Playground.
And that isn't even enough time to make it through all
of the paths through the city of San Francisco.
Now we've artificially slowed it down a little bit
so you can see the paths as we iterate
through them on the live view.
But I think when people see that, they're going to say,
well there must be a better way.
And in fact there is.
And we'd like to start out by showing that to our users
from the very beginning.
So we're going to use another algorithm.
It's a nearest neighbor approximation algorithm,
and what that's going to do is it's going to be
as though we were starting at Moscone.
We looked at all the places that we wanted to visit
and then we just picked the closest one and we went to that.
And then from that place we'll pick the next closest
and we'll go on from there.
And if I wanted, I could implement that right
at the bottom of this Playground document.
But that would start to get a little bit confusing,
and it's not as focused.
One of the wonderful things about Playgrounds is
that they're very, very focused pieces of content,
so we want to be able to preserve that.
And to do that we have a brand new feature
in Xcode 7 called Pages, which allows you
to have multiple pages of content
in a single Playground document.
So to do that we're going to open the navigator.
And in the bottom-left corner we'll choose the Plus button
and click New Page.
And that's going to create a brand-new page
in the same Playground.
I'm going to call this one Nearest Neighbor, after the name
of the algorithm that we're going to be using.
And then we're going to rename our initial Playground
to Getting Around.
Now Pages are also pretty cool because,
like the auxiliary sources and resources that you can include
in a Playground at the top level,
you can do that on a per page basis.
You can see I can twist open any one of these Playground pages
and we can embed their own sources.
Any resources of the same name, for instance,
will also override those in the larger Playground.
So if you want to have some different branding on each page
or a particular image that is specific to the concept
that you're teaching in each different page,
you can do that pretty easily.
So right now I'm going to switch the nearest neighbor page,
switch back to the raw markup.
And I've already written up this algorithm, so I'm just going
to go ahead and paste that in.
So what we have here is a Playground
with nearest neighbor approximation, and you can see
when this one runs it examines way fewer paths
through the city.
Now this is not an optimal algorithm
in that it won't necessarily find our best path
through the city.
But you can see it's already done, which is pretty cool.
So this is a great way of showing, alright,
there might be more than one answer to this problem.
And if we render this, we can also show
where we got this path from.
We actually edited this on, we found the information
for this algorithm on Wikipedia.
Unfortunately, I invented a little too far.
And we can embed a link right into the Playground,
which would take us to the page explaining exactly how this
We could also link between pages in a single Playground
and bring it back to our optimal path that we discovered earlier.
And in fact, when we look at the number of paths
and the different paths that we took through the city
and how long this algorithm takes to execute,
we examined 720 paths on this one and find a path
that is only 21 minutes faster than the other page.
So that gives people a frame of reference for saying,
maybe there are other ways to do it.
And they can use a Playground to experiment with that all
by themselves, which is pretty awesome.
So that's adding sections of markup, Pages,
and Live Views in Playgrounds.
So we have a lot of really awesome new features
in Playgrounds in Xcode 7.
We showed you Custom Quick Looks, which allow you
to take your custom data types and make them come alive
in the same way that a lot of the built-in types do.
We've also got inline results, which stay with the Playground,
so you can show results right next to the line of codes
that produced them, and then those go with the Playground
when you share it with other people.
We also have Auxiliary Sources so you can take the code
that goes with your Playground that isn't as instructive
as the code in the main Playground and put those aside
so that your users see only the API and the functionality
that you want them to see.
We also have Embedded Resources so you can bring in images
and make things feel even more alive and more engaging.
We've got brand-new markup comments
that are a really great way to guide your user
through your Playground when you can't be there with them,
enhanced Live Views which are better than ever,
and Pages which allow you to cover multiple topics
in a single Playground without distracting from the focus
of each of them, which is really, really cool.
So that is what we have in Playgrounds in Xcode 7.
For more information, you can visit the website.
We've got documentation up there and the developer forums.
You can also talk to Stefan Lesser,
our Developer Tools Evangelist.
We have a number of related sessions that are going on.
We've got Swift in Practice,
which is happening tomorrow afternoon,
and Building Better Apps with Value Types in Swift.
Also the What's New in Xcode and What's New
in Swift sessions will be great all week.
Thanks so much everybody and enjoy the rest of the WWDC.
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.