Video hosted by Apple at devstreaming-cdn.apple.com

Configure player

Close

WWDC Index does not host video files

If you have access to video files, you can configure a URL pattern to be used in a video player.

URL pattern

preview

Use any of these variables in your URL pattern, the pattern is stored in your browsers' local storage.

$id
ID of session: wwdc2014-408
$eventId
ID of event: wwdc2014
$eventContentId
ID of session without event part: 408
$eventShortId
Shortened ID of event: wwdc14
$year
Year of session: 2014
$extension
Extension of original filename: mov
$filenameAlmostEvery
Filename from "(Almost) Every..." gist: [2014] [Session 408] Swift Playg...

WWDC14 • Session 408

Swift Playgrounds

Tools • iOS, OS X • 55:39

Playgrounds are a new and innovative way to explore the Swift programming language. Explore how Playgrounds provide new workflows, enable rapid development, help you conveniently step through your code to diagnose bugs, and make it easier than ever to learn new concepts.

Speakers: Rick Ballard, Connor Wakamo

Unlisted on Apple Developer site

Transcript

This transcript has potential transcription errors. We are working on an improved version.

Hi. Welcome to Swift Playgrounds. I'm Rick Ballard and with me today is my colleague Connor Wakamo. We're both Engineers in the Xcode Team and we've been working hard to bring Playgrounds to life. We introduced Playgrounds to the world Monday morning and you saw a little bit more about them Monday afternoon and yesterday. Well, today we're going to go into a lot more depth.

We're going to start out today with some conceptual background, what Playgrounds actually are and what you can use them for. And then we'll show you examples of how to use Playgrounds for learning, exploration, and visualization of the results of your code. We'll show you how you can use your own custom resources with your Playgrounds, and how to use Playgrounds for algorithm development and development of other separable pieces of code.

We'll introduce the XCPlayground framework which includes some really powerful utilities that you can use to enhance your Playgrounds. And we'll show you how you can develop your own Custom Quick Looks, so that you can visualize your own classes the same way you visualize the classes that come with the frameworks.

Next, we'll show you a great demo of how awesome Playgrounds are for developing custom views and in any other kind of custom drawing and we'll show you how you can use your own asynchronous code with Playgrounds. Finally, we'll finish up today with a little bit about the limitations that Playgrounds have today.

So what exactly are Playgrounds? Playgrounds are a new type of document introduced in Xcode 6 and they're actually a file wrapper containing a few useful things. First of all is your Swift code. The code that would be run and the result are, and generate results to display automatically every time you edit your Playground file.

Swift Playgrounds also can contain a folder of embedded resources which are made available to your code or your Playground can reference resources elsewhere on your system you want to make available. Finally, your Playground can contain a timeline full of timeline items that provide useful visualization of your results beyond what you see in the sidebar.

When you first open a Playground, we show the Playground Editor with your Swift code on the left and the results sidebar on the right showing the result of every expression in your code. Every time you edit your source, we rerun your Playground source from the top to the bottom and present the new results from that run in the sidebar.

This is the basic editor mode. But if you go into the assistant editor mode we'll show the Timeline Assistant by default which allows you to visualize your results in more detail. For example, you can display the value history from a line in your code. In this case, since it's a numeric value, we'll draw a graph of that value over time since it was iterated multiple times in a loop. If you're looking for console output like that from Print Man, you'll also find that in the Timeline Assistant.

There are a couple other useful things you, I want to call out here. In the lower right hand corner, there's a time-stepper. And this controls how long your Playground will continue to run after the top of a source is finished if you're using live views or indefinite execution. And I'll explain what both of those are a little later on.

There's also a slider which allows you to go back in time and view results in the timeline from a specific point in your Playground execution. So here, you can see we're viewing a numeric result from partway through the Playground execution. But you'll find this is very useful with live views as it allows you to scrub back through the recording of that view and see exactly what your animation was doing at a specific point in time.

So that's what Playgrounds are. Let's talk a little bit about what you can use them for. We think your first great use of Playgrounds is going to be learning. We've introduced a brand new language for you to learn and we think the best way to get started is just to open up a Playground and dive in and play around. Our documentation also includes a special interactive Playground called the Swift Tour. This allows you to see documentation and Playground Editor side by side in the same editor. So you can read about how to do something and try it out right there without leaving the editor.

Finally, we think Playgrounds are a fantastic way for people to learn how to program in the first place. Beginners don't have to learn how to configure a project and target and build and run and debug. They can just type code into a Playground Editor and immediately see the results. So if you know anyone who wants to learn how to program, we encourage you to suggest trying it in a Playground.

We think Playgrounds are also going to be in indispensable tool in your toolbox for everyday code development. If you're developing an algorithm or any other separable chunk of code, you should consider starting it on a Playground, working on it there until you have it how you want it, and then dragging that code into your project for use in your application.

Any sort of drawing code you want to do is also great in a Playground because you can immediately see the visual result of what your code is doing. And every time you change your code, you can immediately see how that affects the visual result. Finally, processing code like value transformers or a sequence of image filters are great in Playgrounds because you can visualize the result at every step of the transformation process. And when you change something, you can see how that change ripples through all your results.

We think you'll find that Playgrounds are fertile ground for experimentation. And in particular, any time you're trying to learn some new API, you should try it out on a Playground because you can immediately see how it works and what results it gives you. You don't need a project, you don't need to build and run. You just open up even a standalone Playground document, type in your code, and see what happens.

I'm sure all of you have many a time gone to create a new project from the application template, and gone to find applicationDidFinishLaunching, just to put a line of code and to try some API. Oh, and then you probably have to NSLog it too so you can see what happened. You don't have to do that anymore. Now you can just open up a Playground and try out the API you want to try.

