Hi. Welcome toSwift Playgrounds. I'm Rick Ballard and withme 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 todaywith some conceptual background, what Playgrounds actually areand what you can use them for.
And then we'll show you examplesof how to use Playgrounds for learning, exploration,and visualization of the results of your code.
We'll show you how you canuse your own custom resources with your Playgrounds,and how to use Playgrounds for algorithm developmentand development of other separablepieces of code.
We'll introduce theXCPlayground framework which includes somereally powerful utilities that you can use toenhance your Playgrounds.
And we'll show you how you candevelop your own Custom Quick Looks, so that you can visualizeyour own classes the same way you visualize the classesthat come with the frameworks.
Next, we'll showyou a great demo of how awesome Playgrounds arefor developing custom views and in any other kindof custom drawing and we'll show you how you canuse your own asynchronous code with Playgrounds.
Finally, we'll finish uptoday with a little bit about the limitations thatPlaygrounds have today.
So what exactly are Playgrounds? Playgrounds are a new type ofdocument introduced in Xcode6 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 Playgroundcan contain a timeline full of timeline items that provide useful visualization of your results beyond what you see in the sidebar.
When you first opena Playground, we show the Playground Editorwith your Swift code on the left and the results sidebar onthe right showing the result of every expressionin your code.
Every time you edit your source,we rerun your Playground source from the top to the bottomand present the new results from that run in the sidebar.
This is the basic editor mode.
But if you go into the assistanteditor mode we'll show the Timeline Assistant bydefault which allows you to visualize yourresults in more detail.
For example, you candisplay the value history from a line in your code.
In this case, sinceit's a numeric value, we'll draw a graph ofthat value over time since it was iteratedmultiple times in a loop.
If you're looking for consoleoutput like that from Print Man, you'll also find that inthe Timeline Assistant.
There are a coupleother useful things you, I want to call out here.
In the lower right handcorner, there's a time-stepper.
And this controls how long yourPlayground will continue to run after the top of asource is finished if you're using live viewsor indefinite execution.
And I'll explain what both ofthose are a little later on.
There's also a slider whichallows you to go back in time and view results in thetimeline from a specific point in your Playground execution.
So here, you can see we'reviewing a numeric result from partway through thePlayground execution.
But you'll find this isvery useful with live views as it allows you to scrubback through the recording of that view and see exactlywhat your animation was doing at a specific point in time.
So that's what Playgrounds are.
Let's talk a little bit aboutwhat you can use them for.
We think your first great use of Playgrounds isgoing to be learning.
We've introduced a brand newlanguage for you to learn and we think the best way toget started is just to open up a Playground anddive in and play around.
Our documentation also includesa special interactive Playground called the Swift Tour.
This allows you tosee documentation and Playground Editor sideby side in the same editor.
So you can read about howto do something and try it out right there withoutleaving the editor.
Finally, we think Playgroundsare a fantastic way for people to learn how to programin the first place.
Beginners don't have to learnhow to configure a project and target and buildand run and debug.
They can just type codeinto a Playground Editor and immediately see the results.
So if you know anyone whowants to learn how to program, we encourage you to suggesttrying it in a Playground.
We think Playgroundsare also going to be in indispensabletool in your toolbox for everyday code development.
If you're developingan algorithm or any other separablechunk of code, you should considerstarting it on a Playground, working on it there untilyou have it how you want it, and then dragging thatcode into your project for use in your application.
Any sort of drawing codeyou want to do is also great in a Playground because youcan immediately see the visual result of what yourcode is doing.
And every time youchange your code, you can immediately see howthat affects the visual result.
Finally, processing code likevalue transformers or a sequence of image filters aregreat in Playgrounds because you can visualizethe result at every step of the transformation process.
And when you changesomething, you can see how that change ripplesthrough all your results.
We think you'll find that Playgrounds are fertileground for experimentation.
And in particular,any time you're trying to learn some newAPI, you should try it out on a Playground because youcan immediately see how it works and what results it gives you.
You don't need a project, youdon't need to build and run.
You just open up even astandalone Playground document, type in your code,and see what happens.
I'm sure all of youhave many a time gone to create a new project fromthe application template, and gone to findapplicationDidFinishLaunching, just to put a line ofcode and to try some API.
Oh, and then you probablyhave to NSLog it too so you can see what happened.
You don't have todo that anymore.
Now you can just openup a Playground and try out the API you want to try.
In fact, we'd recommend youconsider keeping a Playground in your doc at alltimes for quick access.
So anytime you want to try something it's rightthere at your fingertips.
So with all that said, let'sdive in and take a look in an actual Playground.
To do that, I'm going to invitemy colleague Connor up on stage.
>> Thank you, Rick.
Hello everyone.
My name is Connor.
I'm an Engineer onthe Xcode Team.
And today I'll be talking toyou about how you can work with Playgrounds as wellas some of the things which we think Playgroundswill be really great for.
Now, Rick has alreadycovered many of the basic conceptsbehind Playgrounds.
And so I think really the bestway to show you how to work with Playgroundsis actually just by jumping straight into a demo.
So, let's go ahead and do that.
So here I am at the demomachine and I'm just going to go ahead and launch Xcode.
Now you'll notice herethat on the Welcome window for Xcode we've added thisbrand new "Get started with a Playground" button.
It's that way we want tomake it really easy for you to just get started with one.
So I'll just click on that.
We'll create a Playgroundand 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 wehave here our Playground itself.
So, you notice thatwe're importing Cocoa, so we have full accessto the Cocoa APIs.
And then we are alsocreating a string and we're assigningthe value, "Hello, Playground" to that string.
You'll notice that in the resultsidebar we're seeing the result of that.
So in this case we're seeingthe string, "Hello, Playground".
So OK. So that's kindof the basic idea.
Let's try somethingwith numbers.
So let's say, for i in 0 to10, let's just say, i times i.
You see there thatwe execute the code and we're getting anindicator in the result sidebar that we've executedthat code 10 times.
So, OK, let's trybumping that up to 100.
We'll let it runand we'll see there that we immediatelyget an indication that this code hasexecuted 100 times.
Now, knowing that isvery useful information but sometimes you actuallywant to see the value there.
And we have supportfor that as well.
So OK, I'll just hover overthis result, and you'll see that we're highlightingthe line of code with which it is associated.
And we're also showingthis button here.
That's called theValue History button.
And if I go aheadand click on it, we'll open up the assistanteditor into the timeline mode.
This is the place where you cansee results over time as well as a place for you tostore results which you like to see persistently.
So in this case, we're showingthe graph for i times i.
And we've seen this, you know,this nice little curve here.
So OK, so that's kind of thebasics of using the timeline and calculating numbers.
Let's try something alittle bit more interesting.
Let's go ahead and dosomething with AppKit.
So let's first startup by creating a color.
So you let color equalsNSColor. blueColor.
You'll see there thatwe're now showing in the result sidebar a colorswatch indicating what the color is as well as indicatorsof all of the components which make up that color.
So I can, you know,take this color and let's create anotherattributed string using it.
So let's say, let attrStrequals NSAttributedString.
And we'll pass it in the stringin an attributes dictionary.
So we'll use thestring we already have and we'll create a dictionary.
So we'll sayNSForegroundColorAttributeName and we'll pass itthe 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 somethingfairly big, so I'll just put in 42, see what that looks like.
So, OK. So here, you notice that we're getting aresult for this as well.
You're seeing that we're showingthe plain text representation of this, as well asan icon indicating that it is an attributed string.
Now, that's great.
You know, we know thatthis code is executed.
But I really want to see whatthe actual value is there.
See how the attributedstring looks itself and we support that as well.
So I can just hover overthe result and in addition to the Value History button, you'll see that we havea Quick Look button.
And so if I go ahead and clickon that we'll show a Quick Look of that value to show youthe full representation of it as it was created inthe Playground source.
So, OK, that's colorsand strings.
Let's try something with images.
Let's actually start up by creating anarray of image names.
So I'll say, letimageNames equals, we'll put in an array thereand, I know it's something to do with like NSImageNameUseror accounts or something in that line.
So I'm just going to createan array with imageNames that I think it couldbe, the ImageNameUser, NameUserAccounts,NSImageNameUserGroup.
It's OK. We run thecode and you notice that we now have anarray of strings.
We actually want tosee an array of images and that's very easy to do.
I can just say something like, let images equalsimageNames. map.
I'll pass it a trailing closureto just say, NSImage named, pass it the positionalargument $0.
And you'll notice there thatwe're now seeing that this line of code executed 4 times.
And so, basicallywe can see that, you know, OK, that makes sense.
We're executing thisline of code 3 times for the trailing closure itself.
Then we're executing it oncefor the assignment to images.
Actually, I only want tosee the images array itself and we have a nice little trickfor doing that in a Playground.
You just go ahead and putthe 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'reseeing the images array.
I can Quick Look that andI can see, "Oh, you know, here's the image thatI'm looking for. " And so, I'll just getthat image and say, let image equals images at 0.
We'll rerun it.
I'll Quick Look to make sureit's OK and in fact, yeah, that's the one thatI'm looking for.
Let's go ahead and putthis into an image view.
So I'll say, letimageView equal NSImageView.
We'll pass our self aframe, so let's say NSRect.
We'll say 0 for the origin because we don'treally care about that.
Then we'll also say 512by 512 for the size.
Now I'm going to go aheadand put this ImageView on its own line as well.
So I can show thisresult in the timeline.
And this is a neat littleway of building something up.
You take the, you startcreating the object and then you put another linewhere we show it as a result.
Anyway, I can add somecode in between there to see how it buildsup over time.
So you see here thatwe're starting out with just this emptyimageView, you know, we're not seeing anyinteresting there.
So let's go ahead add ourimage to the imageView.
So let's say, imageView. imageequals image.
And we'll re-execute andwe'll see here now that we're in fact showing the image there but it's not fillingthe full imageView.
It's not doing what we expect.
That's because we haven't set upthe image scaling appropriately.
So we'll set that as well.
Say imageScaling equalsImageScaleProportionally UpOrDown. And we'llre-execute and now you'll see that we're seeing the imageat full size in the imageView.
We're seeing what we expect.
And it's OK.
That's how you can workwith system resources.
But I'm sure you have manyresources of your own that you'd like to use in Playgroundsas well.
And we support that too.
So I'm just going togo ahead and I'm going to show the final inspector.
It will slide in on theright hand of my Playground.
And you'll noticehere that we're, we have this new sectioncalled Playground Settings which is shown whenever you'reviewing a Playground document.
You can select the platform against which thePlayground should execute.
And, you know, OS X iswhat we're doing right now.
But we also support iOS.
And you can select apath for resources.
This defaults to nonebut you can select one if you have resourcesthat you're interested in.
In this case, I'm just going tosay I have a folder of resources on my desktop so I'mjust going to say, let's use the AbsolutePath option.
I can then go aheadand choose that.
So let's say here's my resourcesfolder, I'll choose that.
And then once I made that choiceI'm actually going to go ahead and hide the Utilities area.
And to access the imagesthemselves, I just use, you know, NSBundle API, youknow, the resources show up as resources forthe main bundle.
So I can say something like "letmyImage equals NSImage, named".
I have an image inhere that's just called "Xcode" so let's grab that.
We'll re-executeand you'll notice that now we're gettingthe image result here.
And click, click to confirmthat it's what I think it is.
And in fact, it is, we'reseeing the Xcode icon there.
And now I'm just going to have that imageView showthe Xcode icon instead.
So, I'll say, "imageView. imageequals myImage".
We'll re-execute and nowyou're seeing this new result, let's add it to thetimeline as well.
So you can see here thatwe have what we expected.
The Xcode icon is showingup in our imageView.
You'll probably also notice that we're still seeingthe older version here with the user iconin the imageView.
And that's because Playgroundsactually capture results on every single lineof execution.
So you can do thesekinds 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 theuser icon to there.
And so, we see thatearlier version that we saw where it's small in the center.
Then I set the imagescaling appropriately and it's now fillingfull image view.
Finally, I updated it touse myImage and we're seeing that it's showingthe Xcode icon.
And that's great, so that youdon't have, you know, go back and see what happenedat a particular point.
We're capturing the data foryou as your Playground executes.
So I think that about coversthe basics, so let's go back to slides and talk a littlebit more about Playgrounds.
So one of the key ideasthat you saw there is that Playgrounds willautomatically execute.
You just type in some codeand you'll see the results in a sidebar on the right.
Additionally, you saw thatwe can add a value history to the timeline.
So here we have a line ofcode which executed 100 times.
And if I hover over that result, you'll see this ValueHistory button.
If I click it, we'll switchinto the assistant editor and we'll show that asa history of that value.
Additionally, many values inthe Playground have Quick Looks.
All right.
So in this case we havean attributed string.
We don't see the fullrepresentation of the sidebar, just kind of theplain text of it.
But if I click on theQuick Look button, we'll see the attributedstring as it was created in the Playground source.
We support many different types for Quick Looks inthe Playground.
We support colors, strings --both plain text and attributed.
We can show images, views, in this case we'll capturea snapshot of the view at that point in time.
We can show arraysand dictionaries as we'll show a structuredversion of the array or dictionary, ah,like you might see in the variablesview on the debugger.
We can show points,rects, and sizes.
We'll kind of create a graphicalrepresentation of those.
We can show Bézier paths, soboth NSBezierPath on the Mac and UIBezierPath on iOS.
We can show URLs, for this we'lltake the plain text of the URL and show it in the sidebar.
But if you Quick Look, itwill show you a web view with the contents of that URL.
And finally, for types if we don't have a nativeQuick Look representation, we can usually get astructured view of it, again, like you would see in thevariables view in the debugger.
So here I have anobject of a class that I created inthe Playground.
And it is, it has acouple of properties, a foo property anda bar property.
And you're seeing thevalues of those at that line of code when it executed.
In this demo, I also showedyou how you can use your own resources with Playgrounds.
And this is actuallyfairly easy.
So you just go ahead andshow the file inspector.
You select a locationfor Playground resources.
And for this we havethree options.
We've got an Absolute Pathoption which basically says, "OK, I've got this folderof resources somewhere on my computer andI'd like to show it and use it with the Playground. " We have a Relative toPlayground path option.
And this is really great if you're checking yourPlayground into SCM.
Because you can say, "Oh, youknow, here's this Playground and here's this folder ofresources that's next to it, I can set this up and then whenyou use other people to check out your repository, then itwill automatically be able to use the Playgroundwith its resources. " Finally, we support anInside Playground option.
And this is greatif you're sharing in ways other than via SCM.
Because you can just say, "Iwant to store my resources in my Playground" and you canemail that out to other people and see, when they openit, they'll be able to see those resourcesimmediately.
Once you have madethe selection, to access these resourcesin your Playground source, you just use things like, NSBundle. pathForResourceofType and NSImage named.
The resources just showup as the resources for the main bundle duringPlayground execution.
So, now that we have thebasics out of the way, I think I'd like to starttalking to you about some of the use cases forwhich Playgrounds would be really great.
And the first of theseis Experimentation.
I'm sure that all of youout there have a folder on your computer whichlooks something like this.
It's just a bunch ofXcode projects created from the template that are,you know, maybe 1 or 2 changes to see how something worksor to test out an idea.
It's actually isn'tthat easy of a process.
You know, you have todo many different -- you have to first choose theright project template then find the right file in that projectto edit which may be easy or maybe not depending onwhich template you chose.
You'd have to do what you'retrying to do in the first place, and that's write some code.
Once you've writtensomething, you then have to build your project.
You then run whatever you built.
And for iOS that mayinvolve deploying to a simulator or to a device.
And if you didn't get it rightthe first time, you'd then have to redo this, stop inthe debugger and step through your code to figure outwhere things are going wrong.
We think Playgrounds canhandle this a whole lot better.
That's because there'sreally only 2 steps.
You would just, say, get started with a Playgroundand write your code.
Once you start writingyour code, we'll automatically execute itfor you and show you the results in the sidebar so you can seewhere things are going wrong.
So now, I think I'dlike to show you a demo of what this looks like.
So let's go back tothe demo machine.
So here I am.
I'm going to go ahead andjust launch Xcode again.
And this time I'm going tocreate 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 UITableViewCellstyle API works.
So, I'm just going to calland create this Playground and call it TestTableViewCell.
Save it to the desktop, and OK.
So, here we haveour iOS Playground.
It's, you know, importing UIKit,but otherwise, it's the same, we're just creating a stringand assigning it to a variable.
So, if I want to use aUITableViewCell style, I need a UITableViewCell.
And the best way to showthat is with a UITableView.
In order to get those cells into my UITableView,I need a data source.
So, let's just go ahead andimplement a data source.
So I'll say "class DataSource".
We'll inherit fromNSObject and we'll conform to the UITableViewDataSourceprotocol.
Notice now that we're gettingan issue here and that's because the DataSource we'vecreated does not actually conform toUITableViewDataSource.
And, you know, that's expected.
We haven't actuallyimplemented any methods yet.
So, I'm actually going tojump to the declaration of UITableViewDataSource bycommand-option-clicking on it.
We see that we then openthe assistant editor.
And instead of showingyou UITableView. h, we're going to show you aSwift version of that header.
So, in this case, we're seeing,you know, here's our protocol.
We're seeing that we need toimplement these two methods.
And so, OK, I'm just going totake this one, this first one to tell the TableView thenumber of rows per section.
I'm going to copyand paste it in here.
And then I'm just going to startthings out, return 1 from this.
So, OK. So that'sthe number of rows.
Let's also provide the cell.
And OK, let's just go aheadand create our UITableViewCell.
Let's say let cellequals UITableViewCell.
I need to fix this typo.
Here, we'll say the style, we'lljust say the default style.
And then for thereuseIdentifier, we aren't actually goingto be reusing these cells so we can just passnil for this parameter.
And OK, so therewe have our cell.
Let's go ahead and configure it.
So, I can say something likecell. textLabel. text equals Text.
OK. So that's the text label.
We'll see what that looks like.
UITableViewCell may alsohave a detail text label.
But that's not guaranteedto be the case.
So I'm going to explicitlyhandle the fact that it's an optional.
So, I can say something like "if let detailTextLabelequals cell. DetailTextLabel".
And so, if the code insideof this "if" executes, then we'll know that wehave a detailTextLabel.
So, I can say something like, detailTextLabel. textequals Detail Text, and we know that this is safe.
We're not going to accidentallytry to assign a property to nil.
So now that we've configuredour UITableViewCell, I can just go aheadand return that.
You can see now that weno longer have an issue in our Playground.
But we're also not gettingany results in the sidebar.
That's because we haven'tactually instantiated our data source.
So, I'll just say something likeDataSource equals DataSource and then I can, you know,I'll just create a TableView and tell it to useour DataSource.
So, let tableViewequals UITableView.
We'll pass it a frameso, CGRect.
Again, we don't careabout the origin.
I'll pass 320 for the width, and for the height we justneed enough to be able to show all the cellswe care about.
So, I'll just saysomething like 240.
Finally, we'll passa style of Plain.
We'll then tell the tableViewto use our DataSource.
And then, we will tell thetableView to reload data.
Let that Playground execute.
And once it's finishedexecuting, we'll be able to see the tableViewwe've created.
So, I'm going to just go aheadand add this to the timeline.
We can see here that we'vecreated our tableView, you know, we're seeing thecell that we want, with the text that we want.
So, OK. So that, you know,gets us up and running.
But actually I wantto see the styles for all the styles that we have.
So, I'm going to jumpback to the declaration of UITableViewCell style.
And you can see herethat there are 4 options.
So I'm going to change this1 to a 4, so if 4 rows.
Instead of alwayspassing the default style, I'm going to conditionalizeit based on the row that we're currently at.
So, I'll say let rowequals IndexPath. row.
And I'll say somethinglike let style equals UITableViewCellStyle. fromRaw.
I'll pass the row.
This fromRaw will convert theUITable, the raw row integer into a UITableViewCellstyle optional.
And we confirm that by usingquick help and we can say that, "Oh, yes in fact, thisstyle is an optional UITableViewCell style. " If we were to passthis directly here, we would get an erroras you can see here.
We need to explicitly handlethe fact that this could be nil.
You know, the UITableViewCellinitializer doesn't expect that.
So, let's go aheadand check that.
So we'll say, if we havea style, let's unwrap it, otherwise you justuse the default style.
It's OK. Now thatwe've handled that, let the Playgroundre-execute and let's jump back to the timeline usingthe jump bar.
And once it's re-executed,we'll notice here that we're now seeing all thedifferent UITableViewCell styles in our tableView.
And so now, I have a Playgroundwhich I can, you know, share with my co-workers orjust keep it as a reference for myself to see whateach UITableViewCell style looks like.
Let's go back to slides now.
So that showed you howgreat Playgrounds are for experimentation.
You just get startedwith an idea, write some code, andsee how it works.
And now I'd like to inviteRick back on stage to talk about another great ideawe have for Playgrounds and that's AlgorithmDevelopment.
Rick? >> Thanks, Connor.
Developing algorithms and anyother separable pieces of code in a Playground isa great way to go.
And so to show you that, I'mgoing to dive right into a demo.
So what we're going to do todayis implement insertion sort, a fairly straightforward sort.
We're going to create a brandnew Playground to do that.
So I'll just say getstarted with a Playground, and we'll call thePlayground InsertionSort and save it on the desktop.
If you're not familiarwith insertion sort, imagine that you have a hand ofcards and you want to put them in order with thelowest values in the left and the highest valueson the right.
One way you might do thatis, start with the second to leftmost card and compareits value to the leftmost card.
If it's less, you'dswap the position of the two cards in your hand.
You'd then look at the thirdto 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 goon doing this for every card in your hand until everycard had reached the correct, sorted position.
When you're done, yourhand will be in order.
So, let's implementthat in a Playground.
To start with, weneed some random data that we're going to sort.
So, I'm going to goahead and I'm going to declare an array of data.
I'm going to use varbecause this needs to be a mutable array, so Ican add to it and sort it.
And we'll just make an emptyarray of ints to start with.
And I could say fori in 0 through 20, because maybe I want20 data points.
I can say data. appendto add a new element.
And let's use thearc4random function to generate a random number.
That doesn't return aSwift Int, so we're going to cast it explicitlyto a Swift Int.
And we'll modulus it by 100 toget a number between 0 and 99.
So if I look at data here, you can see I have aresult here on the right.
Here's an array of what looklike pretty random numbers.
You'll also notice if I editthe Playground source again it reruns and I get a differentarray of random numbers.
Ah, OK, so that's great.
Well, it's nice to be ableto generate random data but I probably don'twant it to change on me every time I editthe Playground source because that might make ithard to develop my algorithm.
So, let's grab this randomdata and use it every time.
To do that, I'm going toclick over the result sidebar and use command-A to selectthis data, command-C to copy it, and then I'm just going to pastethis in here as array literal.
And now I can work off thesame random data every time.
OK. So, let's startimplementing our algorithm.
The first thing weneed is a function to swap two pointsof data in our array.
There actually is abuilt-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 makethis a generic because, well, we have an array of ints.
Our insertion sort shouldbe able to work on any type.
So, any type at least aslong as it's comparable.
One element can becompared as greater than or less than another.
So, we'll mostly work oncomparable types here, the exchange functioncan work on any type because we just areswapping types.
So this is an exchangeusing a type D.
And it's going to take anarray of T and two indexes which we're going toexchange in the array.
So, the simplest way to exchangethese objects is to assign one to a temporary variable,assign the second to the first, and assign the temporaryvariable to the second.
So, we can say lettemp equals data of i.
Data of i equals data of j.
And data of j equals temp.
OK. I think we'veimplemented this correctly but let's try it and find out.
I can say exchange,pass my data array and we'll say exchange the 0thelement with the second element.
And then we'll take a lookat our array when we're done.
So, before, element 0 was12, and element 2 was 15, now element 0 is 15and element 2 is 12.
So, it looks likeexchange works properly.
OK. The next thing we need isa function to, given an index, look at the datapoint of that index, compare it to the data pointto its left; if it's less, exchange them and keepcomparing and exchanging until it reaches the correctposition in the array.
So, let's call thisfunction swapLeft.
Again, it's a genericbut this time we need to actually do a comparison.
So, we're going to say our typeD is comparable and we're going to pass an array of T and anindex of the data point we want to start swapping left.
OK. So, let's implementthis, we're going to start with our index and goback to position 1, not 0 because there's nothingto the left of 0 to swap.
So, I'm going to sayfor i in, and, you know, I could do a rangefrom 1 to index but what I reallywant is index to 1.
So I'm going to reversethe range with reverse 1.
3 dots makes it afully closed range which means it will goall the way to index.
So, since I'm reversing this, itgoes from index and ends at 1.
And for each of these datapoints, I'm just going to say if data of i is lessthan data of i minus 1, exchange data i and i minus 1.
OK. If it's not lessthan data of i minus 1, it must have reached thecorrect sort of position in the array, sowe can stop there.
So, let's say else break.
OK. Let's try this function out.
I'm going to go ahead andsay swapLeft, pass data, and let's pass element1, 2, 3, 4, 5, 6.
Let's pass element 6 left.
Oops! And look at our data.
And you can see the 0has moved all the way from the 6th position tothe beginning of the array and everything's beenmoved to the right.
So it looks like thisfunction is working great too.
OK. The last thing we need isto actually implement the sort, so this should be pretty simple.
We'll call our function isort, works again on typeT that is comparable.
And we can just passan array of T and it will sortthe whole array.
To do this, I'm just going tosay for i in 1 (we're starting at 1 because there's nothingto the left of 0 to sort to) to data. count, swapLeft,data and i.
So, let's try itout, isort data.
And we'll look our dataarray when we're done.
And you can see it did a wholebunch of assignments up here.
And now here's ourfinal array and it looks like this is in sorted order.
So, we've correctlyimplemented insertion sort.
So, this is great for a simplealgorithm like insertion sort.
That wasn't too hard.
But you know if I was doingsomething more complicated, it might be nice tohave more visibility into exactly what'sgoing on here.
So, let's look at how wemight visualize our results in more detail.
Well to start out with, let'sdraw a graph of the results of the data at the beginning.
To do that, I'm just going tosay for x in data (to iterate through every data point)and just print out x.
And so, you'll see thereare 20 data points here.
So this line executed 20 times.
And if I click on theValue History button, I get a nice graph here showingmy data at the beginning and, boy, that does look random.
OK. So, now I wantto try to print out another graph everytime swapLeft is called, so I can see what'shappening to the graph over iterations of swapLeft.
And I could put this"for" statement in the end of swapLeft again andshow the Value History.
But again, in Value HistoryTimeline item for given, a line is going to show allthe data from that line.
So, each time swapLeftis called, its data would beappended 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 toneed a new tool in our toolbox.
I'm going to go back toslides and show you that.
With Playgrounds, we'reshipping a new framework called XCPlayground and it containssome very useful utilities for enhancing your Playgrounds.
Right now, we have API formanually capturing values to display in timeline items,showing your views live and extending executionfor asynchronous code.
Right now, we'regoing to use the API for manually capturing values.
That API is calledXCPCaptureValue.
It's a function that takes anidentifier, which is a string, and your value, whichis of any type.
When you pass it -- your value-- it will take that value and put it in a timelineitem for you.
So, the identifier that you passit identifies what timeline item you want that value to go to.
If you call this functionon different lines but pass the same identifier, the values from thosedifferent lines will go to the same timeline item.
Conversely, and what we wanthere, if you have one line that calls XCPCaptureValuebut it's called multiple times with different identifiers and it passes thosedifferent identifiers, that one line can generatemultiple different timeline items (or grabs, in our case).
That identifier is also shownas the name of the timeline item so you can easily seewhat data is what.
The value pass can beanything, because it's a generic but it helps if it's a typeof value that we know how to Quick Look appropriately.
So, let's go backand give this a shot.
So to start out with, Ineed to import XCPlayground to make this API availableand I'm going to go ahead and define a new function.
I'll call it visualizeand it's a generic.
And it will take an array oftype T and I'm going to use this "for" loop in it, soI'll just indent that and close the function.
But instead of justprinting out x, what we want to do is capture that value.
So, I'll call XCPCaptureValue.
I need an identifier, solet's add one to our function.
So, identifier is astring and we could pass that identifier,and our value is x.
OK. So let's try this functionout and visualize the data at the start of our sortand we'll label it Start as the identifier justso we know what's what.
And here you can see it ran andhere's our data at the start.
So that's a good start.
So now, we're going to goahead and visualize our data after every iterationof swapLeft.
So, I can call visualize,I'll pass data as it is after this iterationof swapLeft.
And for our identifier, let'slabel it after the iteration, the number of timesthat swapLeft is called, which is the index parameter.
And so, I'm goingto let this run now.
And you can see that it'sgenerated multiple graphs labeled after theiteration that we're on.
So, now we can justscroll through here and see what's happening to ourdata over time as swapLeft runs and the sort completes.
You can see it looks like ourdata is getting sorted piece by piece.
And so, at the end, wehave a nicely-sorted array.
So there, we can easilyvisualize exactly what's going on with our algorithm.
We think you'll findthis very, very useful.
OK. Let's move onto another example.
I've got a heap PlaygroundI made here earlier.
And it's got thisHeapGrapher class at the top which I'll explain in a moment.
But the meat of this classis my heap class which, if you're not familiar witha heap, a heap is a type of balanced binarytree where the value of every node isgreater than or equal to the value of its children.
Heaps are often used toimplement priority queues, because it's very efficient to remove the highestpriority item, that's the top of the tree, and it's alsoefficient to insert new items into the correct position ofthe tree for their priority.
We're implementing our heapwith an underlying array to represent the tree.
And in our array, the treenoted index i has children at indexes i times 2and i times 2 plus 1.
So you can see down here at the bottom we'vegot some random data that we seeded ourselves with.
And we've created a newheap with that data.
And we "heapified the heap,"which is to say, put that data into correctly heap-sortedorder.
On the right, inthe results sidebar, you can see our defaulttreatment of this custom class is toshow the name of the class and show its properties.
In this case, it hasone property which is that heap array and here itis before it's been heapified, when it's not a correct heap.
And here it is afterit's been heapified, when it's purportedlya correct heap.
But you know, it's reallyhard to tell looking at this array whetherthat's a correct heap.
This array representsa 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 ifI could just visualize this as a tree everywheremy heap is referenced to my Playground source? So let's see how to do that.
In order to visualizemy own custom class, we're going to implementCustom Quick Look Support for this class.
Our Custom Quick Look Supportallows you to add Quick Looks for subclasses ofNSObject only (right now).
And to do it, you implementthe debugQuickLookObject method which takes no parameters and returns any objectas an optional.
And you're going to returnthe value that you want to represent yourobject as its Quick Look.
So, right now, thatvalue (the values that we support here) arecolors, strings (both plain and attributed),images, and Bézier paths.
So, for your Custom Quick Looksyou can use any of these types.
So, let's try it out.
OK. So I mentioned before Ihad a little HeapGrapher class that I wrote.
That's a little class that knowshow to take an array and draw it as a tree, so we'regoing to use that.
We'll implement ourdebugQuickLookObject method.
It takes any, or returnsany object as an optional and we're just going to createone of our HeapGraphers.
And this HeapGrapher knowshow to generate an NSImage which is one of the Custom QuickLook types, supported types.
So, we're just going toreturn the image it generates with g. graphHeap andpass self. heaparray.
And now, when this runs, instead of showing the defaultrepresentation for our class, it shows our custom QuickLook representation, which is an image.
And so when I clickthe Quick Look button, you can see here it'sdrawing my heap as a tree.
This is before it's beenheapified when you can see, for example, 78 is less than 89.
So this is not a correct heap.
But if I Quick Look itafter it's been heapified, I can now go, oh great, 91is greater than 86 and 89, 86 is greater than 84 and79, and so on and so forth, and I can reallyeasily visually verify that this is a correct heap.
So that's how you can Quick Lookyour own classes in Playgrounds and we think you'llfind that very useful.
All right.
Next, we'd like to move on toshowing you how great it is to do Custom View Development and other drawingdevelopment in Playground.
And to do that, I'm goingto hand it over to Connor.
>> Thank you, Rick.
Another great use case wethink Playgrounds will be used for is Custom View Development.
And that's because you canjust start writing some code and see the actual viewas it's being drawn and as you're starting tobuild up your drawing code.
So for this I have a goal.
I want to take thisPlayground icon and add some animation to it.
The icon that wehave is really great.
It conveys the playfulnessof Playgrounds.
But unlike Playgroundsthemselves, it's static.
There's nothing dynamicabout it.
And so, I'm going to tryto add animation to this.
And what better wayto do it than when in a Playground itself? So, let's jump over to the demo.
So OK, here I'm going to goahead and open up a Playground that I've already started.
So, OK. So here we'vegot a Playground.
We've got our subclass of NSViewcalled PlaygroundIconView.
It has a few layers.
It's got these three instance,er, these three instance methods which actually do thesetup of those layers.
You see that they'reunimplemented right now and we'll come backto that in a moment.
I also have an extension ofNSColor which defines a couple of colors for thePlayground icon itself.
I then have a helper functionto convert an NSBezierPath to a CGPath for usewith CAShapeLayer.
Finally, I just go aheadand create an instance of my PlaygroundIconView.
And then, I put iton a separate line so I can add some stuff later.
Let's go ahead and showthat in the timeline.
So, OK. So you'll see now that we've just gotourselves an empty view here.
So yes, we have anempty view here.
We actually justnow need to go ahead and implement thesesetup functions.
So let's go ahead and do that.
So we'll start outby creating the path for the background layer.
So you can see here we'recreating NSBezierPath and we can Quick Look it tomake sure it looks right.
And in fact, yeah,that looks more or less like the Playground icon.
So let's tell, let'ssetup our layer.
So OK, now we'resetting up the layer.
You can see here in the timeline that we're now drawing thelayer where, you know. . .
We have the background, we'vegot the little border there, and so, OK, we've gotour background set up.
Let's also do the seesaw baseand we'll do the same thing.
We'll create a path for that.
And we'll let it executeand we'll see here, let's Quick Look, make sure. . .
Yeah, that looks more orless like the little base that we have for theplay- . . . for the seesaw.
So let's set up thelayer itself as well.
And there, we justmake that change and immediately get the feedbackof seeing what that looks like when drawn in our view.
Let's also do the seesaw layer.
I've got some code hereto set that up as well.
You see here that we're just,you know, have a closure which will create thechild layer itself.
We then create a coupleof layers for the children on each side of the seesaw, andthen we set up the bench itself and then add those layersto our seesaw layer.
So, OK. So now we'vegot ourselves something that looks kind of likethe Playground icon.
But like the icon itself,it's not animating.
So let's go ahead andadd support for animation to our PlaygroundIconView.
I have a snippetfor that as well.
And so, let's walkthrough what this is doing.
I define a constant for themaximum angle of the seesaw.
I've, you know, workedthrough this and I think pi over 12 is about right.
I also have a property for thecurrent angle of the seesaw after any pendinganimation is finished.
And then have a propertywhich determines whether or not it should be animating.
It starts out as falsebut we have this code here which executes wheneverthis is set to say, "Well, if the animation statehas changed and we're told to animate, then juststart animating depending on the current angleof the seesaw. " I then have this helper method for actually performingthe animation itself.
So we just, you know, go aheadand create a CABasicAnimation, set a couple of values,set our timing function to match what a seesawwould actually look like.
Set the duration to whatwas passed in which defaults to 1-1/2 seconds, but canbe customized depending on the angle of the seesaw.
We then add the animationto our seesaw layer.
We set the underlying transformproperty of that seesaw layer, so that once the animationcompletes it looks correct.
And then we update ourcurrent seesaw angle property accordingly.
Finally, we have, uh, weimplement the "animationDidStop, finished" delegate callback.
Or basically saythat if we finished and we're still supposedto still be animating, then just go ahead andanimate to the opposite angle of what we currently are at.
So, OK. Let's go ahead and tellthis view to start animating.
So we'll do that and you'llnotice that after it reruns, we seeing the view updateit's look, you know, so we see that ittilted over to the side.
We're not seeing theanimation itself.
And for that, we'regoing to need some help from the XCPlayground framework.
So, let's switch back the slides to see what thatcould look like.
So the second pieceof functionality which the XCPlayground frameworkprovides is the ability to show live viewsin the timeline.
And you do that by callingthis XCPShowView function.
It takes an identifier and theview that you want to show.
After calling it, we'll show theview live while the Playground executes and thenwe'll record frames as the Playground executes so you can play them backonce execution finishes.
The identifier you pass to thisfunction must be unique inside of the Playground.
That's because thisis how we refer to the live viewinternally in Xcode.
And it is also whatwe'd show as the title for the live viewin the timeline.
The view pass must alsonot have a superview.
This is because we will addit to our own view hierarchy and it would generally notproduce 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 goahead and just go ahead and import XCPlayground.
And then down here, insteadof just having this view item, I'm going to removethat from the timeline.
I'm going to saysomething like XCPShowView and pass an identifier.
It can be anything aslong as it's unique.
So I'll say PlaygroundIcon View.
And then I'll pass theview that we've created.
So, we'll just letthat re-execute.
And you see therethat in the timeline, we're showing the viewlive as it's animating.
You-all also probably noticedthis little timeout field down here.
And that lets us specifythe amount of time which we'll let thePlayground continue executing after we reach the end ofexecution of the top of a code.
Now, it defaults to 30 secondsbut I'm going to adjust this down since I know myanimation only takes about a second and a half.
So I'll do 10 seconds toget a few times around.
After we edit that,we'll rerun it.
And so that's great, youknow, we see it running there.
And I'd like to show how youcan integrate XCPShowView with the XCPCaptureValueAPI we mentioned earlier.
And so, what I'm going to do,I'm going to capture the angle of the seesaw, orof the left edge of the seesaw aswe're animating.
So here, I'm just goingto say XCPCaptureValue.
I'll pass Left SeesawPosition and I'll just pass because we know atthis point that it's, you know, it's flat on there.
Then you can take this andI'm going to put it in our "animationDidStop,finished" callback.
Now I'm going to just pass thenegative currentSeesawAngle.
That's just because that'swhat we need to do in order to get the left positionof the seesaw.
That is how the angle worksout for the transform.
So you see here thatas we're executing, we're getting the graph kindof building up over time.
And then once executionfinishes, the graph will snapback into place and kind of show you the best view ofthe data that it collected.
It's OK. You probablyalso noticed this slider became active.
And so, I can just goahead and take that and drag it through here.
And you'll notice that we'reupdating the graph at the bottom but we're also showing youthe animation, you know, as it went through in time.
So this is, you know, afairly basic animation and it's doing what weexpected but, you know, if you had somethingmore complex and you want to just kind of take a lookat just a small portion of your animation, youcould do that as well.
And I can also dosomething like, you know, click on one of these points.
So I can click there.
We can see it, you know, thatthe two things are in sync.
I click there.
It updates the point.
I can use the arrow keys togo through the graph's points and see that, OK,yeah, you know, we're doing whatwe expect it to do.
And so, that's how you canshow 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 canuse asynchronous code in your Playgrounds.
You got a little taste ofthis in the demo before.
But I'd like to go into alittle bit more detail now.
The third piece of functionality which the XCPlayground frameworkprovides is the ability to extend execution.
By default, execution terminatesonce all top-level code has executed.
XCPlayground, though,provides API for extending executionindefinitely.
That's thisXCPSetExecutionShould ContinueIndefinitely function.
You should know that this isactually not quite indefinite.
The execution time is controlledby the timeline's timeout which defaults to 30 seconds.
Additionally, executionwill be terminated if you edit the Playgroundwhile it's running.
This is so that we can showyou up to date results rather than let, leaving you astale results while we wait for an earlier executionto finish.
Additionally, as you sawon the last demo, you know, we didn't actuallycall this function, but we saw that executioncontinued after we reached theend of top-level code.
That's because XCPShowViewimplicitly calls XCPSetExecutionShould ContinueIndefinitely.
You should just thinkabout this as if nothing in the Playgroundsource has told Xcode that the Playgroundused to stay alive, then the Playground will stopexecuting once we reach the end of top-level code.
So now, I'd like to show youa quick demo of what it's like to use asynchronouscode in Playgrounds.
So here I am back hereand I have a Playground which uses asynchronous code.
We create, uh, we haveour session delegate which is anNSURLSessionDelegate.
It has a few callbacks.
And then we also just, you know, create an instanceof our delegate.
We created an NSURLSession.
And then create a data taskto download the contents of the Apple home page.
We then tell thedata task to resume.
And you noticed that, you know, the Playground itselfhas executed but we're not receivingany results up here.
And if I open up theassistant editor, you'll notice that we haven't received anyconsole output even though they were clearly logging here thatwe've received some bytes.
And this is because nothing in the Playground hastold the Playground that it should continueexecuting.
So we call task. resume, weresume the task and then as soon as that finishes, we hitthe end of top-level code and the Playgroundjust stops executing.
Let's go ahead and sayimport XCPlayground.
And then we can sayXCPSetExecution ShouldContinue,XCPSetExecutionShould ContinueIndefinitely.
This takes a Bool butthat defaults to true, so you typically don't needto pass anything there.
And I won't do that here.
You'll now notice that, youknow, we were receiving results from here and we're alsoseeing the console output that we expect in the timeline.
So OK, that's how youuse asynchronous code in Playgrounds.
Let's go back to slides now.
There are a few alternativesbut we really think that you should typicallyuse XCPSetExecutionShould ContinueIndefinitelywhen you're trying to use asynchronouscode in Playgrounds.
If that won't workfor you though, you can use othermethods for waiting for asynchronousoperations to finish.
Basically, you just need to makesure you don't reach the end of top-level code beforeyour operation completes.
Before we leave today, I'd liketo talk to you a little bit about some of the limitationswe have with Playgrounds.
First off, you shouldnot use performance, uh, Playgrounds for anyperformance testing.
That's because thelogging of results in the Playground willgenerally dominate the runtime, not your actual code.
This means that the performancewill be dependent on the number of lines of code executed,not the actual performance of whatever it isyou are developing.
And that's not necessarilywhat you'd expect.
Instead we'd suggest thatyou use the XCTest framework to create performancetests in a test bundle where you can getmore accurate results.
We have a session later thisweek called Testing in Xcode which will go intothis in more detail.
There are few morelimitations with Playgrounds.
Playgrounds cannotbe used for things which require user interaction.
So we have great supportfor showing live views but you can only see them,you can't touch them.
We also do not support usingPlaygrounds for anything which require customentitlements.
For iOS Playgrounds, weonly support executing against the simulator.
So anything which requires adevice will not be supported with Playgrounds.
And finally, we do notsupport using your own app or framework code in aPlayground unless it's something that you can just copy and pasteinto the Playground source.
Basically, you can only usethings in the standard library, in the SDK, or that's in thePlayground source itself.
You can get around some of theselimitations by using the REPL.
The REPL is the commandline interface to Swift and it works this way becausethe REPL can actually execute in your own process.
You just stop at a breakpoint,and then at the LLDB prompt, you execute the REPL commandand you'll just be dropped down right into the Swift REPL.
Playgrounds though provide aricher experience than the REPL.
And that's because we willautomatically execute your code from a known state.
That means, you know, you make asingle edit to a line and then, you know, we justrerun it from 0.
Whereas with the REPL, ifyou wanted to make an edit to something earlier in thesource that you had entered, you have to, you know,get the process back into the state then, youknow, reenter the REPL, retype everythingmaking that one change to see how it affects things.
Playgrounds also supports someof these higher level futures like Quick Looks and a timelinewhich we do not support, uh, which the REPL does not support.
If you'd like to learnmore about the REPL, you can go to the Introductionto LLDB and the Swift REPL talk.
And we'll go into much moredetail about how the REPL works.
In summary, we think Playgroundsare a great way to play with Swift, with Cocoaand with Cocoa Touch.
We think you can use themfor things like learning, exploration and visualizationand frankly probably tons of things which we haven'teven thought of yet.
The XCPlaygroundframework provides APIs for using your Playgroundsfor more advanced things.
So you can do things likemanually capture values with the XCPCaptureValue API.
You can show live views in thetimeline by calling XCPShowView.
And then you canalso extend execution for asynchronous operationswith the XCPSetExecutionShould ContinueIndefinitely function.
Finally, we'd really like tojust encourage you to go out and give Playgrounds a try.
I think, you know,they're really approachable and if you just sitdown with them for a little bit you'llfind a number of great ways to integrate them intoyour development process.
For more information, you cancontact our Developer Tools Evangelist, Dave DeLong.
We also have someinformation about Playgrounds in the Source EditorHelp for Xcode 6.
You can also askquestions about Playgrounds on the Apple Developer Forums.
We have several relatedsessions about Swift this week.
So there was an Introductionto Swift session yesterday, which you can catchon the video.
We also have an IntermediateSwift session later this afternoon.
There's also an AdvancedSwift session tomorrow which you'll be able to see.
We had an Integrating Swift with Objective-C sessionearlier this morning which you can catch on video.
And we also have aSwift Interoperability in Depth sessionlater this afternoon.
Finally, if you'd like to learnmore about the Swift REPL, you can go to theIntroduction to LLDB and the Swift REPL session.
Thank you all for coming and I hope you have agreat week here at WWDC.