1. 程式人生 > >2014s408 Swift Playgrounds

2014s408 Swift Playgrounds

>> Hi.

Welcome to Swift Playgrounds.

I'm Rick Ballard and with me today is my colleagueConnor Wakamo.

We're both Engineers in the Xcode Teamand we've been working hard to bring Playgrounds to life.

We introduced Playgrounds to the world Monday morningand you saw a little bit moreabout 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 Playgroundsfor learning, exploration, and visualizationof the results of your code.

We'll show you how you can use your own custom resourceswith your Playgrounds, and how to use Playgroundsfor algorithm development and developmentof other separable pieces of code.

We'll introduce the XCPlayground frameworkwhich includes some really powerful utilitiesthat you can use to enhance your Playgrounds.

And we'll show you how you can develop your own Custom QuickLooks, so that you can visualize your own classes the same wayyou visualize the classes that come with the frameworks.

Next, we'll show you a great demoof how awesome Playgrounds are for developing custom viewsand in any other kind of custom drawingand we'll show you how you can use your own asynchronous codewith Playgrounds.

Finally, we'll finish up today with a little bitabout the limitations that Playgrounds have today.

So what exactly are Playgrounds?Playgrounds are a new type of document introduced in Xcode and they're actually a file wrapper containing a fewuseful 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 youedit your Playground file.

Swift Playgrounds also can contain a folderof embedded resources which are made available to your codeor your Playground can reference resources elsewhereon your system you want to make available.

Finally, your Playground can contain a timeline fullof timeline items that provide useful visualizationof 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 leftand the results sidebar on the right showing the resultof every expression in your code.

Every time you edit your source, we rerun your Playground sourcefrom the top to the bottom and present the new resultsfrom that run in the sidebar.

This is the basic editor mode.

But if you go into the assistant editor mode we'll show theTimeline Assistant by default which allows youto visualize your results in more detail.

For example, you can display the value historyfrom a line in your code.

In this case, since it's a numeric value,we'll draw a graph of that value over timesince 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 runafter the top of a source is finishedif 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 timeand view results in the timeline from a specific pointin your Playground execution.

So here, you can see we're viewing a numeric resultfrom partway through the Playground execution.

But you'll find this is very useful with live viewsas it allows you to scrub back through the recordingof that view and see exactly what your animation was doingat 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 useof Playgrounds is going to be learning.

We've introduced a brand new language for you to learnand we think the best way to get started is just to openup a Playground and dive in and play around.

Our documentation also includes a special interactive Playgroundcalled the Swift Tour.

This allows you to see documentationand Playground Editor side by side in the same editor.

So you can read about how to do something and try itout right there without leaving the editor.

Finally, we think Playgrounds are a fantastic way for peopleto learn how to program in the first place.

Beginners don't have to learn how to configure a projectand target and build and run and debug.

They can just type code into a Playground Editorand 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 bein indispensable tool in your toolboxfor everyday code development.

If you're developing an algorithmor 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 projectfor use in your application.

Any sort of drawing code you want to do is also greatin a Playground because you can immediately see the visualresult 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 sequenceof image filters are great in Playgroundsbecause you can visualize the result at every stepof the transformation process.

And when you change something, you can see howthat change ripples through all your results.

We think you'll findthat Playgrounds are fertile ground for experimentation.

And in particular, any time you're tryingto learn some new API, you should try itout on a Playground because you can immediately see how it worksand 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 goneto 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 tooso you can see what happened.

You don't have to do that anymore.

Now you can just open up a Playground and tryout the API you want to try.

In fact, we'd recommend you consider keeping a Playgroundin your doc at all times for quick access.

So anytime you wantto try something it's right there at your fingertips.

So with all that said, let's dive in and take a lookin 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 workwith Playgrounds as well as some of the thingswhich we think Playgrounds will be really great for.

Now, Rick has already covered manyof the basic concepts behind Playgrounds.

And so I think really the best way to show you how to workwith Playgrounds is actually justby 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 goingto go ahead and launch Xcode.

Now you'll notice here that on the Welcome windowfor Xcode we've added this brand new "Get startedwith a Playground" button.

It's that way we want to make it really easy for youto just get started with one.

So I'll just click on that.

We'll create a Playground and I'll just give it a nameand a place to save it.

So "MyPlayground" is fine and puttingon 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 stringand we're assigning the value, "Hello,Playground" to that string.