In fact, we'd recommend you consider keeping a Playground in your doc at all times for quick access. So anytime you want to try something it's right there at your fingertips. So with all that said, let's dive in and take a look in an actual Playground. To do that, I'm going to invite my colleague Connor up on stage.

Thank you, Rick. Hello everyone. My name is Connor. I'm an Engineer on the Xcode Team. And today I'll be talking to you about how you can work with Playgrounds as well as some of the things which we think Playgrounds will be really great for. Now, Rick has already covered many of the basic concepts behind Playgrounds.

And so I think really the best way to show you how to work with Playgrounds is actually just by jumping straight into a demo. So, let's go ahead and do that. So here I am at the demo machine and I'm just going to go ahead and launch Xcode.

Now you'll notice here that on the Welcome window for Xcode we've added this brand new "Get started with a Playground" button. It's that way we want to make it really easy for you to just get started with one. So I'll just click on that. We'll create a Playground and I'll just give it a name and a place to save it.

So "MyPlayground" is fine and putting on the desktop is fine as well. So let's say create, and then we have here our Playground itself. So, you notice that we're importing Cocoa, so we have full access to the Cocoa APIs. And then we are also creating a string and we're assigning the value, "Hello, Playground" to that string.

You'll notice that in the result sidebar we're seeing the result of that. So in this case we're seeing the string, "Hello, Playground". So OK. So that's kind of the basic idea. Let's try something with numbers. So let's say, for i in 0 to 10, let's just say, i times i.

You see there that we execute the code and we're getting an indicator in the result sidebar that we've executed that code 10 times. So, OK, let's try bumping that up to 100. We'll let it run and we'll see there that we immediately get an indication that this code has executed 100 times. Now, knowing that is very useful information but sometimes you actually want to see the value there. And we have support for that as well.

So OK, I'll just hover over this result, and you'll see that we're highlighting the line of code with which it is associated. And we're also showing this button here. That's called the Value History button. And if I go ahead and click on it, we'll open up the assistant editor into the timeline mode. This is the place where you can see results over time as well as a place for you to store results which you like to see persistently.

So in this case, we're showing the graph for i times i. And we've seen this, you know, this nice little curve here. So OK, so that's kind of the basics of using the timeline and calculating numbers. Let's try something a little bit more interesting. Let's go ahead and do something with AppKit. So let's first start up by creating a color. So you let color equals NSColor.blueColor.

You'll see there that we're now showing in the result sidebar a color swatch indicating what the color is as well as indicators of all of the components which make up that color. So I can, you know, take this color and let's create another attributed string using it. So let's say, let attrStr equals NSAttributedString.

And we'll pass it in the string in an attributes dictionary. So we'll use the string we already have and we'll create a dictionary. So we'll say NSForegroundColorAttributeName and we'll pass it the color we have. And then I'll say, NSFontAttributeName, I'll just pass it a font. So I'll say, NSFont, systemFontOfSize and then let's go to something fairly big, so I'll just put in 42, see what that looks like.

So, OK. So here, you notice that we're getting a result for this as well. You're seeing that we're showing the plain text representation of this, as well as an icon indicating that it is an attributed string. Now, that's great. You know, we know that this code is executed.

But I really want to see what the actual value is there. See how the attributed string looks itself and we support that as well. So I can just hover over the result and in addition to the Value History button, you'll see that we have a Quick Look button. And so if I go ahead and click on that we'll show a Quick Look of that value to show you the full representation of it as it was created in the Playground source.

So, OK, that's colors and strings. Let's try something with images. Let's actually start up by creating an array of image names. So I'll say, let imageNames equals, we'll put in an array there and, I know it's something to do with like NSImageNameUser or accounts or something in that line. So I'm just going to create an array with imageNames that I think it could be, the ImageNameUser, NameUserAccounts, NSImageNameUserGroup.

It's OK. We run the code and you notice that we now have an array of strings. We actually want to see an array of images and that's very easy to do. I can just say something like, let images equals imageNames.map. I'll pass it a trailing closure to just say, NSImage named, pass it the positional argument $0. And you'll notice there that we're now seeing that this line of code executed 4 times. And so, basically we can see that, you know, OK, that makes sense. We're executing this line of code 3 times for the trailing closure itself.

Then we're executing it once for the assignment to images. Actually, I only want to see the images array itself and we have a nice little trick for doing that in a Playground. You just go ahead and put the thing that you want to see on a line by itself.

So there you see, you know, we've put images there, we rerun the code, and we're seeing the images array. I can Quick Look that and I can see, "Oh, you know, here's the image that I'm looking for." And so, I'll just get that image and say, let image equals images at 0.

We'll rerun it. I'll Quick Look to make sure it's OK and in fact, yeah, that's the one that I'm looking for. Let's go ahead and put this into an image view. So I'll say, let imageView equal NSImageView. We'll pass our self a frame, so let's say NSRect. We'll say 0 for the origin because we don't really care about that. Then we'll also say 512 by 512 for the size.

Now I'm going to go ahead and put this ImageView on its own line as well. So I can show this result in the timeline. And this is a neat little way of building something up. You take the, you start creating the object and then you put another line where we show it as a result. Anyway, I can add some code in between there to see how it builds up over time. So you see here that we're starting out with just this empty imageView, you know, we're not seeing any interesting there. So let's go ahead add our image to the imageView.

So let's say, imageView.image equals image. And we'll re-execute and we'll see here now that we're in fact showing the image there but it's not filling the full imageView. It's not doing what we expect. That's because we haven't set up the image scaling appropriately. So we'll set that as well.

