See how you can incrementally add Swift into your existing Objective-C codebase and app development workflow. Learn how to leverage Swift's powerful language features to develop robust applications that are faster to write and easier to maintain.
WOODY LIDSTONE: Hi, everyone.
I made a comment to Stefan earlier today, saying,
I hope some people come out to this.
And it's incredible.
You are just packing the place.
So, thank you for coming out.
My name is Woody, and I would like to introduce you
to Improving Your Existing Apps with Swift.
Can I get a show of hands,
how many of you are actually using Swift
in your code right now?
Then you are all at the right session,
whether you've done it or not.
Hopefully by the end of it you will all be using Swift
with your existing Objective-C projects.
You know, last year I was also in this room, I was sitting
in the back corner as an attendee, using my laptop,
trying to figure out how to use some of the technologies
that I learned about in an earlier session,
replying to work email even though I told them I wouldn't,
and half paying attention to the presenter that was up here,
as I am sure many of us are right now.
Well, since then, I've switched sides
from the attendee to the stage.
I have moved sides of the continent from Halifax,
Nova Scotia, to California, and I am out today
to help you learn some techniques to work
with Swift and Objective-C.
I don't have to go over and move it.
I've got a remote control now.
So what I want to do is take you through some
of the techniques you can use to add Swift to an existing project
to make that project better.
And I thought the approach I would use would be
to do exactly that in this session.
So I went to Infinite Loop, I went down to the parking garage,
and down to a floor below that where we have our catacombs,
and I went past the three-headed dog that guards the entrance
to industrial design, to the end
where we keep our software vault.
And I opened the software vault and I took
out an app called The Elements that we haven't seen at WWDC
for maybe two or three years.
I'd like to show you how it is right now.
Alright, this is The Elements.
Do you remember seeing this before?
Yeah? Some of you do, some of you don't.
Somebody really like it.
I like it too.
So it's a standard UIKit-based table view app.
We have got a bunch of cells for each
of the elements in the atomic table.
We have this small, little detail view
with a little bit of information.
And if you tap on one of the cells,
we have this navigation controllers push presentation
to show some details about that.
Great. I figure it's something
that probably a lot of you have to do.
You move around between different applications,
and you come back and you revisit an app
that you haven't used in a while or you haven't programmed
in a while and you are asked to add new features to it
or support a new operating system, a new SDK.
So that's exactly what we are going to do.
We are going to modernize this Objective-C app
and we're going to do it using Swift.
The pitch to you is this: if you have an existing application
and you have got to write new code for it
and that existing application is an Objective-C app,
consider taking advantage of Swift's features by writing
that new code in Swift, while, at the same time,
leave your original Objective-C code in Objective-C.
That's perfectly fine too.
In this session, we are going to start by doing a makeover
on the application to bring its user interface
to a more contemporary appearance.
We are going to do that using Swift.
Then we are also going to take a look at, for example,
Swift's structs and its functions like mapping
and reducing to find ways
that we can add new features to the application.
This application has small tiles and large tiles.
The small tile is the table view,
the large tile is the detail view.
And the tiles consist of a background,
plus the text that's rendered on top of that background.
Because this app is an older app,
the backgrounds were originally rendered in Photoshop,
and then they are just embedded inside the application.
But these backgrounds which exist
in different colors depending on the atomic states, solid,
liquid, synthetics, gaseous, are only rendered
for the original iPhone.
There is no Retina artwork included.
Which means when we take this older app and we run it
on newer hardware, we have to scale up, and when we scale
up this older, this older artwork,
we end up getting these artifacts, called aliasing,
on the rounded corners because we don't have enough pixel data
to represent those corners smoothly.
So that's something that we definitely are going to fix
up in this presentation.
The other thing is, do you ever look
at your middle school yearbook,
maybe in the '80s or '90s [applause]?
You see a picture of yourself,
and you are there wearing a vest with, like,
this embroidered kitten on it, and you are holding a keyboard
because it was cool at the time,
and you've got this laser background
because that was also cool.
And now you are looking at it
and you are just thinking, what was I thinking?
Sometimes we look back at our apps and we think,
what were we thinking?
With the shine and the gloss and the reflection.
So we are going to fix that.
And one of the ways that we can do
that with this app is simply removing the gloss
on the background.
We get a very contemporary, rendered rectangle outline.
It looks good in the small tile as well
as in the large tile for this app.
Now, we could rerender the new backgrounds in Photoshop,
and embed them inside the application,
but clearly this is an app that we don't,
we don't get into very often.
You know, it might not be until WWDC 2020 before we come back
to The Elements, and I'd like to make sure
that it looks good not just on past hardware
and current hardware, but also on potential future hardware.
So I am going to choose to put in some custom drawing code just
to draw the rounded rectangle background
because it's just a rounded rectangle.
I am going to do that in Swift, but I am going
to call it from Objective-C.
To do that, the technique I am going to use is called Mix
and Match, and we have numerous sessions both last year
and this year on interoperability between Swift
and Objective-C, the mechanics
of which can be covered better in those sessions.
What I would like to do at this point is just give you an
overview of how the technology works
and then we'll actually dive into a demo and you can see it.
Typically when we think about classes in Objective-C,
we have a header file and an implementation file,
and those two things together form our class definition.
But it's possible that we can have some
of our methods implemented in a category,
and that's perfectly fine,
and then our class definition is our base class plus
And there's nothing to say
that you can't have multiple categories.
In fact, this is something that we do with UI table view.
If you look at this header file in Objective-C, you will see
that there's many categories on UI table view.
Now, there's also nothing to say that one
of those categories couldn't be implemented in Swift,
in which case the terminology changes
but the concept is the same.
We just call it a Swift extension on the Objective-C,
in this case, base class.
And there's also nothing
to say you couldn't have multiple Objective-C categories
mixed in with multiple Swift extensions and the content
of all of them forms your class.
This lets us have some of our functions written
in Objective-C, and it lets you have newer functions be written
For this interoperability technique to work, we use a set
of bridging headers -- not a set of bridging headers --
we use a bridging header and a generated header.
Now, the bridging header is made in Xcode.
The first time that you introduce Swift
into an existing Objective-C project.
And then you maintain it.
You just basically go into it, and put some import statements
so you can selectively choose which data types
and header files
from Objective-C you are going to expose to Swift.
Then on the reciprocal,
the Swift compiler makes a generated header
which you can import into your Objective-C implementation files
to expose Swift, in this case, extensions
and other data types, to Objective-C.
So we have these two header files.
You are going to see them in the demonstration,
which is coming up right now.
Okay. So in my project,
I have this class called atomic element tile view.
That's the one that actually draws the background.
There is a method in it.
It's actually not just drawing the background,
it's drawing the background and all the text that goes on top
of it for both the small tile and the large tile.
So I am going to introduce the new drawing code, but I am going
to do it in Swift, so I will go ahead and make a new Swift file.
It's command-N in Xcode.
We will choose a Swift file, create it,
and because it's the first time that I've added Swift
to this project, I have the option
to create the bridging header now.
I want to create it, so press Return.
And now I have my two files that consist of the base class
in Objective-C plus the Swift file.
I also have the bridging header down here.
Let's just make this a little bit wider.
There we go.
You might notice that I chose to use the exact same file name
for my Swift file as I did for the Objective-C.
That's not a requirement, but it's a convenience
because it means that in Xcode, I can use the shortcut
of control-command-up arrow and just cycle through the Swift
and the Objective-C header and implementation,
just quickly move back and forth between all three.
Now, the bridging header is where I choose
to expose data types that I've declared in Objective-C
to Swift, and I do that by importing their header files.
Since I want to extend atomic element tile view into Swift
or using Swift, I have to import it into the bridging header.
The only one that I really need at the moment is the one
that I've highlighted, atomic element tile view,
but later on in the presentation I will need the other ones,
so I am just going to go ahead and get them all imported now.
Now we can go over to the Swift file,
and I will write an extension on atomic element tile view.
So now the class atomic element tile view has this new function
called draw raw background.
And you can see I am also using the new Xcode 7 markup
to give a document comment, a documentation comment,
in this case, draw an atomic elements background tile.
I will go ahead and put the code
in that actually does the drawing.
And that's it for the Swift part.
But now I want to call this Swift function from Objective-C
so that instead of having the pre-rendered images being
loaded, I am going to draw using this method.
So I'll switch over to atomic element tile view.m,
and I want to make sure that it sees the code that I just added
in Swift, so I will go ahead and import the generated header.
Generated header uses the same name as the product,
so the elements, then you append hyphen Swift.h. And now,
in this method, where I typically loaded the
pre-rendered backgrounds, I'll comment that out.
And instead call 'self draw,' and you can see that the method
from Swift is showing up as a native method
with everything else that's there.
You can even see the comment is showing
up 'draw an atomic elements background tile.'
So I will pass over the element.
Pass it to bounding rectangle
in which it will draw the rounded rectangle.
Run the app.
There we go.
So we are having some rounded rectangles being drawn using
Swift code with Objective-C [applause].
It's the benefit of planting your friends in the audience.
Now for the most part, it looks kind of like I expected.
It's a rounded rectangle.
But the rounded rectangles themselves,
they don't look the way I intended.
In fact, if we zoom in on it, you can see that it's rounded
on the inside but it's not rounded on the outside,
and that wasn't the intent.
I wanted pure rounded, pure roundedness
on both the inside and the outside.
So let's explore in more detail why that's happening
as we take a look at Swift structures.
And how Swift makes it easier
and more natural to work with structs.
So we have a lot of primitive structs, for example,
in the Core Graphics framework.
We have things like CGrects, CGpoints, CGsize, and so forth.
And what we did when we drew is I have a bounding rectangle,
which is a CGrect, and I drew this bezier path.
Now, the bezier path is the grey outline
on the screen, drew the bezier path.
Next it was put inside of the bounding rectangle,
and you can see the bounding rectangle here.
Bezier paths themselves are not something that you see.
They don't render until you apply a line to them,
like a line stroke, and then that's what you see,
that's what's rendered against the bezier path.
So we draw the bezier path.
We then put a stroke on it.
The stroke is, for example, ten units wide, ten points wide,
but it's going outside the boundaries
of the bounding rectangle.
And that results in clipping.
So the rounded rectangle is actually there on the outside,
but this clipping that's happening
with the bounding rectangle is preventing it from being there.
I know some of you in the audience might think, well,
if you have an issue with clipping,
just turn clipping off, and then that issue is fixed
and you go on to the next thing.
Which is, I suppose, true.
It's kind of like solving issues with Swift, though,
in Xcode by just shuffling around Swift's exclamation marks
until it compiles [laughter].
You can do it, but I would never call that a best practice.
And when it comes to clipping,
there's a performance issue with this.
With every API that you call, with every task
that you initiate, with every move that you make
and every breath that you take - [laughter] --
you need to consider the impact on power and performance.
And it's not very performant
to be constantly calculating the intersection of two rectangles
and performing clipping on it.
It's more performant just to set the rectangle
to be the right size in the first place.
That's what we are going to do.
We are just going to inset the bezier path
so that it doesn't clip itself.
Now, to do that, we are going to use some methods --
and I do mean methods, available on CGrect,
when it's being used in Swift.
Think about how these primitive types are used normally.
We have things like CGrect and CGpoint, and so forth,
as I said, and they might exist over here.
And then separately you have got the set
of global utility functions that work on them, like CGrectZero,
CGrectMake, or GetWidth, or some actual functions
like get the union or the intersection.
There's this cognitive separation between the two.
We know that this is the type, and then we have to know
that these are the methods -- or sorry --
the functions that act upon it.
Well, when we work in Swift, we actually change how things
like CGrect and CGpoint and CGsize come into Swift.
We basically use encapsulation and take all those,
those global, formerly global functions that can act
on that structure and build it into the structure,
which makes it much easier to have code completion,
makes it more awesome to predict what the API is,
because you can just do my struct dot
and then you get code completion for all the methods
and properties that it has.
But if we left the names like this,
it wouldn't really feel native.
So the names are actually remapped to have a feel
to make them first-class methods on these data types.
The benefit of this is the way that you work with structures
in Swift, calling functions or calling methods really
or accessing their properties, exactly the same way
that you work with classes.
It's exactly the same way that you work with enums, or enums.
It's all the same consistent style.
We also get to use initializers that are the same
across all the different data types.
We get to have better code completion.
So all in all, working with these types is much more natural
in Swift because they behave
as first-class data types with methods.
Okay. The other thing that we are going to do
in the following demonstration is, I don't know about you,
but when I work with graphics code,
especially some Core Graphics stuff, one of the approaches
that I would use is, I would render the code,
and then I would run it, and then it builds and it copies
into the simulator, then I navigate to that part
in the simulator where the code is actually activated,
where it's used.
Then I inspect it, and if I don't like it, I go back
and I tweak the code and I run the whole thing.
This is a -- this loop,
this round-trip can be really expensive time-wise.
Just to see what it looks like when you change a line width
from three to four or you turn off rasterization
or you do some sort of setting change as you try
to get things to work.
So there's a better approach
that doesn't have this round-tripping,
and it doesn't have you often commenting out portions
of your code just to experiment with how it looks.
If you really want to experiment,
and play around with some code, and see how it, how it works,
that's what we have playgrounds for.
With playgrounds, this loop gets switched
to just something like this.
You just tweak the code, and you see the change right away,
and if you don't like it, just change it right away.
There's none of that copying to the simulator, navigate
and see what it looks like.
So we are going to fix up the problem
with our rounded rectangles, using a playground
and using the methods that are part of CGrect
to get a better CGrect out of it.
Let me show you.
The drawing code is over in atomic element tile view
And this is the function that I just copied
in the previous demonstration.
It's the one I want to play with, so I am just going
to copy it into a playground.
So I've copied it, I'll hit command-N
and make a new iOS playground.
Paste it in.
And now I have the drawing function.
No developer is an island.
No drawing functions live in isolation either.
Drawing functions have to draw in the context of --
well, a drawing context or graphics context.
And the easiest way to get a graphics context is just
to make a subclass of UIView.
So that's exactly what I am going to do.
I am just going to declare a subclass of UIView here.
All it does is call that drawing function,
and then I'll instantiate that class here.
And then I can take the image that's drawn as a result
of my drawing function and just add it directly
to the storyboard here.
Make it larger so we can see it.
And then you can experiment with it.
You can kind of figure out what you need to do
to make it draw the way you want it to draw.
So, for example, I want to see if it looks
like if it has only 120 points across.
There's the result right away.
Maybe I want to see what it looks
like if the line width isn't 6 but is actually 60,
with a corner radius of 356.
That's what we get.
So you can keep experimenting with it.
And then once you have the code working the way that you like,
you just copy and paste it back
into the actual file from which it came.
So in this case, I want to have my line width scale so that
if it's the small tile view in the table view,
it's got thin edges, and if it's the larger one,
it has proportionately thicker edges.
So I am going to make it related to the width
of the background rectangle.
So background rectangle.width divided by, in this case, 36.
And I will do the same thing for the corner radius.
by something smaller, like 16.
So now it's starting to look like I want it to look,
but I still have the problem where I am clipping,
so I am not able to see the full extent
of the stroke nor the rounded rectangles.
So, to do that, on background rectangle,
I will use the method called rect by insetting,
and I will inset it to be half the line width.
So that's line width divided by 2 and same thing,
line width divided by 2.
And there, now I have a perfectly rounded rectangle
exactly like I expected to have in the first place.
I will copy this code from here back to the extension,
replacing the file -- sorry --
replacing the method that's there.
Rerun the app with command-R.
And that's exactly what I wanted to have, rounded rectangles.
Yeah, pretty much at WWDC, if ever you feel
like applauding, just applaud.
Nobody is going to say stop that.
It's all good [applause].
See, thank you.
So the app is looking okay.
I've got these rounded rectangles.
That's great, that's what I want.
But the next thing I want
to do is make this app feel more like a current app.
Now, I don't know about you, but have you ever gone
to your client after especially WWDC and said, hey,
there's this new version of iOS coming out,
for example, iOS 9 is coming out.
I think we should just not support iOS 8 anymore,
and we are only going to support the new upcoming operating
Yeah. Have you done that [applause]?
Yeah, and then you are looking for another client [laughter].
Because they all want you to support these old versions,
iOS 7, 8, and now 9 is probably going to be on slate
for this fall for many of you.
So to do that, we have this new availability feature introduced
in Swift 2.0.
So as long as you are writing some code in Swift 2.0,
we have a great way to check to see what SDK you are on
and if you can actually use this feature or not.
Now, last year at WWDC,
we introduced some new view controller presentation APIs
that allow for popover presentations on iPhone.
So what I want to do in my elements app is when I am
on any device that supports it -- for example, an iOS 8 device
or newer -- I want to use a popover presentation.
But when I am on iOS 7,
I want to continue using the navigation push
So how do we do this?
Well, this is the classic way of checking to see
if you support an API.
We do whatever the type is, we check and see
if it responds to selector.
And if so, then we just use the selector.
If not, then we do something else.
This is the way that we do it in Swift, as of Swift 2.0.
We have this hashtag available, and you specify the SDK
that you want, so iOS 8.3 in this case, and then if so,
we use a popover, and if not, we use the other approach.
And the benefit of this style is that you are not waiting
to runtime to see if it actually works.
At compilation time, the compiler can tell you, yes,
this will work, or it won't work depending
on your deployment target.
So if I am deploying to iOS 7, it's able to tell me,
popover isn't available.
But because I've properly guarded it
by giving it another path, it's able to compile.
In this case, if I hadn't put that guard in, if I hadn't said,
here's the check and I tried to compile this and it was trying
to deploy back to iOS 7, it would say,
popover presentation controller is not available.
It's only available on 8 or newer.
And then it gives you some fixes.
But instead of just showing you some more slides,
let me actually show it to you in code.
Alright. So first of all,
the code that presents the second view controller is kept
over in elementsviewcontroller.m. It's
just an implementation of table view accessory but in tapped
for row with index path.
And because I want to use availability checking,
I have to have this implemented in Swift, not Objective-C.
So I am just going to comment it out.
And then I am going to create a class extension much
like the original demo from 20 minutes or so ago,
so that I can extend elements view controller and have some
of its functionality implemented in Swift.
So I will hit command-N to make a new file, it's a Swift file.
It's elements view controller dot Swift.
Then I will write a class extension on it here.
Extension, elements view controller,
and inside of there I will just take the equivalent
So this is essentially the same code
that I already had there in Swift.
There's nothing new at this point.
It's just the same thing now implemented in Swift,
but this lets me bring up the availability checking.
This particular application is targeting iOS 7.1,
and I want to use this new popover presentation controller
technique in it, so I am going to comment out this line and put
in code that tries to directly call the popover presentation.
So I am getting some errors.
One of the errors it's complaining about is
that I don't actually conform to the delegate protocol
that I need to for popovers.
Well, just on the aside, it's okay to take an extension
in Swift and use it to add conformance
to additional protocols.
So I'll just add UI popover presentation controller
That clears up that error, but I still have the problem
about trying to use an API that doesn't exist on iOS 7.1,
which is exactly what I wanted --
well, in the demonstration anyway.
So I have a couple of ways to fix it.
I have it pre-baked for you here.
To say if I am running on -- in this case, iOS 8.3 --
go ahead and display as a popover.
Otherwise, use navigation controller.
Now, if I run it and I tap on the i -- let's see here.
We get a popover.
It's been 15 years and we are still getting Carbon
at WWDC [applause].
For more information about availability checking,
please check out Thursday's session called Swift
There's a whole big talk about it.
Next up, the previous demonstrations were
about improving and modernizing the look of the application.
You know, we changed the drawing to get rid of the gloss.
We now have a popover and so forth.
But let's actually add some functionality to it.
So we are going to implement live searching.
And to do that, we are going to take a look
at Swift's filter method, which is now available
on all collections, including sets and arrays.
Filtering can be used to drive a live search function
where only atomic elements
that match the search string are displayed in the table view.
A standard setup for this would be, well, something like this.
We've got a TableView.
The TableView is paired with a view controller
that acts as its data source.
That view controller has an array of content.
And when I type something into the search field,
I have a delegate method that's called,
on the view controller called searchbar:textDidChange.
I figure out the string that's been passed.
It's just an argument.
I filter the array of content.
And then I tell the TableView to update
with this now filtered array of content.
Search bar:textDidChange looks something like this.
In actuality, it looks exactly like this
because that's the code that I am using.
Now I want to draw your attention
to the highlighted section, which is a closure.
So I am running a filter, and in the filter,
it's going to be applied to every one of the items
in the array, and that item in the array, I have a placeholder,
which the dollar sign zero, I am getting its name,
and then I'm asking if it has the prefix,
and whatever the search string is.
It kind of works like this.
Here I have my original array up at the top.
And I have a closure for filter.
And it just cycles through,
passing in the element each time, and if it has the name
that begins with the letter, in this case N,
it's passed through to the returning filtered array.
And if not, it's not.
Let me show you this in code.
But just to speed things along, I've already gone
and put a search bar up at the top.
But I haven't rigged it up yet,
so if I try to do anything inside of it,
it just doesn't work because I haven't put the delegate method
The delegate method is this.
We are saying, if the search text is empty,
show all the atomic elements.
If it's not empty, I want to do a filter,
and that part is left to be done.
Let's do it right now.
So I am going to bring up a filter.
And if it's the first time that you've seen closures,
great, welcome to closures.
Let me show you a little bit about it.
And if not, maybe it's a bit of a review.
When Xcode shows you these blue kind of tokenized backgrounds
that are all singular items, you can double-click them,
and they expand out, and you just fill in the blanks.
So I'll take this closure, double-click it, it expands out.
And I know that I have an array of atomic elements.
The data type is called atomic element.
So the parameter that's being passed in is one atomic element.
So I am just going to specify that in this closure,
the parameters that are being passed
in is one atomic element -- I am going to give it a local name,
so atomic element is its local name,
and its data type is atomic element.
Inside the closure, I need to check to see if I want
to include it in the filtered results or not
because I promised to give a return value that's a Boolean.
So I'll say my return value is whether the atomic element,
name, has prefix, and then the search text that's passed
in from the search bar.
Now, when I run it, we'll do a search for everything
that begins with letter N.
There we go.
We get it filtered using Swift's filter.
But there's two things I want to show you.
One, there's really two different ways
to take a look at closures.
There's this expanded syntax.
There's also a condensed syntax.
Let me show you the condensed syntax.
Swift has a very strong type inference system.
We can infer a lot of things based on context and the kind
of data types that you are using.
So for example, if you have a single line in a closure,
it's assumed that it's going to return a value, so I don't have
to put the return in there.
And in fact, has prefix gives a return type of Boolean
so Swift can infer that the return type
for this closure is Boolean, so I don't really need
to have this here, which means I don't have to have
that there either, and since atomic elements is an array
of atomic elements, I don't have to specify
that an atomic element is being passed in,
so I can get rid of that.
And since I don't have any parameters, I don't have
to separate the parameters from the code, so I don't need the
in keyword, which means I can get rid of that and just tidy
up the spacing a bit, and I end
up getting something that looks like this.
And because the last argument to the filter method is a closure
in itself, we can make it into a trailing closure
and just get rid of the parentheses,
so we get that looking more like this.
Now the only trouble is
that there's no symbol declared called atomic element
because I removed it.
But I'm passing in one item into this filter closure every time,
and I can reference that argument like that.
That's exactly the same code.
If you were missing Perl, well, now we have this.
So now we can do a check.
Let's just put in a letter N, and great.
Now I have the elements, but they are not actually sorting
in the right direction.
Actually, they are not sorting at all.
So, let's just quickly go ahead and add a sort.
I am just going to chain it to the end
of this existing closure.
Dot sort. Now, in this case,
I could double-click this blue token, have it expand out,
and there's many ways we can compare strings, like case
and sensitive compare, localized compare, so forth and so on.
But because I know that in a sort I am given one atomic
element, and then I'm given the other atomic element,
and I only have to specify which one comes before the other,
or if the first one comes before the other, I can just write
out a closure myself, first of all recognizing that I am going
to have two atomic elements passed in.
So I have the first one, I am going to check its name,
and I have the second one.
I am going to check its name.
That in itself is not a comparison.
However, in Swift, we've overloaded many
of the standard operators, like greater than and less than,
so they actually work on types that you might not expect them
to work on, like strings.
That's a string comparison.
I'll run it again.
Search on letter N, and now it's being properly sorted.
It's filtered and sorted all in just one line.
I can check again.
Let's search on S.
We have some really important elements,
like Swiftonium [laughter].
Okay. Let's come back.
So in this section, we implemented filtering
of our table view by using Swift's filter method.
And then we sorted it using sort and got
to see an overloaded operator,
that being the less than/greater than.
The next feature and final feature that I want to add
to this app is simply one that lets me select multiple rows
and then it adds them up to give me the sum of the atomic weights
for the selected elements.
It looks kinds of like this.
We start off with the table view.
The nav bar at the top is saying select two or more items.
You select two or more items, and then the nav bar
at the top specifies the sum of their weights.
To do this, I start off with my content array.
That's all the atomic elements that I have,
those are all the ones that are displayed in the table view.
But what I want is just the selected atomic elements.
So to get that, I can't go to the table view
and ask the table view for the array of selected items.
I can only ask it for the index paths for selected items.
So the table view will give me an array of the index paths
for the selected items.
I can query those index paths to get the row.
I can correlate that with the backing array, the content.
And from that, produce the selected elements.
Basically, it's this.
We make a new array.
We loop through the index paths.
And then we go back to content and we pull
out the corresponding atomic element
for the current index paths' row.
If you've been accustomed to writing code like this,
you can do the same thing in Swift with this.
It's the map function.
The important part is still there, it's the part in orange.
Just all the the extra infrastructure that's
around it has been removed.
Next, once I have an array of all the selected items,
I want to add up their atomic weights.
So to do that, I might traditionally use a foreign loop
where I first declare a variable that's set to zero,
then I just iterate through the selected objects and just add
to that, in this case, D, their weight.
If you are accustomed to doing this kind of thing
with a for-in loop, you can do the same thing in Swift,
with a reduce, where we set the initial value as zero,
and then we just patch in a closure
that takes the initial value, that's zero, and then appends
to it the next item being passed in, adds them all up.
Let me just show you the code, though I will give you a preview
that we can do the whole thing
with just a single line of code like this.
One of the graphic designers was asking me
when he saw the presentation,
can you make that fit on one line?
It's like, not really, no,
I don't think you could see it then.
Let's switch over to the demo computer.
Alright. So here's the function that does all the work.
I start off by ensuring that I have more
than two items selected.
So you can see I am using a where clause on an if to say
that as long as the selected items count as greater or equal
to two, continue executing this code.
Then I use map so I can actually get the objects
that are selected by the table view, not the index paths.
And then use reduce to add it all up.
And then in the end just passed it through a number formatter
and stick it up in the title.
If you wanted to see the same thing on a single line,
it would look like that.
When I run the program, it adds them all
up and puts them up top.
That's showing map and reduce to make it easier to work
with items that back a table view.
Alright. In summary, I'm hoping you will see that there's a lot
of advantages to incorporating Swift,
even with your existing Objective-C projects.
It's not hard to do, and there's a lot of benefits to it.
You don't have to throw away any existing code,
and you get to use these modern and powerful techniques,
like reducing and maps and these powerful structs, so forth.
For more information, come see us in the labs,
check out our documentation, check out the Developer Forums,
or send Stefan an email.
He loves to get mail.
You can just tell him the conference is going well,
that would be fine.
And with that, I'd like to thank you,
and have a great conference.
Looking for something specific? Enter a topic above and jump straight to the good stuff.
An error occurred when submitting your query. Please check your Internet connection and try again.