You'll notice that in the result sidebar we're seeing the resultof 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 codeand we're getting an indicator in the result sidebarthat 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 therethat we immediately get an indicationthat this code has executed 100 times.

Now, knowing that is very useful informationbut 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 seethat we're highlighting the line of codewith 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 wellas a place for you to store results which youlike 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 timelineand 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 showingin the result sidebar a color swatch indicating what the coloris as well as indicators of all of the componentswhich make up that color.

So I can, you know, take this colorand 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 haveand we'll create a dictionary.

So we'll say NSForegroundColorAttributeNameand 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, systemFontOfSizeand then let's go to something fairly big, so I'll just putin 42, see what that looks like.

So, OK.

So here, you noticethat we're getting a result for this as well.

You're seeing that we're showing the plain text representationof this, as well as an icon indicatingthat 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 itselfand we support that as well.

So I can just hover over the result and in additionto 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 Lookof that value to show you the full representation of itas it was created in the Playground source.

So, OK, that's colors and strings.

Let's try something with images.

Let's actually startup 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 dowith like NSImageNameUser or accountsor something in that line.

So I'm just going to create an array with imageNamesthat I think it could be, the ImageNameUser,NameUserAccounts, NSImageNameUserGroup.

It's OK.

We run the code and you noticethat we now have an array of strings.

We actually want to see an array of imagesand 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 lineof 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 timesfor the trailing closure itself.

Then we're executing it once for the assignment to images.

Actually, I only want to see the images array itselfand we have a nice little trick for doing that in a Playground.

You just go ahead and put the thing that you wantto 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 originbecause we don't really care about that.

Then we'll also say by 512 for the size.

Now I'm going to go ahead and put this ImageViewon 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 objectand then you put another line where we show it as a result.

Anyway, I can add some code in between thereto see how it builds up over time.

So you see here that we're startingout 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'rein fact showing the image therebut 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 ImageScaleProportionallyUpOrDown.

And we'll re-execute and now you'll seethat 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'dlike to use in Playgrounds as well.

And we support that too.

So I'm just going to go ahead and I'm goingto 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 Settingswhich is shown whenever you're viewing a Playground document.

You can select the platformagainst 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 oneif you have resources that you're interested in.

In this case, I'm just going to say I have a folder of resourceson 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 aheadand hide the Utilities area.

And to access the images themselves, I just use,you know, NSBundle API, you know, the resources showup 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 noticethat 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 havethat 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 noticethat we're still seeing the older version herewith the user icon in the imageView.

And that's because Playgrounds actually capture resultson every single line of execution.

So you can do these kinds of comparisons.

So like for instance, you know, let's look at the imageViewwhen 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 sawwhere it's small in the center.

Then I set the image scaling appropriatelyand it's now filling full image view.

Finally, I updated it to use myImage and we're seeingthat it's showing the Xcode icon.

And that's great, so that you don't have, you know, go backand 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 backto slides and talk a little bit more about Playgrounds.

So one of the key ideas that you saw there isthat Playgrounds will automatically execute.

You just type in some code and you'll see the resultsin a sidebar on the right.

Additionally, you saw that we can add a value historyto 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 editorand 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 createdin the Playground source.

We support many different typesfor 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 viewat that point in time.

We can show arrays and dictionariesas we'll show a structured version of the arrayor dictionary, ah, like you might seein 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 Macand UIBezierPath on iOS.

We can show URLs, for this we'll take the plain text of the URLand show it in the sidebar.

But if you Quick Look, it will show you a web viewwith the contents of that URL.

And finally, for typesif 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 classthat 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 lineof code when it executed.

In this demo, I also showed you how you can use your ownresources 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 somewhereon my computer and I'd like to show itand use it with the Playground.

"We have a Relative to Playground path option.

And this is really greatif you're checking your Playground into SCM.

Because you can say, "Oh, you know, here's this Playgroundand here's this folder of resources that's next to it,I can set this up and then when you use other people to checkout your repository, then it will automatically be ableto use the Playground with its resources.

"Finally, we support an Inside Playground option.

And this is great if you're sharingin ways other than via SCM.

Because you can just say, "I want to store my resourcesin my Playground" and you can email that out to other peopleand see, when they open it, they'll be ableto 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 resourcesfor 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 someof the use cases for which Playgrounds would bereally great.

And the first of these is Experimentation.

I'm sure that all of you out there have a folderon your computer which looks something like this.

It's just a bunch of Xcode projects createdfrom the template that are, you know, maybe 1 or 2 changesto 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 findthe right file in that project to edit which may be easyor 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 haveto build your project.