Say imageScaling equals ImageScaleProportionally UpOrDown. And we'll re-execute and now you'll see that we're seeing the image at full size in the imageView. We're seeing what we expect. And it's OK. That's how you can work with system resources. But I'm sure you have many resources of your own that you'd like to use in Playgrounds as well. And we support that too. So I'm just going to go ahead and I'm going to show the final inspector.

It will slide in on the right hand of my Playground. And you'll notice here that we're, we have this new section called Playground Settings which is shown whenever you're viewing a Playground document. You can select the platform against which the Playground should execute. And, you know, OS X is what we're doing right now. But we also support iOS.

And you can select a path for resources. This defaults to none but you can select one if you have resources that you're interested in. In this case, I'm just going to say I have a folder of resources on my desktop so I'm just going to say, let's use the Absolute Path option. I can then go ahead and choose that. So let's say here's my resources folder, I'll choose that. And then once I made that choice I'm actually going to go ahead and hide the Utilities area.

And to access the images themselves, I just use, you know, NSBundle API, you know, the resources show up as resources for the main bundle. So I can say something like "let myImage equals NSImage, named". I have an image in here that's just called "Xcode" so let's grab that.

We'll re-execute and you'll notice that now we're getting the image result here. And click, click to confirm that it's what I think it is. And in fact, it is, we're seeing the Xcode icon there. And now I'm just going to have that imageView show the Xcode icon instead. So, I'll say, "imageView.image equals myImage".

We'll re-execute and now you're seeing this new result, let's add it to the timeline as well. So you can see here that we have what we expected. The Xcode icon is showing up in our imageView. You'll probably also notice that we're still seeing the older version here with the user icon in the imageView.

And that's because Playgrounds actually capture results on every single line of execution. So you can do these kinds of comparisons. So like for instance, you know, let's look at the imageView when we first create it. And it's empty. Then I added the user icon to there. And so, we see that earlier version that we saw where it's small in the center.

Then I set the image scaling appropriately and it's now filling full image view. Finally, I updated it to use myImage and we're seeing that it's showing the Xcode icon. And that's great, so that you don't have, you know, go back and see what happened at a particular point. We're capturing the data for you as your Playground executes.

So I think that about covers the basics, so let's go back to slides and talk a little bit more about Playgrounds. So one of the key ideas that you saw there is that Playgrounds will automatically execute. You just type in some code and you'll see the results in a sidebar on the right.

Additionally, you saw that we can add a value history to the timeline. So here we have a line of code which executed 100 times. And if I hover over that result, you'll see this Value History button. If I click it, we'll switch into the assistant editor and we'll show that as a history of that value.

Additionally, many values in the Playground have Quick Looks. All right. So in this case we have an attributed string. We don't see the full representation of the sidebar, just kind of the plain text of it. But if I click on the Quick Look button, we'll see the attributed string as it was created in the Playground source.

We support many different types for Quick Looks in the Playground. We support colors, strings -- both plain text and attributed. We can show images, views, in this case we'll capture a snapshot of the view at that point in time. We can show arrays and dictionaries as we'll show a structured version of the array or dictionary, ah, like you might see in the variables view on the debugger.

We can show points, rects, and sizes. We'll kind of create a graphical representation of those. We can show Bézier paths, so both NSBezierPath on the Mac and UIBezierPath on iOS. We can show URLs, for this we'll take the plain text of the URL and show it in the sidebar. But if you Quick Look, it will show you a web view with the contents of that URL.

And finally, for types if we don't have a native Quick Look representation, we can usually get a structured view of it, again, like you would see in the variables view in the debugger. So here I have an object of a class that I created in the Playground. And it is, it has a couple of properties, a foo property and a bar property. And you're seeing the values of those at that line of code when it executed.

In this demo, I also showed you how you can use your own resources with Playgrounds. And this is actually fairly easy. So you just go ahead and show the file inspector. You select a location for Playground resources. And for this we have three options. We've got an Absolute Path option which basically says, "OK, I've got this folder of resources somewhere on my computer and I'd like to show it and use it with the Playground." We have a Relative to Playground path option.

And this is really great if you're checking your Playground into SCM. Because you can say, "Oh, you know, here's this Playground and here's this folder of resources that's next to it, I can set this up and then when you use other people to check out your repository, then it will automatically be able to use the Playground with its resources." Finally, we support an Inside Playground option. And this is great if you're sharing in ways other than via SCM.

Because you can just say, "I want to store my resources in my Playground" and you can email that out to other people and see, when they open it, they'll be able to see those resources immediately. Once you have made the selection, to access these resources in your Playground source, you just use things like, NSBundle.pathForResource ofType and NSImage named. The resources just show up as the resources for the main bundle during Playground execution.

So, now that we have the basics out of the way, I think I'd like to start talking to you about some of the use cases for which Playgrounds would be really great. And the first of these is Experimentation. I'm sure that all of you out there have a folder on your computer which looks something like this. It's just a bunch of Xcode projects created from the template that are, you know, maybe 1 or 2 changes to see how something works or to test out an idea.

It's actually isn't that easy of a process. You know, you have to do many different -- you have to first choose the right project template then find the right file in that project to edit which may be easy or maybe not depending on which template you chose. You'd have to do what you're trying to do in the first place, and that's write some code. Once you've written something, you then have to build your project.

You then run whatever you built. And for iOS that may involve deploying to a simulator or to a device. And if you didn't get it right the first time, you'd then have to redo this, stop in the debugger and step through your code to figure out where things are going wrong.

We think Playgrounds can handle this a whole lot better. That's because there's really only 2 steps. You would just, say, get started with a Playground and write your code. Once you start writing your code, we'll automatically execute it for you and show you the results in the sidebar so you can see where things are going wrong.

