WWDC2013 Session 407

Transcript

X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
[ Silence ]
>> My name is Troy
and I'm an engineer
on the debugger UI
team for Xcode.
And I'm glad to see so
many people here today
because we all know that
debugging is really important.
And you know that debugging
is what sets your app apart
from the app on the App
Store that gets one star
because it crashes on launch.
And debugging is what sets
your app apart from the app
on our iOS devices that use all
the memory and evict other apps
when our users are trying
to do some multitasking.
And debugging is what sets
your app apart from the apps
on our Mac and iOS portables
that use all of battery life
in just a few hours making it a
worst experience for everyone.
But you guys know that already.
You're here because
debugging is hard.
I like this quote from
Brian Kernighan and it says,
"Everybody knows that
debugging is twice as hard
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
as writing a program
in the first place.
So if you're as clever as you
can be when you're writing it
in the first place, how are
you ever going to debug it?"
Well, the answer is better
tools and specifically,
the new debugging
tools in Xcode 5.
We have a lot of new
things to cover today.
But first, let's go
on a tour of the UI
so we have a common
vocabulary when we know--
when we're talking
about these things.
So here is the brand
new, Xcode 5 UI.
And the first thing you're going
to notice is we've moved the
breakpoints activation button
from the toolbar down
into the debug bar
because it's right there next
to the other tools that you need
when you're debugging such as
Continue, Step Over, Step Into.
And it's just a much
more natural place
to disable all your breakpoints
if you need to do that
and then hit Continue.
If you need to enable or
disable breakpoints one by one,
of course, we go to the
breakpoints navigator.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And here you see a list of all
of the breakpoints separated
by filename and line number.
And you can edit or disable,
enable breakpoints right here.
But not all breakpoints have
filenames and file numbers.
There are some special
breakpoints.
And we create those down
at the bottom of the window
where you can create
symbolic breakpoints
or the exception breakpoints
that are more special
breakpoints.
And we got a two new
breakpoint types that are
like the exception breakpoints.
And that's the OpenGL
ES error breakpoint
and the unit test
failure breakpoint.
Both of these breakpoints
are kind
of like the exception
breakpoints
where you can set it once
and just kind of forget
about it in your project.
And then when you have an
error, Xcode is going to pause
in your applications
code instead
of some error handler later on.
So that's a really great way to
catch those errors in unit tests
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and in your OpenGL
ES games on iOS.
Let's move on to the-- there's
another navigator that's really
important of course and
that's the debug navigator.
And the first thing
you're going to notice
in the debug navigator is
this brand new debug gauges.
And we're going to talk
a lot about that later.
So let's skip it for now.
I do want to draw your
attention to this icon here.
This is the spool of
thread icon and this means
that your debug navigator
is in threads mode.
And so, down here, you
get a list of your threads
and a stack trace where
you're paused in the debugger.
And this is a really great
place 'cause you can navigate
through that stack trace and
jump through the files that led
up to where you are in your
paused application code.
And you can even check out
the parameters that went
into the calculations that
got you to this point.
And so, you can figure out
why you got to this point
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and why maybe you need
to go somewhere else.
But let's return back to
that spool of thread icon
because you can change that and
a lot of people don't know that.
If you're using grand central
dispatch, it's more natural
to organize your threads by cue.
And so, this is exactly
what this spool--
this grand central dispatch
stoplight icon indicates
that we're grouping
your threads by cue.
Now, let's move on to
the variables view.
The variables view is where when
you stopped at a breakpoint,
it will show you the
most important variables
for that line of code and
that might be local variables,
it might be instance variables
or parameters to the method
and Xcode does a
really great job
of choosing those
variables for you.
But in some situations,
you need to find
out a little bit
more information.
Maybe, you need to find out
a global variable state,
or you need to find out
some register states.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And so, you can click on this
toggle down here and change auto
to all and that will give
you a more expansive view
of your variables.
Let's move on to
the debug console.
The debug console is where
you receive the output
from your application whether
that's NSLogs, printfs,
or maybe the system frameworks
that you're using are showing
you some warnings or errors
that you need to be aware
of and they're going
to come out right here.
Of course, when you're paused
in the debugger, this is also
where you have a direct
conduit to the LLDB debugger
which is a state of the art
debugger that powers so many
of the features in Xcode,
and we're going to talk more
about that and how
it's integrated
with Xcode more a little later.
And so, that's basically
the main aspects
of the debugging in Xcode.
And of course, we've added new
things which we're going to talk
about today including
the new debugging gauges
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
which we saw briefly.
We're going to see a new way to
debug, a new debugging workflow.
And then we're going to look at
a specific debugging workflow
which is really great
now with XPC services.
So let's talk about performance.
We all know that performance
is extremely important.
Nobody likes to see stutters
in their application.
Nobody wants to see scrolling
stuff for any reason.
But you've ever hung on
the Apple developer forums,
you may have heard,
"Don't pre-optimize."
And you may even get this quote
from Donald Knuth that says,
"Essentially, pre-optimization
is the root of all evil."
I think we can agree
that there's a little
bit of hyperbole here.
But we can also agree
that if you think
about performance before you
think about code correctness,
you end up with code
that's harder to read,
code that's harder to
maintain, and ultimately,
code that may not even be
correct in the first place.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So if performance is
such an important aspect
of your application, but we
don't want to pre-optimize
when are we supposed to
optimize our programs?
We should optimize when
we measure a problem.
This is the only time that
we know what's going wrong
so we can fix that instead
of what we think
might be going wrong.
And Instruments is
the best place to go
and optimize your code.
There are sessions this week and
there's videos from prior years
to tell you how to
use Instruments.
But the good news is now in
Xcode 5, Xcode is measuring
for you all of the time, and
that's the new debug gauges.
Debug gauges show up
in the debug navigator,
right there where you
can always see them.
And this is really
great a place for them
because when you just
pause, it switches to that.
It's right there, you just need
to peak behind your current
application or if you're
on a device, it's right
there on your Mac.
There's a bunch of
debugging gauges
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
to show you the performance
and the characteristics
of all sorts of technologies.
There are two debugging gauges
that are universal no matter
what kind of app you're writing,
what platform you're
targeting, and that's the CPU
and the memory debugging gauges.
And so, since those
are universal,
we're going to take a look
at them more closely today.
So first step, the CPU gauge.
We show you a chart
of the recent history
of a CPU utilization which
is your first indication
that something may be going
wrong in your application.
If you see a spike
that you didn't expect,
or if you see a pegged on a
processor and you don't know
that that's happening,
you want to take a look
at that, take a deeper look.
And to do that, you click on
the CPU gauge and it brings
up the beautiful CPU
debugging report.
Some of the characteristics
of these reports
that are common among all of the
reports, so let's take a look
through some of the aspects.
First we have this view here
which is the meter view.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
The meter view shows you a
snapshot of what's happening
in your code right now in your
application to give you an idea
of what's going on right now.
As you can see here,
we're using 97 percent
of the CPU utilization.
And that puts the
needle about halfway
because this iOS device has
a two core processor and so,
it's out of a total
of 200 percent.
We don't know whether that's
50 percent of each core
and we don't know if that's
100 percent of 1 core,
and zero percent of the other.
But we know that approximately,
half the CPU utilization is
going to our application.
I also want to draw
your attention
to the small inner blue
arc because that's a range
of the last few minutes
of CPU utilization.
So you know whether things
have been wildly swinging back
and forth or if it's just
been pegged at a narrow range
such as it is here between
about 60 and 100 percent.
The next area is the utilization
across the whole system
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
because all know that our
applications do not run
in isolation.
Other applications affect
how our application runs.
And so here, you can see
in purple that we are using
about half of the total
CPU utilization potential.
The orange area is all
the other applications
which on iOS is very
well-behaved.
So it's a tiny little
15 percent slither.
And then of course, the
free area is the gray area.
And as we've been stressing all
week, if you have work to do,
you really do want to
use all the CPU can
and then let it go to sleep.
Let the computer-- the machinery
underneath your application go
to rest for better
performance and power.
Now, we have the main
section of the report.
This is where we have some
graph showing you with history,
basically, the history
of that needle up above.
And the first one
is a large graph
because that's showing
an aggregate
across all your threads at
the CPU utilization over time.
Below that, we split
it out by the threads.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And here, we only
have two threads.
But these-- as your threads
come and go, we will add
or remove graphs down here.
In this case, we can
see that thread 1,
the main thread is getting a
lot of activity and whatever
that second thread is
basically doing nothing.
So this might be
a good opportunity
to profile our application
and see if we can move any
of that off the main thread.
And of course, as I said,
the best place to do
that is in Instruments.
So the most important part
of this report is the Profile
and Instruments button.
And this will launch
Instruments,
open up the time profiler
template, and gets you started
down the path to
fixing this problem.
Let's move on to
the memory report.
The memory gauge sets in
the debugging navigator just
like the CPU gauge and it shows
you a chart of what's going
on giving you a first indication
that something maybe going wrong
or maybe, an indication that
everything is just fine.
If we click on this gauge,
we get the memory report.
And like the CPU report,
it has similar sections
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and the first section
is the meter view.
The meter view in this case is
showing 153 megabytes being used
which is about a third of this
iOS' devices total memory.
It also has that inner blue
arc which shows you the range
and since I've been measuring
quickly after the start
of this application, the range
goes from zero to where we are,
153, because hardly,
any time is elapsed.
If we go over to the total
system utilization area,
we can again see in this
pie charts that we're using
about a third of the
total system's memory.
And that the other applications
on the system are not using
very much but you can imagine
that other applications might
be affecting our application.
We might be getting
memory warnings
because of our app
or other apps.
And finally, we have
the main gauge area.
And this is where you
can see at a glance
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
that something might be going
wrong with this application
because we seemed to be doing
a repeatable set of steps
and memory usage is just
monotonously climbing up,
and up, and up.
And so, this would be a
great opportunity to profile
in Instruments or
as my colleague,
Han Ming [phonetic] is going
to show in a real life example,
how we can solve these problems
by looking at these reports.
[ Applause ]
>> Thank you Troy.
So I'd like to show you
how to make use of the CPU
and memory gauges to detect
performance issues even while
you're actively developing
your application.
So let's get to it.
[ Pause ]
So the app I'm using
is a Mac application.
But everything I say here
today applies completely
to your iOS apps.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So to set the stage, imagine
I have an award-winning
application on the
Mac App Store.
People love it because it does
one and one thing really well.
It shows you exactly
one picture.
Now because of this
unsurpassed simplicity,
it has been downloaded
many times
over the last couple of years.
But my users are
clamoring for more features.
So in the next release, I'm
adding two new features.
The ability to add
filters to the image
and the ability to do rotation.
Let's try them out.
[ Pause ]
So you can see, I
have four filters.
Let's try the rotation--
distortion, I'm sorry,
sepia tone.
I notice a little bit of a
lag, maybe a tenth of a second,
or a quarter of a second every
time I change the filter.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
I'm going to assume that Apple
has done an incredible job
of optimizing those
core image filters.
So my next idea is to
add a cache so that
if my user reselects
the same filter,
it would be lightning fast.
So I'm going to do that.
So this is where I create
a cache, scrolling down,
this is where after the cache,
I'm going to put a breakpoint
here so that when it breaks,
I can validate that I have
successfully added to the cache.
And this is where I make use
of it, I'm going to recompile
and run so I hit the
breakpoint, that C.
I'm going to make use of our
variable view, zooming in here.
And oops, so one key value pair.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So that's good.
So remove breakpoint
and continue.
Now, the debugger team would
like you to build up a habit
of whenever you add a new
feature, a new enhancement
to cleanse over to the debug
gauges, just to make sure
that now everything
is behaving OK.
So please keep your eyes
peeled in this particular case
to the CPU and the memory gauge
while I try out my new cache.
With distortion, CPU is
behaving pretty well.
Memory went up a little bit
because I just added
a new filtered image.
Sepia tone, same logic.
Now, let's try out our new cache
by reselecting back distortion.
Oops, memory went
up a little bit.
Now, just to reconfirm
what I saw, yup!
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So now, we don't want
you to get paranoid
over every single
bump on the chart.
But if you see a monotonous
growth pattern like this,
it should pick your interest.
And it does for me.
So I want to get
more detail about it.
So I can do that like Troy
said, I can select the gauge
on the navigator and it
will show me a report of it.
The top section is a
snapshot but what really jumps
out at me is the graph.
This pattern here.
So something is definitely
cuckoo here.
Now, I can select, I
can click on the profile
and instruments button to get
more detail but sometimes,
because this is your own
source code, you have reached
in for last couple of years.
And I just added some more new
lines so we can reflect on it
and see what you just did.
So let's look at that.
So here is where the cache is
created, nothing is wrong here.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Here is what I make use
of it, seems-- looks OK.
So this line right
here, now, those of you
with eagle eyes would
have noticed
that I've made the
classic rookie mistake
of confusing the
key and the value.
So, you know, obviously,
that's not going to work.
Even though when I've checked
it early on, it was in the,
you know, I added one key value.
So let's switch them,
switch the order.
[ Pause ]
I'm going to recompile and run.
And I'm going to
try them out again.
Distortion, sepia tone,
this is the important part.
Let's go back to distortion.
And you can see that
we are staying
at for about 39 megabytes.
Let's try it again.
So that the debug gauge,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
the memory gauge validates
what I think is happening,
the correctness of it.
I just want to expand a little
on what goes hand in hand
with the memory gauge.
Some of you may have had used
that usually involves
a repeatable pattern,
a repeatable user gesture.
You know, you do X and then
you do Y to make X go away.
Sometimes, you have
to do X again.
A concrete example would be on
the iOS, you put up a picture,
you flick it away,
then you flick it back.
On your Mac, you may open a, you
know, NSDocument-based document
and then close it
so you get the idea.
So I'm pretty happy
with the cache,
let's move on to the slider.
[ Pause ]
All right, let's try it out.
OK, it looks like it does
what it says and now rotating.
Again, I'm going to
glance over to my CPU
and memory gauge and try it out.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So memory seems pretty stable,
but there's something
interesting about the CPU.
You cannot see here but even
after I've released the button,
there seems to be
some activities,
CPU activity going on.
Again, I'm interested in it.
So let's select it.
The top section is the snapshot,
the middle section is
the utilization overtime
which is the accumulation
over the usage on the threats,
and the last section
at the bottom,
the threat activities
on each threat.
You can see that, well, I know
that when I did the rotation,
I'm using set bounce
rotation on NSView.
And what's surprising for me is
that I'm seeing activities
on many threats.
So I'm going to leave the
report right there and try
out my slider again to see if
I see anything interesting.
So I can see that a whole
slew of threats just came on.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Now this-- that's
weird too, you know,
I'm and I think I just wrote
the set Rotation method,
I'm going to go back
and take a look at it.
So here's where I noticed the
rotation changes or I cut it
down and I set a flag,
this method right here.
So when I wrote the method,
it was necessary for me
to call this method to get--
fill that image so
that I can rotate it.
This method that uses a dispatch
cue so that work is done
on a different threat; they'll
by explaining why we saw a lot
of activities on threats,
but we have a better way now,
we're keeping-- I'm
keeping instance variable
to filtered image.
So this method is not necessary,
now I must have missed it
in my refactoring early on.
So let's get rid
of it, recompile.
And I'm going to bring up the
report, scroll to the bottom,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
try the rotation again.
And this time you see that,
there are no new
threats coming in.
So I'm pretty happy
with that as well.
CPU like what Troy says
or what you have heard
over the last few days.
Now we want you to do use
as much CPU as possible
to get the work done in
the shortest possible time,
so that the rest of the
course can go to rest,
thereby saving you
battery power.
So do not be afraid to
make used of the CPU
to get real work done.
So that concludes about my
demo and I have this one thing,
I want you to take out from
here is that, whenever you--
a new feature, a new
enhancement and you're--
in the process of testing
it, please remember
to consult the performers,
the debug edges
to make sure you don't add
any performance regressions
to your application, thank you.
[ Applause ]
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
>> Thank you, Han Ming.
As you can see these debugging
reports give a great high level
overview on what's going
on in your application.
But as debuggers, we--
they can't always rely
on a high level overview.
Sometimes, we need to go down
deep, sometimes we need to look
at the specific state
of our application
in a specific instance variables
that make up our application.
And so for that, I'd like to
talk about the new data tips
and Quick Look features.
If you're gone programming
for a while,
you know that you're
getting into the cycle,
you write a little bit
a code, you hit run,
and you do some debugging,
and then you go back
and do some more coding.
And in Xcode, it's
going to look like this.
You have your big code editor
and you're writing code.
And when you hit a breakpoint
that debug area comes
up showing you useful
information.
But a lot of times, we get
all of the context we need
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
from our code and so it
would be great to be able
to see the whole method that
we're working on and just hide
that debug area for
when we really need it.
And so then, we'd have
a debugging experience
that looks more like this
and so that's exactly what
we have done in Xcode 5.
The first thing we did
was we improve data tips
and how do we improve them,
we strip away all the
extraneous information.
You already have the
variable name there,
I assumed you also know that
this is a size variable,
so you don't need the
type and the name.
All you care about is the width
and height of this size variable
and so that's what we show you.
But you'll notice we added two
more things to this data tip.
And the first one is the Info
button and if you press that,
you get the results as if you
typed in the LLDB console,
PO or print that object.
[applause] It's really
handy because right there
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
in your code, right
where you need it,
but we didn't stop there.
Variables, even simple ones
like size has visualization
about them that you would
like to see, maybe you want
to see the aspect ratio.
So you can click on this
Quick Look button and see
that size variable
right there in the code
in a visual representation.
[applause] And this
is super helpful.
So to show you a demo of
how this works in practice,
I'd like to invite
Christopher Friesen.
>> So our users loved the new
features, the Han Ming about it.
The filters are great, even my
mom is sending motion blurred
cap-- pictures already,
so, you we know,
that made a great success.
Now there's another
feature they want, you know,
rectangular boarders around
your pictures are, oh,
they're pretty normal,
but they're also kind
of not that exciting.
Our users want something
little more edgy.
So I've been working
on another feature
and let's take a look at that.
[ Pause ]
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So we'll run our
application here
and I've added the
Mask button down here.
So this is creating a mask
for the image which is--
what our users have asked for.
However, what they really wanted
is they want a star shape.
So I'm in the middle of
running this feature and I want
to use the data steps
in Quick Looks to figure
out what's gone wrong
with my implementation.
So I'll go back here and
I'll use the button down here
at the bottom of the Debug bar
to activate our breakpoints
and then we'll exercise
our application
to hit our breakpoint.
So here we are, we're
creating a Bezier path
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
that will become our mask
but we don't know exactly
what's wrong with the shape.
We can use our data
tips to hover over it.
We can click the Info button
to get a description of it.
Well that's all the
stroke information,
I can breakout some graph
paper and plotted out
or I can click Quick Look.
And here we get our
wonderful image Bezier path
that we're using
to mask or image.
That's not what we want.
Let's take a look
at our method here.
So our method is lazily
initializing the Bezier path.
So as you can see, since,
we already have a mask,
it's going to return
out of this function.
We can use our data tips
to actually edit the value.
I can double click
on my address here,
I can enter zero
to nil that out.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And now as we step over
this code, we won't return
out of the method
early and we'll go,
get into the code that's
going to setup the Bezier path
and we can start debugging that.
So I'll continue here
and now we're on the
for loop that's going to
go through and it's going
to construct the shape.
Let's click continue
about three times
and then we'll see how our
Bezier path is coming along.
We can hover over any
reference to mask in this method
and we'll see what
the current value is.
Again, we'll use Quick
Look and we can see
that it's starting
to draw the shape.
Now in order to draw
a star shape,
we need the drawing points
at alternating radiuses.
If you look at our radius,
we see that every other time
through the loop, it should
be using a different radius.
So let's look at R2.
We see that's 200, R1 is 100.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So they're both the same,
so that's why we're not getting
the shape that we wanted.
Again, I can use data tips,
double click on the value
and turn new value and now
that value has been changed
in our running program.
We'll continue several
more times
and then we'll check
on the drawing.
Click on Quick Look
and here we go.
So we're starting to get
our star shape, great.
We figured out where
the problem is.
And we'll go ahead and continue.
And here we are in
a drawRect method.
So it will-- we have
completed our Bezier shape,
our Bezier path and here
we see the complete shape,
and as we continue over
in our application,
we've got the distortion
filters been applied
as well as our mask.
So we're nearly there.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Now another thing you can
do with the data tips is
that you can go ahead
and inspect the values,
you can crawl in
to the variables,
and dive into them will say.
So let's set our
breakpoint again,
exercising our application,
and we can hover
over self for instance.
And here we see that self
doesn't have a nice concise
summary so we show you the
type as well as the address.
So over here on the left,
we can turn it open,
we start seeing the instance
variables and properties,
and we can see the same
for the super class.
Here's a frame, again, Quick
Looks are also available
as you drill down
into these variables.
Here's another URL.
We can do a peel of it.
Again, this is a textual
description of what it is,
not many people know, you
know, can picture the latitude
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and longitude of that, but we
can use our visual Quick Looks
to see exactly where
this is, we'll do that
and here we are, we can zoom-in.
[applause]
And it sure looks like
it's near where we are
and there might some
event happening
in the Yerba Buena Park.
So that's data tips for you.
They now provide concise
data for you as well
as these great visual data tips
and we hope this will hope
keep you in your source code
as you do your debugging,
thank you.
[ Applause ]
>> Thank you, Christopher.
Now that showed a couple of a
data types available and I'd
like to run through some more.
But let's talk a little
bit about how this works
because this is a developer
conference and I trust you guys
with the information about how
these things are put together
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
because it's really interesting.
LLDB powers, many of these
simple ones like NSIs
because it has data
formatters that returns
to us the within the height.
But we also support more
complex types like images,
we support UIImage in
iOS, NSImage on Mac OS.
But also CGImageRef and CIImage.
And CGImageRef as you well
know has a bunch of functions
that get information out of it.
So if we want to get a
CGImageRef off your iOS device,
in Xcode, we construct
the expressions,
and we send those using LLDB
to your running application
and we say, CGImageGetWidth,
we do the same with the height,
and the color space, and
even the bytes of the image
that get shipped over
the wire back to Xcode
where we can reconstruct
the image
and show you right inside Xcode.
And believe me that's much
easier than any debugging method
for seeing an in-progress image
that you may have had
to use in the past.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
We also support NSString and
we support NSAttributedString,
so you can see your fonts and
colors right inside Xcode,
instead of the plain text view
that might be in the console.
And it's really great for
long strings because it--
of course, it doesn't fit
there in the data tip.
So you can scroll
through the whole string
and see it large right
up in your screen.
We support NSPoint, we support
NSData, and this one is great
because data has bytes and we
format the bytes nicely, NSView.
But data also has, as we all
know, it often comes from files
of streams and that's
usually character data.
And so right next to the bytes,
we show what those
bytes would be
if they were ASCII characters.
And so you can see here
that this is probably a Plist
that's been loaded from disk.
We support Core Location and
if you know, Core Location,
it's basically a
pretty bare bones object
that has latitude, longitude.
And so recognizing what that
latitude and longitude is,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
is very difficult unless
you have the map right there
in Xcode.
So this is very powerful.
Similar to Core Location,
we have, we support colors.
And so, rather than
looking at that triplet
of RGB values plus alpha, we
show you the color right there.
We support Bezier paths,
both on iOS and Mac OS
as Christopher showed
in his demo.
And we support URLs.
And it's important to
realize that URLs have a path,
that's a string representation,
and we show you
that in the data tip, but we
also show you the contents
of that URL because that's
just as important to you
who is trying to understand
how your code is working.
So we'll render web
pages from the internet
and put those right there
in Xcode or we'll load files
from your local disk
and show those as well.
In this example, I'm
running a program
that has URL that's
referencing a keynote document.
In fact, it's this
keynote document
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and I can see it right inside
Xcode which is really powerful.
And so Quick Look is
a new powerful way
to debug your applications that
makes it a whole lot easier
and a whole lot more fun
to see what your
value-- the values are.
Visualizing data type is not the
only thing we need to visualize,
especially, if like me,
you work on UI things.
And especially, in your Mac Apps
because your windows have many,
many views and you
want to visualize,
let's say the bounce
of each view.
And so when I would like to
highlight is the Show View
Frames which will
put a colorful rec--
rectangle around every
view in your application.
I actually used this recently
because I had a toolbar
which I needed to make
a little bit smaller.
And it has-- as you know,
the toolbar will take the
tallest toolbar item in it
to represent the full height.
And I had one icon that
had invisible background
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
that was bigger and I didn't
know which one it was.
So I turn on this option and
it was easy to pinpoint exactly
which toolbar item it was and
I could change the, our asset,
debug it, make that item smaller
and fix my bug, it was green.
Now if you're on iOS, we also
have some solutions for you.
Many people don't realize
that LLDB accepts expressions
which are fully qualified
Objective-C statements.
And so if you have a method,
let's say the UIViews
recursive description,
you can send a message
to that object,
telling it to return the string
for that recursive description
and print it to the console.
And this allows you to
see what the child views
of that view are.
And many of the properties
that you might need
to debug what's going
wrong with your UIViews.
And so these workflows
are very powerful.
And now I'd like to
switch gears and talk
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
about the specific
debugging workflow
that we've made really great
and that's XPC Services.
But first, let's talk a little
bit about what XPC Services are.
XPC Services are really
powerful bits of functionality
that you separate from
your main code in order
to have stability
or maybe security.
And Xcode provides a template
if you're writing a Mac App
that will allow you to
create one of these surfaces
which makes a bundle
inside your application
which is a separate process
that gets launched by the system
when you call the
APIs that call it up.
And this bundle can
be communicated too,
you can ask request things
from the bundle and when
that operation is completed,
it will send the message back
with the results
of that procedure.
This is possible to
do in Xcode 4 to--
it is possible to modify
your scheme to wait
for these XPC services
to come up.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And when they do, your
Xcode will attach to it.
And what does that mean
to attach to XPC Service?
That means it gets its own entry
in the debug navigator
complete with its own gauges.
And if you said breakpoints in
the XPC Service, they'll stop
in those breakpoints
just alongside your Mac
Application breakpoints.
So it's easy to be able
to step through each
of them concurrently just
by switching back and forth
between the process and
the debug navigator.
But the difficult part is that
when this communication ends
with your service, the
system is allowed to wreak
that XPC Service to free up
system resources for other apps.
And so to make that even better,
we've improved the
situation in Xcode 5.
When Xcode debugs your
application, it starts listening
for any services in
your application bundle.
And when those services come
up, Xcode automatically attaches
to it, meaning, you can set
breakpoints, you can see it
in the debug navigator,
you can check out the CPU
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and memory reports for those.
And when it goes away, Xcode
automatically detaches.
But Xcode is waiting once again
for that service to come back
and we'll attach to it again,
providing a seamless experience
for you XPC Service debugging.
This works great
in practice and I'd
like to invite Christopher
Friesen
up one more time to
give a final demo.
>> So yet again our users
want another feature.
They want to be able to look
at any image of the internet.
Now this might be kind
of dangerous to do.
So we're going to put this
functionality in an XPC Service
so that it's partition
from our main application.
So we've changed the
input to be a URL
and we put this on our service.
So let's take a look
and see what Xcode does
as we debug this application.
So I'll click the run here,
our application starting up.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Now we've hit a breakpoint where
the main app is now setting
up an XPC connection
to talk to our service.
You'll notice that in
the debug navigator,
we currently have just
a single application.
Our debug gauges and
threads and stacks.
Now as I continue, watch
this area and you'll see
that we automatically
attached to the XPC process.
And there it just showed up.
You'll note that it
has a different icon
in your main application.
It's a black and white
screwdriver and a wrench.
And again, it has
the same debug gauges
and the same capabilities
in this debug area.
As you see in our application,
we've fetched the image
and we're displaying it.
Now in order to debug in your
XPC Service, you simply need
to go set your breakpoints.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So we'll go to our breakpoint
that we've already created.
I'll set it in our service
and then I'll go back
and exercise our application.
Here we are.
It's now in the debug navigator,
you can see that we've
got our main application
which is still running, the
gauges are still whirling away,
the UI is still responsive, but
the XPC Service has been paused.
And here you see
that we're stopped
in thread 16 on stack
frame zero.
And we can continue
our application.
And we see that we've
returned back from the service,
applied the filter and
display it in the UI.
Now another thing to note is
that the Stop button
doesn't show
that multiple processes
are running.
This is because we
grouped them together
so that whenever you click stop,
we'll stop your main application
as well as your-- any XPC
processes that you have running,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
this is so that you can go
back, change your source code
and then next time you
run, we'll use that--
those changes in
your XPC Services.
So let's watch that debug
area as I click Stop.
I know, it's exciting
when it just works.
So there, so this is, so as we
said, XPC debugging is automatic
and enabled by default, but
there's also a toggle for it.
So let's go to the scheme popup
and we'll choose edit scheme.
Here we see that we're
on the run action.
Currently, we have
the info tab selected.
If we go to the options
tab, we see that the option
to toggle our debugging
XPC services is right here.
So here, you can
just toggle it on
and off should you ever need
to, most likely you won't.
And we hope that the
XPC integration in Xcode
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
for debugging your XPC
Services will entice you to look
at the powerful XPC subsystem
in Mac iOS X and add it
to your application, thank you.
[ Applause ]
>> So today, we've talked
about a lot of new things.
We talked about the
new debugging gauges
and the associated
debug reports.
We talked about data tips
and the improvements they
allow access to Quick Looks
which are also available
in the variable view.
We talked about some
drawing diagnostics
that you have access to.
And we talked about XPC Services
and the debug capabilities
in Xcode.
I know many of you; perhaps
all of you have new features
or new applications that
you're working on right now.
And I really hope that you
use the new features in Xcode,
maybe you take a look
at that debug gauge
and see what your
memory profile is like.
Maybe you look at the CPU,
maybe use the new Quick Looks
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
to solve the problem
in your application
because Xcode is
trying really hard
to make sure you ship great Apps
and I hope that's
what you get to do.
We have, of course, if
you have any questions
after the conference, you
can talk to Dave DeLong
or visit the developer forums.
There are some really
great people there.
I've referenced some
related sessions.
Thank you very much
for attending Debugging
in Xcode 5, have a great week.
[ Applause ]