You then run whatever you built.

And for iOS that may involve deployingto a simulator or to a device.

And if you didn't get it right the first time, you'd then haveto redo this, stop in the debugger and stepthrough 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 startedwith a Playground and write your code.

Once you start writing your code,we'll automatically execute it for you and show you the resultsin the sidebar so you can see where things are going wrong.

So now, I think I'd like to show you a demoof 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 testout how the UITableViewCell style API works.

So, I'm just going to call and create this Playgroundand 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 cellsinto 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 conformto the UITableViewDataSource protocol.

Notice now that we're getting an issue here and that'sbecause the DataSource we've created does not actuallyconform 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 declarationof 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 oneto 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 cellsso 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 factthat 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 issuein our Playground.

But we're also not getting any results in the sidebar.

That's because we haven't actually instantiated ourdata source.

So, I'll just say something like DataSource equals DataSourceand then I can, you know, I'll just create a TableViewand 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 ableto 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 ableto 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 stylesfor all the styles that we have.

So, I'm going to jump back to the declarationof 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 rowthat we're currently at.

So, I'll say let row equals IndexPath.

row.

And I'll say something like let style equalsUITableViewCellStyle.

fromRaw.

I'll pass the row.

This fromRaw will convert the UITable, the raw row integerinto 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 optionalUITableViewCell 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 backto the timeline using the jump bar.

And once it's re-executed, we'll notice herethat we're now seeing all the different UITableViewCell stylesin 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 referencefor myself to see what each UITableViewCell stylelooks like.

Let's go back to slides now.

So that showed you how great Playgrounds arefor 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 talkabout another great idea we have for Playgroundsand that's Algorithm Development.

Rick?>> Thanks, Connor.

Developing algorithms and any other separable pieces of codein 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 InsertionSortand 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 themin order with the lowest values in the leftand the highest values on the right.

One way you might do that is, start with the secondto leftmost card and compare its value to the leftmost card.

If it's less, you'd swap the positionof the two cards in your hand.

You'd then look at the third to leftmost card and compare itto 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 cardin 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 datathat we're going to sort.

So, I'm going to go ahead and I'm goingto declare an array of data.

I'm going to use var because this needsto 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 functionto generate a random number.

That doesn't return a Swift Int, so we're goingto 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 itreruns 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 databut I probably don't want it to changeon me every time I edit the Playground sourcebecause 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 sidebarand 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 functionto swap two points of data in our array.

There actually is a built-in function called swapfor 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 greaterthan or less than another.

So, we'll mostly work on comparable types here,the exchange function can work on any typebecause 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 indexeswhich we're going to exchange in the array.

So, the simplest way to exchange these objects is to assign oneto 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 correctlybut let's try it and find out.

I can say exchange, pass my data arrayand 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 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 exchanginguntil it reaches the correct position in the array.

So, let's call this function swapLeft.

Again, it's a generic but this time we needto actually do a comparison.

So, we're going to say our type D is comparable and we're goingto pass an array of T and an index of the data point we wantto start swapping left.

OK.

So, let's implement this, we're going to startwith 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 indexbut 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 rangewhich 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 sayif 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 positionin 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 has moved all the wayfrom the 6th position to the beginning of the arrayand 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 Tand it will sort the whole array.

To do this, I'm just going to say for i in 1 (we're startingat 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 lookslike 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 visibilityinto exactly what's going on here.

So, let's look at how we might visualize our resultsin more detail.

Well to start out with, let's draw a graph of the resultsof the data at the beginning.

To do that, I'm just going to say for x in data (to iteratethrough 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 printout another graph every time swapLeft is called,so I can see what's happening to the graphover iterations of swapLeft.

And I could put this "for" statement in the endof 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 calledXCPlayground and it contains some very useful utilitiesfor enhancing your Playgrounds.

Right now, we have API for manually capturing valuesto display in timeline items, showing your views liveand extending execution for asynchronous code.

Right now, we're going to use the APIfor 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 valueand put it in a timeline item for you.

So, the identifier that you pass it identifies what timeline itemyou want that value to go to.

If you call this function on different linesbut pass the same identifier,the values from those different lines will goto the same timeline item.

Conversely, and what we want here, if you have one linethat calls XCPCaptureValue but it's called multiple timeswith different identifiersand it passes those different identifiers,that one line can generate multiple different timelineitems (or grabs, in our case).

That identifier is also shown as the name of the timeline itemso you can easily see what data is what.