So now, I think I'd like to show you a demo of what this looks like. So let's go back to the demo machine. So here I am. I'm going to go ahead and just launch Xcode again. And this time I'm going to create an iOS-based Playground. So I'll say, File, New File, and I'll say, iOS Playground.

And I want to actually test out how the UITableViewCell style API works. So, I'm just going to call and create this Playground and call it TestTableViewCell. Save it to the desktop, and OK. So, here we have our iOS Playground. It's, you know, importing UIKit, but otherwise, it's the same, we're just creating a string and assigning it to a variable.

So, if I want to use a UITableViewCell style, I need a UITableViewCell. And the best way to show that is with a UITableView. In order to get those cells into my UITableView, I need a data source. So, let's just go ahead and implement a data source. So I'll say "class DataSource". We'll inherit from NSObject and we'll conform to the UITableViewDataSource protocol.

Notice now that we're getting an issue here and that's because the DataSource we've created does not actually conform to UITableViewDataSource. And, you know, that's expected. We haven't actually implemented any methods yet. So, I'm actually going to jump to the declaration of UITableViewDataSource by command-option-clicking on it. We see that we then open the assistant editor. And instead of showing you UITableView.h, we're going to show you a Swift version of that header.

So, in this case, we're seeing, you know, here's our protocol. We're seeing that we need to implement these two methods. And so, OK, I'm just going to take this one, this first one to tell the TableView the number of rows per section. I'm going to copy and paste it in here. And then I'm just going to start things out, return 1 from this. So, OK. So that's the number of rows. Let's also provide the cell.

And OK, let's just go ahead and create our UITableViewCell. Let's say let cell equals UITableViewCell. I need to fix this typo. Here, we'll say the style, we'll just say the default style. And then for the reuseIdentifier, we aren't actually going to be reusing these cells so we can just pass nil for this parameter. And OK, so there we have our cell. Let's go ahead and configure it. So, I can say something like cell.textLabel.text equals Text.

OK. So that's the text label. We'll see what that looks like. UITableViewCell may also have a detail text label. But that's not guaranteed to be the case. So I'm going to explicitly handle the fact that it's an optional. So, I can say something like "if let detailTextLabel equals cell.DetailTextLabel".

And so, if the code inside of this "if" executes, then we'll know that we have a detailTextLabel. So, I can say something like, detailTextLabel.text equals Detail Text, and we know that this is safe. We're not going to accidentally try to assign a property to nil. So now that we've configured our UITableViewCell, I can just go ahead and return that.

You can see now that we no longer have an issue in our Playground. But we're also not getting any results in the sidebar. That's because we haven't actually instantiated our data source. So, I'll just say something like DataSource equals DataSource and then I can, you know, I'll just create a TableView and tell it to use our DataSource. So, let tableView equals UITableView.

We'll pass it a frame so, CGRect. Again, we don't care about the origin. I'll pass 320 for the width, and for the height we just need enough to be able to show all the cells we care about. So, I'll just say something like 240. Finally, we'll pass a style of Plain. We'll then tell the tableView to use our DataSource.

And then, we will tell the tableView to reload data. Let that Playground execute. And once it's finished executing, we'll be able to see the tableView we've created. So, I'm going to just go ahead and add this to the timeline. We can see here that we've created our tableView, you know, we're seeing the cell that we want, with the text that we want.

So, OK. So that, you know, gets us up and running. But actually I want to see the styles for all the styles that we have. So, I'm going to jump back to the declaration of UITableViewCell style. And you can see here that there are 4 options. So I'm going to change this 1 to a 4, so if 4 rows. Instead of always passing the default style, I'm going to conditionalize it based on the row that we're currently at. So, I'll say let row equals IndexPath.row. And I'll say something like let style equals UITableViewCellStyle.fromRaw.

I'll pass the row. This fromRaw will convert the UITable, the raw row integer into a UITableViewCell style optional. And we confirm that by using quick help and we can say that, "Oh, yes in fact, this style is an optional UITableViewCell style." If we were to pass this directly here, we would get an error as you can see here. We need to explicitly handle the fact that this could be nil.

You know, the UITableViewCell initializer doesn't expect that. So, let's go ahead and check that. So we'll say, if we have a style, let's unwrap it, otherwise you just use the default style. It's OK. Now that we've handled that, let the Playground re-execute and let's jump back to the timeline using the jump bar.

And once it's re-executed, we'll notice here that we're now seeing all the different UITableViewCell styles in our tableView. And so now, I have a Playground which I can, you know, share with my co-workers or just keep it as a reference for myself to see what each UITableViewCell style looks like. Let's go back to slides now.

So that showed you how great Playgrounds are for experimentation. You just get started with an idea, write some code, and see how it works. And now I'd like to invite Rick back on stage to talk about another great idea we have for Playgrounds and that's Algorithm Development. Rick?

Thanks, Connor. Developing algorithms and any other separable pieces of code in a Playground is a great way to go. And so to show you that, I'm going to dive right into a demo. So what we're going to do today is implement insertion sort, a fairly straightforward sort. We're going to create a brand new Playground to do that. So I'll just say get started with a Playground, and we'll call the Playground InsertionSort and save it on the desktop.

If you're not familiar with insertion sort, imagine that you have a hand of cards and you want to put them in order with the lowest values in the left and the highest values on the right. One way you might do that is, start with the second to leftmost card and compare its value to the leftmost card. If it's less, you'd swap the position of the two cards in your hand.

You'd then look at the third to leftmost card and compare it to the second to leftmost. If it's less, you'd swap it, compare it to the leftmost card, swap it if needed, and go on doing this for every card in your hand until every card had reached the correct, sorted position. When you're done, your hand will be in order.

So, let's implement that in a Playground. To start with, we need some random data that we're going to sort. So, I'm going to go ahead and I'm going to declare an array of data. I'm going to use var because this needs to be a mutable array, so I can add to it and sort it. And we'll just make an empty array of ints to start with.

And I could say for i in 0 through 20, because maybe I want 20 data points. I can say data.append to add a new element. And let's use the arc4random function to generate a random number. That doesn't return a Swift Int, so we're going to cast it explicitly to a Swift Int.

And we'll modulus it by 100 to get a number between 0 and 99. So if I look at data here, you can see I have a result here on the right. Here's an array of what look like pretty random numbers. You'll also notice if I edit the Playground source again it reruns and I get a different array of random numbers.

Ah, OK, so that's great. Well, it's nice to be able to generate random data but I probably don't want it to change on me every time I edit the Playground source because that might make it hard to develop my algorithm. So, let's grab this random data and use it every time. To do that, I'm going to click over the result sidebar and use command-A to select this data, command-C to copy it, and then I'm just going to paste this in here as array literal. And now I can work off the same random data every time.

OK. So, let's start implementing our algorithm. The first thing we need is a function to swap two points of data in our array. There actually is a built-in function called swap for this already. But for the sake of argument, we'll implement it ourselves. So, I'm going to say func. I'll call mine exchange.

You know, we're going to make this a generic because, well, we have an array of ints. Our insertion sort should be able to work on any type. So, any type at least as long as it's comparable. One element can be compared as greater than or less than another.

So, we'll mostly work on comparable types here, the exchange function can work on any type because we just are swapping types. So this is an exchange using a type D. And it's going to take an array of T and two indexes which we're going to exchange in the array.

So, the simplest way to exchange these objects is to assign one to a temporary variable, assign the second to the first, and assign the temporary variable to the second. So, we can say let temp equals data of i. Data of i equals data of j. And data of j equals temp.

OK. I think we've implemented this correctly but let's try it and find out. I can say exchange, pass my data array and we'll say exchange the 0th element with the second element. And then we'll take a look at our array when we're done. So, before, element 0 was 12, and element 2 was 15, now element 0 is 15 and element 2 is 12. So, it looks like exchange works properly.

OK. The next thing we need is a function to, given an index, look at the data point of that index, compare it to the data point to its left; if it's less, exchange them and keep comparing and exchanging until it reaches the correct position in the array. So, let's call this function swapLeft.

Again, it's a generic but this time we need to actually do a comparison. So, we're going to say our type D is comparable and we're going to pass an array of T and an index of the data point we want to start swapping left. OK. So, let's implement this, we're going to start with our index and go back to position 1, not 0 because there's nothing to the left of 0 to swap.

So, I'm going to say for i in, and, you know, I could do a range from 1 to index but what I really want is index to 1. So I'm going to reverse the range with reverse 1. 3 dots makes it a fully closed range which means it will go all the way to index. So, since I'm reversing this, it goes from index and ends at 1.

And for each of these data points, I'm just going to say if data of i is less than data of i minus 1, exchange data i and i minus 1. OK. If it's not less than data of i minus 1, it must have reached the correct sort of position in the array, so we can stop there. So, let's say else break.

OK. Let's try this function out. I'm going to go ahead and say swapLeft, pass data, and let's pass element 1, 2, 3, 4, 5, 6. Let's pass element 6 left. Oops! And look at our data. And you can see the 0 has moved all the way from the 6th position to the beginning of the array and everything's been moved to the right. So it looks like this function is working great too.

OK. The last thing we need is to actually implement the sort, so this should be pretty simple. We'll call our function isort, works again on type T that is comparable. And we can just pass an array of T and it will sort the whole array. To do this, I'm just going to say for i in 1 (we're starting at 1 because there's nothing to the left of 0 to sort to) to data.count, swapLeft, data and i. So, let's try it out, isort data.

And we'll look our data array when we're done. And you can see it did a whole bunch of assignments up here. And now here's our final array and it looks like this is in sorted order. So, we've correctly implemented insertion sort. So, this is great for a simple algorithm like insertion sort. That wasn't too hard. But you know if I was doing something more complicated, it might be nice to have more visibility into exactly what's going on here.

So, let's look at how we might visualize our results in more detail. Well to start out with, let's draw a graph of the results of the data at the beginning. To do that, I'm just going to say for x in data (to iterate through every data point) and just print out x.

And so, you'll see there are 20 data points here. So this line executed 20 times. And if I click on the Value History button, I get a nice graph here showing my data at the beginning and, boy, that does look random. OK. So, now I want to try to print out another graph every time swapLeft is called, so I can see what's happening to the graph over iterations of swapLeft. And I could put this "for" statement in the end of swapLeft again and show the Value History.

But again, in Value History Timeline item for given, a line is going to show all the data from that line. So, each time swapLeft is called, its data would be appended to the same graph. That's not what I want. I want a new graph, every time it's called. So to do that, we're going to need a new tool in our toolbox. I'm going to go back to slides and show you that. With Playgrounds, we're shipping a new framework called XCPlayground and it contains some very useful utilities for enhancing your Playgrounds.

Right now, we have API for manually capturing values to display in timeline items, showing your views live and extending execution for asynchronous code. Right now, we're going to use the API for manually capturing values. That API is called XCPCaptureValue. It's a function that takes an identifier, which is a string, and your value, which is of any type.

When you pass it -- your value -- it will take that value and put it in a timeline item for you. So, the identifier that you pass it identifies what timeline item you want that value to go to. If you call this function on different lines but pass the same identifier, the values from those different lines will go to the same timeline item. Conversely, and what we want here, if you have one line that calls XCPCaptureValue but it's called multiple times with different identifiers and it passes those different identifiers, that one line can generate multiple different timeline items (or grabs, in our case).