The value pass can be anything, because it's a genericbut it helps if it's a type of value that we know howto Quick Look appropriately.

So, let's go back and give this a shot.

So to start out with, I need to import XCPlaygroundto make this API available and I'm going to go aheadand 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 thatand close the function.

But instead of just printing out x, what we wantto 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 passthat identifier, and our value is x.

OK.

So let's try this function out and visualize the dataat the start of our sort and we'll label it Startas 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 dataafter every iteration of swapLeft.

So, I can call visualize, I'll pass data as it isafter 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 graphslabeled after the iteration that we're on.

So, now we can just scroll through hereand see what's happening to our data over time as swapLeft runsand the sort completes.

You can see it looks like our data is getting sorted pieceby piece.

And so, at the end, we have a nicely-sorted array.

So there, we can easily visualize exactly what's goingon 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 topwhich 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 typeof balanced binary tree where the valueof every node is greater than or equalto the value of its children.

Heaps are often used to implement priority queues,because it's very efficientto remove the highest priority item, that's the topof the tree, and it's also efficient to insert new itemsinto the correct position of the tree for their priority.

We're implementing our heap with an underlying arrayto represent the tree.

And in our array, the tree noted index i has childrenat indexes i times and i times 2 plus 1.

So you can see down hereat the bottom we've got some random datathat 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 datainto correctly heap-sorted order.

On the right, in the results sidebar,you can see our default treatmentof this custom class is to show the name of the classand show its properties.

In this case, it has one property which isthat 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 lookingat 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 thisas a tree everywhere my heap is referencedto 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 Supportfor this class.

Our Custom Quick Look Support allows you to add Quick Looksfor subclasses of NSObject only (right now).

And to do it, you implement the debugQuickLookObject methodwhich takes no parametersand returns any object as an optional.

And you're going to return the value that you wantto represent your object as its Quick Look.