That identifier is also shown as the name of the timeline item so you can easily see what data is what. The value pass can be anything, because it's a generic but it helps if it's a type of value that we know how to Quick Look appropriately. So, let's go back and give this a shot. So to start out with, I need to import XCPlayground to make this API available and I'm going to go ahead and define a new function.

I'll call it visualize and it's a generic. And it will take an array of type T and I'm going to use this "for" loop in it, so I'll just indent that and close the function. But instead of just printing out x, what we want to do is capture that value. So, I'll call XCPCaptureValue. I need an identifier, so let's add one to our function. So, identifier is a string and we could pass that identifier, and our value is x.

OK. So let's try this function out and visualize the data at the start of our sort and we'll label it Start as the identifier just so we know what's what. And here you can see it ran and here's our data at the start. So that's a good start.

So now, we're going to go ahead and visualize our data after every iteration of swapLeft. So, I can call visualize, I'll pass data as it is after this iteration of swapLeft. And for our identifier, let's label it after the iteration, the number of times that swapLeft is called, which is the index parameter.

And so, I'm going to let this run now. And you can see that it's generated multiple graphs labeled after the iteration that we're on. So, now we can just scroll through here and see what's happening to our data over time as swapLeft runs and the sort completes. You can see it looks like our data is getting sorted piece by piece. And so, at the end, we have a nicely-sorted array. So there, we can easily visualize exactly what's going on with our algorithm. We think you'll find this very, very useful.

OK. Let's move on to another example. I've got a heap Playground I made here earlier. And it's got this HeapGrapher class at the top which I'll explain in a moment. But the meat of this class is my heap class which, if you're not familiar with a heap, a heap is a type of balanced binary tree where the value of every node is greater than or equal to the value of its children.

Heaps are often used to implement priority queues, because it's very efficient to remove the highest priority item, that's the top of the tree, and it's also efficient to insert new items into the correct position of the tree for their priority. We're implementing our heap with an underlying array to represent the tree.

And in our array, the tree noted index i has children at indexes i times 2 and i times 2 plus 1. So you can see down here at the bottom we've got some random data that we seeded ourselves with. And we've created a new heap with that data. And we "heapified the heap," which is to say, put that data into correctly heap-sorted order.

On the right, in the results sidebar, you can see our default treatment of this custom class is to show the name of the class and show its properties. In this case, it has one property which is that heap array and here it is before it's been heapified, when it's not a correct heap.

And here it is after it's been heapified, when it's purportedly a correct heap. But you know, it's really hard to tell looking at this array whether that's a correct heap. This array represents a tree and, you know, not so good at visualizing, "Hh, well, here's I, and here's i times 2, and yeah, that's less..." Wouldn't it be much better if I could just visualize this as a tree everywhere my heap is referenced to my Playground source? So let's see how to do that. In order to visualize my own custom class, we're going to implement Custom Quick Look Support for this class.

Our Custom Quick Look Support allows you to add Quick Looks for subclasses of NSObject only (right now). And to do it, you implement the debugQuickLookObject method which takes no parameters and returns any object as an optional. And you're going to return the value that you want to represent your object as its Quick Look. So, right now, that value (the values that we support here) are colors, strings (both plain and attributed), images, and Bézier paths. So, for your Custom Quick Looks you can use any of these types. So, let's try it out.

OK. So I mentioned before I had a little HeapGrapher class that I wrote. That's a little class that knows how to take an array and draw it as a tree, so we're going to use that. We'll implement our debugQuickLookObject method. It takes any, or returns any object as an optional and we're just going to create one of our HeapGraphers.

And this HeapGrapher knows how to generate an NSImage which is one of the Custom Quick Look types, supported types. So, we're just going to return the image it generates with g.graphHeap and pass self.heaparray. And now, when this runs, instead of showing the default representation for our class, it shows our custom Quick Look representation, which is an image. And so when I click the Quick Look button, you can see here it's drawing my heap as a tree. This is before it's been heapified when you can see, for example, 78 is less than 89. So this is not a correct heap.

But if I Quick Look it after it's been heapified, I can now go, oh great, 91 is greater than 86 and 89, 86 is greater than 84 and 79, and so on and so forth, and I can really easily visually verify that this is a correct heap. So that's how you can Quick Look your own classes in Playgrounds and we think you'll find that very useful. All right. Next, we'd like to move on to showing you how great it is to do Custom View Development and other drawing development in Playground. And to do that, I'm going to hand it over to Connor.

Thank you, Rick. Another great use case we think Playgrounds will be used for is Custom View Development. And that's because you can just start writing some code and see the actual view as it's being drawn and as you're starting to build up your drawing code. So for this I have a goal. I want to take this Playground icon and add some animation to it.

The icon that we have is really great. It conveys the playfulness of Playgrounds. But unlike Playgrounds themselves, it's static. There's nothing dynamic about it. And so, I'm going to try to add animation to this. And what better way to do it than when in a Playground itself? So, let's jump over to the demo. So OK, here I'm going to go ahead and open up a Playground that I've already started.

So, OK. So here we've got a Playground. We've got our subclass of NSView called PlaygroundIconView. It has a few layers. It's got these three instance, er, these three instance methods which actually do the setup of those layers. You see that they're unimplemented right now and we'll come back to that in a moment. I also have an extension of NSColor which defines a couple of colors for the Playground icon itself.

I then have a helper function to convert an NSBezierPath to a CGPath for use with CAShapeLayer. Finally, I just go ahead and create an instance of my PlaygroundIconView. And then, I put it on a separate line so I can add some stuff later. Let's go ahead and show that in the timeline.

So, OK. So you'll see now that we've just got ourselves an empty view here. So yes, we have an empty view here. We actually just now need to go ahead and implement these setup functions. So let's go ahead and do that. So we'll start out by creating the path for the background layer.

So you can see here we're creating NSBezierPath and we can Quick Look it to make sure it looks right. And in fact, yeah, that looks more or less like the Playground icon. So let's tell, let's setup our layer. So OK, now we're setting up the layer. You can see here in the timeline that we're now drawing the layer where, you know... We have the background, we've got the little border there, and so, OK, we've got our background set up.

Let's also do the seesaw base and we'll do the same thing. We'll create a path for that. And we'll let it execute and we'll see here, let's Quick Look, make sure... Yeah, that looks more or less like the little base that we have for the play- ...for the seesaw. So let's set up the layer itself as well.

And there, we just make that change and immediately get the feedback of seeing what that looks like when drawn in our view. Let's also do the seesaw layer. I've got some code here to set that up as well. You see here that we're just, you know, have a closure which will create the child layer itself.

We then create a couple of layers for the children on each side of the seesaw, and then we set up the bench itself and then add those layers to our seesaw layer. So, OK. So now we've got ourselves something that looks kind of like the Playground icon. But like the icon itself, it's not animating. So let's go ahead and add support for animation to our PlaygroundIconView. I have a snippet for that as well.

And so, let's walk through what this is doing. I define a constant for the maximum angle of the seesaw. I've, you know, worked through this and I think pi over 12 is about right. I also have a property for the current angle of the seesaw after any pending animation is finished.

And then have a property which determines whether or not it should be animating. It starts out as false but we have this code here which executes whenever this is set to say, "Well, if the animation state has changed and we're told to animate, then just start animating depending on the current angle of the seesaw." I then have this helper method for actually performing the animation itself.

So we just, you know, go ahead and create a CABasicAnimation, set a couple of values, set our timing function to match what a seesaw would actually look like. Set the duration to what was passed in which defaults to 1-1/2 seconds, but can be customized depending on the angle of the seesaw.

We then add the animation to our seesaw layer. We set the underlying transform property of that seesaw layer, so that once the animation completes it looks correct. And then we update our current seesaw angle property accordingly. Finally, we have, uh, we implement the "animationDidStop, finished" delegate callback. Or basically say that if we finished and we're still supposed to still be animating, then just go ahead and animate to the opposite angle of what we currently are at. So, OK. Let's go ahead and tell this view to start animating.

So we'll do that and you'll notice that after it reruns, we seeing the view update it's look, you know, so we see that it tilted over to the side. We're not seeing the animation itself. And for that, we're going to need some help from the XCPlayground framework. So, let's switch back the slides to see what that could look like. So the second piece of functionality which the XCPlayground framework provides is the ability to show live views in the timeline.

And you do that by calling this XCPShowView function. It takes an identifier and the view that you want to show. After calling it, we'll show the view live while the Playground executes and then we'll record frames as the Playground executes so you can play them back once execution finishes.

The identifier you pass to this function must be unique inside of the Playground. That's because this is how we refer to the live view internally in Xcode. And it is also what we'd show as the title for the live view in the timeline. The view pass must also not have a superview.

This is because we will add it to our own view hierarchy and it would generally not produce the results you're looking for. So with this in our toolbox, let's jump back to the demo and see how it's used. So I'm going to go ahead and just go ahead and import XCPlayground.

And then down here, instead of just having this view item, I'm going to remove that from the timeline. I'm going to say something like XCPShowView and pass an identifier. It can be anything as long as it's unique. So I'll say Playground Icon View. And then I'll pass the view that we've created.

So, we'll just let that re-execute. And you see there that in the timeline, we're showing the view live as it's animating. You-all also probably noticed this little timeout field down here. And that lets us specify the amount of time which we'll let the Playground continue executing after we reach the end of execution of the top of a code.

Now, it defaults to 30 seconds but I'm going to adjust this down since I know my animation only takes about a second and a half. So I'll do 10 seconds to get a few times around. After we edit that, we'll rerun it. And so that's great, you know, we see it running there. And I'd like to show how you can integrate XCPShowView with the XCPCaptureValue API we mentioned earlier.

And so, what I'm going to do, I'm going to capture the angle of the seesaw, or of the left edge of the seesaw as we're animating. So here, I'm just going to say XCPCaptureValue. I'll pass Left Seesaw Position and I'll just pass 0 because we know at this point that it's, you know, it's flat on there. Then you can take this and I'm going to put it in our "animationDidStop, finished" callback. Now I'm going to just pass the negative currentSeesawAngle.

That's just because that's what we need to do in order to get the left position of the seesaw. That is how the angle works out for the transform. So you see here that as we're executing, we're getting the graph kind of building up over time. And then once execution finishes, the graph will snap back into place and kind of show you the best view of the data that it collected.

It's OK. You probably also noticed this slider became active. And so, I can just go ahead and take that and drag it through here. And you'll notice that we're updating the graph at the bottom but we're also showing you the animation, you know, as it went through in time. So this is, you know, a fairly basic animation and it's doing what we expected but, you know, if you had something more complex and you want to just kind of take a look at just a small portion of your animation, you could do that as well.

And I can also do something like, you know, click on one of these points. So I can click there. We can see it, you know, that the two things are in sync. I click there. It updates the point. I can use the arrow keys to go through the graph's points and see that, OK, yeah, you know, we're doing what we expect it to do.

And so, that's how you can show live views in the timeline with the XCPlayground framework. Let's go back to the slides now. Now, I'd like to talk to you about how you can use asynchronous code in your Playgrounds. You got a little taste of this in the demo before. But I'd like to go into a little bit more detail now.