So, right now, that value (the valuesthat we support here) are colors, strings (both plainand 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 classthat I wrote.

That's a little class that knows how to take an array and draw itas a tree, so we're going to use that.

We'll implement our debugQuickLookObject method.

It takes any, or returns any object as an optionaland we're just going to create one of our HeapGraphers.

And this HeapGrapher knows how to generate an NSImagewhich is one of the Custom Quick Look types, supported types.

So, we're just going to return the image it generateswith g.

graphHeap and pass self.

heaparray.

And now, when this runs, insteadof 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, 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 verifythat this is a correct heap.

So that's how you can Quick Look your own classes in Playgroundsand we think you'll find that very useful.

All right.

Next, we'd like to move on to showing you how great it isto do Custom View Developmentand 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 usedfor is Custom View Development.

And that's because you can just start writing some codeand see the actual view as it's being drawnand as you're starting to build up your drawing code.

So for this I have a goal.

I want to take this Playground iconand 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 whenin a Playground itself?So, let's jump over to the demo.

So OK, here I'm going to go ahead and open up a Playgroundthat 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 methodswhich actually do the setup of those layers.

You see that they're unimplemented right nowand we'll come back to that in a moment.

I also have an extension of NSColor which defines a coupleof colors for the Playground icon itself.

I then have a helper function to convert an NSBezierPathto a CGPath for use with CAShapeLayer.

Finally, I just go ahead and create an instanceof my PlaygroundIconView.

And then, I put it on a separate lineso I can add some stuff later.

Let's go ahead and show that in the timeline.

So, OK.

So you'll see nowthat we've just got ourselves an empty view here.

So yes, we have an empty view here.

We actually just now need to go aheadand implement these setup functions.

So let's go ahead and do that.

So we'll start out by creating the pathfor the background layer.

So you can see here we're creating NSBezierPathand we can Quick Look it to make sure it looks right.

And in fact, yeah, that looks more or lesslike 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 timelinethat 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 basethat we have for the play- .

.

.

for the seesaw.

So let's set up the layer itself as well.

And there, we just make that changeand immediately get the feedback of seeing what that lookslike 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 closurewhich will create the child layer itself.

We then create a couple of layers for the childrenon each side of the seesaw, and then we set up the bench itselfand then add those layers to our seesaw layer.

So, OK.

So now we've got ourselves somethingthat 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 animationto 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 piover 12 is about right.

I also have a property for the current angle of the seesawafter any pending animation is finished.

And then have a property which determines whetheror not it should be animating.

It starts out as false but we have this code herewhich executes whenever this is set to say, "Well,if the animation state has changed and we're toldto animate, then just start animating dependingon the current angle of the seesaw.

"I then have this helper methodfor actually performing the animation itself.

So we just, you know, go ahead and create a CABasicAnimation,set a couple of values, set our timing functionto match what a seesaw would actually look like.

Set the duration to what was passed in which defaultsto 1-1/2 seconds, but can be customized dependingon 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 angleproperty accordingly.

Finally, we have, uh, we implement the "animationDidStop,finished" delegate callback.

Or basically say that if we finishedand we're still supposed to still be animating,then just go ahead and animate to the opposite angleof 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 helpfrom the XCPlayground framework.

So, let's switch back the slidesto see what that could look like.

So the second piece of functionalitywhich the XCPlayground framework provides is the abilityto 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 Playgroundexecutes and then we'll record framesas the Playground executesso you can play them back once execution finishes.

The identifier you pass to this function must be unique insideof the Playground.

That's because this is how we referto the live view internally in Xcode.

And it is also what we'd show as the titlefor 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 hierarchyand it would generally not produce the results you'relooking for.

So with this in our toolbox, let's jump back to the demoand see how it's used.

So I'm going to go ahead and just go aheadand 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 XCPShowViewand 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 fielddown here.

And that lets us specify the amount of timewhich we'll let the Playground continue executingafter we reach the end of execution of the top of a code.

Now, it defaults to 30 seconds but I'm going to adjust thisdown since I know my animation only takesabout 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 XCPShowViewwith the XCPCaptureValue API we mentioned earlier.

And so, what I'm going to do, I'm going to capture the angleof the seesaw, or of the left edgeof 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 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 orderto 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 kindof show you the best view of the data that it collected.

It's OK.

You probably also noticed this sliderbecame active.

And so, I can just go ahead and take thatand drag it through here.

And you'll notice that we're updating the graph at the bottombut we're also showing you the animation, you know,as it went through in time.

So this is, you know, a fairly basic animationand it's doing what we expected but, you know,if you had something more complex and you wantto just kind of take a look at just a small portionof 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 pointsand 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 timelinewith the XCPlayground framework.

Let's go back to the slides now.

Now, I'd like to talk to youabout how you can use asynchronous codein 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 functionalitywhich the XCPlayground framework provides is the abilityto extend execution.

By default, execution terminates once all top-level codehas executed.

XCPlayground, though, provides APIfor extending execution indefinitely.

That's this XCPSetExecutionShouldContinueIndefinitely function.

You should know that this is actually not quite indefinite.

The execution time is controlled by the timeline's timeoutwhich defaults to 30 seconds.

Additionally, execution will be terminatedif you edit the Playground while it's running.

This is so that we can show you up to date results ratherthan let, leaving you a stale results while we waitfor 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 continuedafter we reached the end of top-level code.

That's because XCPShowView implicitlycalls XCPSetExecutionShouldContinueIndefinitely.

You should just think about this as if nothingin the Playground source has told Xcodethat the Playground used to stay alive,then the Playground will stop executing once we reach the endof top-level code.

So now, I'd like to show you a quick demo of what it'slike to use asynchronous code in Playgrounds.

So here I am back here and I have a Playgroundwhich uses asynchronous code.

We create, uh, we have our session delegatewhich 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 contentsof the Apple home page.

We then tell the data task to resume.

And you noticed that, you know,the Playground itself has executedbut we're not receiving any results up here.

And if I open up the assistant editor, you'll noticethat we haven't received any console output even though theywere clearly logging here that we've received some bytes.

And this is because nothingin the Playground has told the Playgroundthat it should continue executing.

So we call task.

resume, we resume the task and then as soonas that finishes, we hit the end of top-level codeand the Playground just stops executing.

Let's go ahead and say import XCPlayground.

And then we can say XCPSetExecutionShouldContinue, XCPSetExecutionShouldContinueIndefinitely.

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 resultsfrom here and we're also seeing the console outputthat we expect in the timeline.

So OK, that's how you use asynchronous codein Playgrounds.

Let's go back to slides now.

There are a few alternatives but we really thinkthat you should typically use XCPSetExecutionShouldContinueIndefinitely when you're tryingto use asynchronous code in Playgrounds.

If that won't work for you though,you can use other methods for waitingfor asynchronous operations to finish.

Basically, you just need to make sure you don't reach the endof top-level code before your operation completes.

Before we leave today, I'd like to talk to you a little bitabout 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 resultsin the Playground will gener