The third piece of functionality which the XCPlayground framework provides is the ability to extend execution. By default, execution terminates once all top-level code has executed. XCPlayground, though, provides API for extending execution indefinitely. That's this XCPSetExecutionShould ContinueIndefinitely function. You should know that this is actually not quite indefinite. The execution time is controlled by the timeline's timeout which defaults to 30 seconds. Additionally, execution will be terminated if you edit the Playground while it's running. This is so that we can show you up to date results rather than let, leaving you a stale results while we wait for an earlier execution to finish.

Additionally, as you saw on the last demo, you know, we didn't actually call this function, but we saw that execution continued after we reached the end of top-level code. That's because XCPShowView implicitly calls XCPSetExecutionShould ContinueIndefinitely. You should just think about this as if nothing in the Playground source has told Xcode that the Playground used to stay alive, then the Playground will stop executing once we reach the end of top-level code.

So now, I'd like to show you a quick demo of what it's like to use asynchronous code in Playgrounds. So here I am back here and I have a Playground which uses asynchronous code. We create, uh, we have our session delegate which is an NSURLSessionDelegate. It has a few callbacks. And then we also just, you know, create an instance of our delegate. We created an NSURLSession.

And then create a data task to download the contents of the Apple home page. We then tell the data task to resume. And you noticed that, you know, the Playground itself has executed but we're not receiving any results up here. And if I open up the assistant editor, you'll notice that we haven't received any console output even though they were clearly logging here that we've received some bytes.

And this is because nothing in the Playground has told the Playground that it should continue executing. So we call task.resume, we resume the task and then as soon as that finishes, we hit the end of top-level code and the Playground just stops executing. Let's go ahead and say import XCPlayground.

And then we can say XCPSetExecution ShouldContinue, XCPSetExecutionShould ContinueIndefinitely. This takes a Bool but that defaults to true, so you typically don't need to pass anything there. And I won't do that here. You'll now notice that, you know, we were receiving results from here and we're also seeing the console output that we expect in the timeline.

So OK, that's how you use asynchronous code in Playgrounds. Let's go back to slides now. There are a few alternatives but we really think that you should typically use XCPSetExecutionShould ContinueIndefinitely when you're trying to use asynchronous code in Playgrounds. If that won't work for you though, you can use other methods for waiting for asynchronous operations to finish. Basically, you just need to make sure you don't reach the end of top-level code before your operation completes. Before we leave today, I'd like to talk to you a little bit about some of the limitations we have with Playgrounds.

First off, you should not use performance, uh, Playgrounds for any performance testing. That's because the logging of results in the Playground will generally dominate the runtime, not your actual code. This means that the performance will be dependent on the number of lines of code executed, not the actual performance of whatever it is you are developing.

And that's not necessarily what you'd expect. Instead we'd suggest that you use the XCTest framework to create performance tests in a test bundle where you can get more accurate results. We have a session later this week called Testing in Xcode 6 which will go into this in more detail.

There are few more limitations with Playgrounds. Playgrounds cannot be used for things which require user interaction. So we have great support for showing live views but you can only see them, you can't touch them. We also do not support using Playgrounds for anything which require custom entitlements. For iOS Playgrounds, we only support executing against the simulator. So anything which requires a device will not be supported with Playgrounds.

And finally, we do not support using your own app or framework code in a Playground unless it's something that you can just copy and paste into the Playground source. Basically, you can only use things in the standard library, in the SDK, or that's in the Playground source itself.

You can get around some of these limitations by using the REPL. The REPL is the command line interface to Swift and it works this way because the REPL can actually execute in your own process. You just stop at a breakpoint, and then at the LLDB prompt, you execute the REPL command and you'll just be dropped down right into the Swift REPL.

Playgrounds though provide a richer experience than the REPL. And that's because we will automatically execute your code from a known state. That means, you know, you make a single edit to a line and then, you know, we just rerun it from 0. Whereas with the REPL, if you wanted to make an edit to something earlier in the source that you had entered, you have to, you know, get the process back into the state then, you know, reenter the REPL, retype everything making that one change to see how it affects things.

Playgrounds also supports some of these higher level futures like Quick Looks and a timeline which we do not support, uh, which the REPL does not support. If you'd like to learn more about the REPL, you can go to the Introduction to LLDB and the Swift REPL talk. And we'll go into much more detail about how the REPL works.

In summary, we think Playgrounds are a great way to play with Swift, with Cocoa and with Cocoa Touch. We think you can use them for things like learning, exploration and visualization and frankly probably tons of things which we haven't even thought of yet. The XCPlayground framework provides APIs for using your Playgrounds for more advanced things. So you can do things like manually capture values with the XCPCaptureValue API. You can show live views in the timeline by calling XCPShowView.

And then you can also extend execution for asynchronous operations with the XCPSetExecutionShould ContinueIndefinitely function. Finally, we'd really like to just encourage you to go out and give Playgrounds a try. I think, you know, they're really approachable and if you just sit down with them for a little bit you'll find a number of great ways to integrate them into your development process.

For more information, you can contact our Developer Tools Evangelist, Dave DeLong. We also have some information about Playgrounds in the Source Editor Help for Xcode 6. You can also ask questions about Playgrounds on the Apple Developer Forums. We have several related sessions about Swift this week. So there was an Introduction to Swift session yesterday, which you can catch on the video. We also have an Intermediate Swift session later this afternoon. There's also an Advanced Swift session tomorrow which you'll be able to see.

We had an Integrating Swift with Objective-C session earlier this morning which you can catch on video. And we also have a Swift Interoperability in Depth session later this afternoon. Finally, if you'd like to learn more about the Swift REPL, you can go to the Introduction to LLDB and the Swift REPL session. Thank you all for coming and I hope you have a great week here at WWDC.