Transcript
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
[ Silence ]
>> Good afternoon.
[applause] Thank you.
Welcome to What's New in Cocoa.
My name is Ali Ozer, I'm the
director Cocoa Frameworks
at Apple.
So, what are we going
to talk about today?
We're going to give you
a high level overview
of the updates we made to Cocoa
in Mac OS X Mavericks 10.9,
and we're going to give you
pointers to related sessions
and labs because we have
many sessions and labs.
Note that everything we're going
to talk about today is new,
so I'm not going to be
putting this new badge
on every single slide that
has new material on it,
pretty much most things are new.
And this is not a
complete reference
to all the things we've added.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
These are the highlights, we
have Heather file updates,
we have Release Notes,
and in many cases coming
soon we have documentation.
Please refer to those
for the complete story.
OK, first let's talk about Tags,
you saw the feature
yesterday in the Keynote.
Tags is a new feature
which enables users
to assign arbitrarily named
labels to their files.
And users can search
for their files
or group their files
using these Tags.
It's a pretty powerful feature.
Just to recap what
it looks like,
so here is some files
grouped by Tag for instance
that you can see the tags
are shown along the side
and also under the file names.
You can search by
tag as shown here,
you type your search tags
there and you will be displayed
that files with those
tags will be displayed.
You can bring up a side bar
which lists the tags you have.
You can go ahead and use tags
in your iCloud open panel.
You can see the tags and their
iCloud documents as well.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
You can go ahead and assign tags
to files as you're saving them
or you can go ahead
and change the tags
on files using this new
document popover that comes
out from the title bar.
So there are many ways for
users to interact with Tags.
Now, let's talk at-- look at
the APIs we've added for tags.
It's actually not too many APIs
here we don't need too many.
One is a new, NSURL resource
key, NSURL tag names key
and the value of this is
an NSArray of NS strings.
You would use this API on
an NSURL, get resource value
for KeyError which of course
an API NSURL already has
to get the list of Tags
assigned to a given file,
and you would use the set
API to set tags on a file.
Now, as you saw earlier, we
also have support for Tags
in the safe panel and
it's actually automatic,
not just for NSDocument-based
applications
but also any application
that uses the safe panel will
get a TagsField as shown here.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Now, the safe panel
will show the TagsField,
it will allow the users
to edit those tags
and it will also
automatically apply those tags
to the saved file, so you don't
really have to do anything.
Now, there might be cases
where this doesn't work right
or there might be
cases where you want
to customize this behavior.
In those cases, we
do have an API.
You can explicitly indicate that
you want to show the TagsField
or you don't want to
show the TagsField.
And if you are showing the
TagsField, you can then go ahead
and get and set the list of tags
that the user has
specified on that file.
And then you would
apply them yourself
or do whatever else you
want to do with them.
Next thing I want to talk about
is Light Content Controls.
So, these are new controls,
variants of our controls
are Standard Aqua Controls
that are meant for Window
bodies or Document Content.
Here's some example.
This is the event inspector
in the Calendar application
and the buttons you see
here, down the side,
these are Light Content
Controls.
As you can see they're
somewhat lighter,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
than standard Aqua
controls and they're meant
for that white lighter
colored background.
Here's another example, this
is the Contacts application,
and the buttons along the side
are light content controls.
Here's the Maps application.
Now, the buttons along the top
here are standard Aqua controls
because they're just
being displayed on top
of the standard Window
background.
But if you bring up a
popover in this application,
then the buttons you
see in the popover again
in that light background, these
are light contents controls.
So, how do you access these
light content controls?
Well, they're available through
a new API called NSAppearance.
This is a class that lets you
access alternate appearances
and it's got a bunch of
methods, the one I'm going
to show here is appearance name,
you just give it
an appearance name
and it fetches an
appearance for you.
And we have two appearances
to find;
Standard Aqua, and
Light Content.
Now, once you have
an appearance,
what do you do with it?
You would use this protocol
which is to find on View,
on NSView and NSWindow,
the appearance customization
protocol.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
You can go ahead and the set
the appearance of that View
or Window, and all the UI
elements inside that View
of Window will now
inherit this appearance,
and start using the
appearance you've specified.
And since the UI element
can inherit its appearance
from its parent views
there's also another property,
a Read Only property
called Effective Appearance
which lets you tell what
appearance a UI element should
be using.
Now, you don't have to use codes
for this, you can also do this
in Xcode in the Attributes
Inspector
in Xcode interface builder.
So here for instance is the
Attributes Inspector for box.
You can do this for
container classes.
And at the bottom here, you
see the appearance setting.
It's now showing Aqua.
If you click on it
you can see that,
you can now specify light
content for that container
and as I said, all the elements
in there will now start
using this appearance.
Next thing I want to talk
about is NSStackView.
NSStackView is a
new class we've added
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
to AppKit in Mavericks.
It's a class which
manages stacks of views
and it uses Auto
Layout internally.
It lets you group the views
and we'll be seeing an
example of that shortly.
And it also will manage
the sizing of the views
and it will also drop Views, or
click Views, or tighten Views
as necessary as the
StackView size changes.
Let me give you a
little example.
This is the kind of view you
might build with NSStackView.
Here you have a group of
controls on the left side
and you have another control,
a slider on the other side.
As this view is made smaller,
the slider comes closer
to the other group and then the
slider starts getting smaller.
And then, the text field
starts getting smaller.
And eventually when there's no
more room and pressure's rising,
the button all the way at this
end is voted off the island
and then things start to
continue to get even smaller.
So, as you can see, StackView
they're not only used
to using Auto Layout, it's also
hiding and removing some Views
as needed and it will
also bring them back
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
when the StackView
is made larger.
So, in this way StackView is
using Auto Layout and building
on top of it, and you
yourself don't have to worry
about any creating those
constraints or managing them
which is, you know, not
that [inaudible] especially
once you're removing
and adding Views and so on.
Now, StackViews don't
have to be horizontal,
they can also be vertical.
Here's a kind of view you might
build with a vertical StackView,
this is an inspector
panel you might see
in drawing application.
As you expand the various
pieces, various elements up here
and you know, they will collapse
as well and that's the kind
of thing that's fairly simple
to build with a StackView.
The API of NSStackView
is purely straightforward,
you create one by giving it
some views, StackView with views
or you can choose to add Views
explicitly one at a time.
Here, you're specifying gravity
and the gravity is the grouping,
either one end, to the other end
or the middle of the StackView.
And there are other
properties on StackView
that lets you specify properties
in Layouts such as the spacing,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
the priority, what the clipping
and hugging priorities
are and so on.
There will be a more in-depth
coverage of NSStackView
in this talk which is tomorrow,
best practices for
Cocoa Animation.
This talk will also go into
various animation techniques
for Cocoa both old and new,
so it's a great to talk
to learn both about animation
and StackView and in fact
about animating StackViews
as well.
So, next I want to talk--
so just of having to
talk about Auto Layout,
let me just talk a bit
about Auto Layout as well.
In Auto Layout, we've made a
lot of performance improvements
and this is true in
general but especially
in view-based TableViews.
That's because constraints are
now attached to Views in a way
that as Views are removed
or added to the hierarchy,
they stick to the View.
In addition, we've
made the enumeration
of constraints a lot more
efficient and predictable,
so that you will see much
more predictable behavior in--
when dealing with Views that
have a lot of constraints.
So, that's something you should
notice in your applications.
In addition, we have
a new workflow to deal
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
with Auto Layout in Xcode.
In general, Xcode is a lot
more flexible and forgiving
about letting you do
Auto Layout in Xcode.
You can now delete constraints,
you can create ambiguous
structures, you can move Views
around et cetera and Xcode
won't throw a fit anymore.
So this is-- you
are more in control.
And you can see more about
this in tomorrow's session,
taking control of Auto
Layout in Xcode 5.
Next, I want to talk about
Responsive Scrolling,
and you saw a demo of this
yesterday at the Keynote,
in addition you saw it perhaps
at the State of the Union
in the afternoon as
well it's something
that we've worked a lot on
and it's you know
something we think is great.
The goal here is to
provide the users
with non-stuttering
fluid scrolling.
So let me just give you a review
of how scrolling works in 10.8.
So here it is a view and assume,
not the blue border there
is your divisible area
of the ScrollView.
In 10.8, when the user
scrolls, they see this.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Now, really what's
happening under the covers is
that when the scroll
starts, divisible area
of the view is copied up
a blip, blip if you will.
And then the-- reveal the area
is drawn in by calling drawRect.
And then this happens again
for every little
slice that's visible.
And of course, the user
never see the black flash
because we actually copy
the bits up and then we fill
in that area without
flushing the Window
so that the user actually
doesn't see a flash.
But one thing you will notice is
that in a situation like this,
the scrolling performance
is really at the mercy
of the performance of drawRect.
If that drawRect
call just to fill
in that little strip
takes say, half a second,
scrolling all stutter,
really for half a second.
And actually more generally,
scrolling performance is
at the mercy of the main thread
because the drawRect is
happening on the main thread
and the main thread is
a pretty popular place.
There is the Run Loop there.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
You know, things are happening.
All sorts of things
might be happening,
network activity,
who knows what?
So, even if drawRect wasn't
badly behaving there might be
other factors which cause the
whole scrolling experience
to stutter in certain
conditions.
So, what's the solution?
The solution is to dissociate
the scrolling from domain thread
as much as possible and
we've done two things
to help with this.
One, is to get scroll events
of a secondary thread.
Now, despite itself is good
because the main thread is
now longer fetching events.
However, it's not
good enough by itself
because if you get scroll
events on a secondary thread
and if you scroll the view
on the secondary thread there
still won't be any content
to show.
So, there will be white
flashes as the user scrolls,
clearly not, not ideal.
So the second part
of the solution is
to prepare Overdraw
regions ahead of time,
so that the scrolling
can happen smoothly.
And let me show how this works.
Here is our ScrollView again
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and this time we have a visible
area, the area that user sees.
In addition, we have this
additionally drawn area
which we called the
Overdraw area
and that's not visible
at the moment.
So as the user scrolls this up,
notice that drawRect
doesn't need to be called
and the user maybe scrolls down
again no drawRect being called.
And-- but if the user scrolls
a bunch, then we might go ahead
and call drawRect to fill
in that Overdraw area.
And of course Overdraw area
is well exists on any edge
that the user can
scroll towards.
Now, this responsive
scrolling is actually automatic
so you don't-- in most cases
you don't have to do anything
and your app should
get this feature,
assuming they're linked
on 10.8 or newer SDK.
And there are also a
few other conditions.
Now, your application can
chose to explicitly opt in our
out by overwriting this method
and this is a purview method
because you might want
some ScrollViews to do this
and some ScrollViews not to is
com/public responsive scrolling
by overwriting and
returning yes you say
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
"I'm doing responsive
scrolling no matter what."
Or "No, I don't want
to do responsive
scrolling no matter what."
So there's a bunch more
APIs here and a lot more--
lot more stuff to
learn and we will cover
that in Optimizing
Drawing and Scrolling talk
with is tomorrow
afternoon at 3:15.
And the next, I want to talk
a bit about Export as PDF.
And we talked about
Export as PDF before
and maybe you've heard about
it in its using its other name
such as save as PDF, save to
PDF, export to PDF et cetera.
The idea here is to enable the
user to generate a PDF file
without going through
the print panel.
And in fact in general,
we'd like the UI
to separate PDF generation
from the print panel
and the whole printing
process as much as possible
from the point of
view of the user.
So, in 10.9 here is what happens
when you choose Export as PDF
in an application like TextEdit.
Here's my window.
You get a nice, simple
safe panel.
It does nothing to do with
printing just a safe field.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And you can go ahead and save.
That's it.
Your PDF is generated.
If you want to go ahead and set
some parameters the users want
to have some control
or what, what they get.
They can click the
Show Details button
and get a somewhat expanded
panel which has field
such as page, size
and orientation
if appropriate for
your application.
In addition, possibly
some additional views
that the application
is adding custom views.
And you know, we normally refer
to those as accessory view.
Now, we've added new APIs
and behaviors in 10.9
to make it lot easier
to do all this.
If you're NSDocument based
application there is a new
action method, save
document to PDF.
If you connect the
menu item to this,
that's pretty much
all you have to do
and you'll get the
experience I showed you.
Now, you might want to customize
though the PDF generation.
For instance maybe
during PDF generation,
you want to take a
different printing code path.
Not the one you would get
when the user print it.
In that case, you can
overwrite this method--
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
I'm sorry, I skipped the
PDF print operation method
and customized the
print operation.
Now, if you're a non
NSDocument-based application,
and it's also fairly easy
when you're generating your
Print operation, go ahead
and specify the job
disposition of Print Save job
but do not supply a URL,
what that will do is
that will cause the
save panel to be shown
and the user will be able to
specify file name as you saw.
There's a few other
ways to customize this.
One new class, one other
new class is NSPDFPanel,
this gives you more panel over
the panel and the excess review.
For instance, let's
say you don't want
to export just one
PDF file but you want
to export the whole bunch
of related PDF files
and you just want the user
to choose one location.
With this, there's an option
that lets you choose a folder
to save the PDF files too.
And then there's this other
class NSPDFInfo that sets
and gets that basically
holds the user choices
that are being made.
Next thing I want to talk
about is Media Library Access.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So the media library is the
user's library of images,
music, videos and so on.
And they're managed by
applications such as iPhoto,
Aperture, iMovie, iTunes.
So, we have two sets of
APIs to make it easy for you
to access these media resources.
One of them is a very simple API
that just gives you
a non modal panel
that will appear in
your applications.
It's a new class of an app kit
called NS Media Library Browser
Controller and it's
fairly easy to use.
You would go ahead and
create the shared instance.
You would specify what kind of
what library you want to see
in this case image
so the photo library.
And then make the UI visible.
When you do this, you will
get the panel that looks
like this appearing
in your application.
As you can see, it's showing
you your iPhoto events just
to where the user is used to.
The user can go ahead and choose
or browse for individual images.
They can also go ahead and
browse through locations, faces,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
et cetera just like it appears
in iPhoto, Aperture et cetera.
They can also go ahead and look
at the images in a list view
which gives them more
details about the images.
So, it's as fairly
simple, not customizable.
But you know, that only took two
or three lines of code to show.
The other API we have
gives you low-level access
to the user's library and
this comes in the form
of a new framework called
medialibrary.framework.
This library provides you
with an Objective-C data model
that represents all
of the user's media.
It's a read-only model so you
can only access the images
for showing in your app or
importing into your app.
It's also asynchronous
in the sense
that your application
doesn't have to be blocked
as you're rummaging
through library.
And just to give
you a quick overview
of what this framework
looks like,
there are four principal
classes,
ML MediaLibrary represents
the library.
ML MediaSource represents
the individual applications
or source of images.
ML MediaGroup represents
groups that make sense
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
within that source for
instance playlists or locations
or photo albums and so on.
And finally, ML MediaObject
represents individual
media objects.
This-- this class will
provide you with properties
of that object such
as the dimensions,
the length of the
movie, et cetera.
In addition, that will
also return to you a URL
which you can use to
access the media object even
in SandBox applications.
Next, I want to talk about
block-based sheet presentation.
As you know, blocks are a
feature we introduced in 10.6
and since then we've been
incrementally updating our APIs
to take advantage of blocks.
In one area where
we haven't done that
yet is generalized
sheet presentation.
In 10.8 and earlier, if you
want to present the sheet
in your application, here's
the code you would write.
You tell NSApp to begin
a sheet you provide
which Window the sheet
should be attached to
and then you provide a call
back in the form of a selector.
And then you go ahead and
implement your selector.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And inside that selector,
inside that method,
you process whatever
the user chose.
So, you know it's pretty
powerful, pretty good stuff
but it does take a
few lines of code.
You know, not super convenient.
And in 10.9 here is
all you need to do.
You tell the parent
window to show the sheet
and then you execute the
code that should happen
when the sheet is dismissed.
So, that's really it.
So that's the code
you're writing here.
So it's much better.
Now, this thing has
few other advantages.
This approach has
few other advantages.
For one thing, this version will
automatically dismiss the sheet.
You don't have to call
order out anymore.
When that completion
block is done,
the sheet will be dismissed.
It will queue up multiple
sheets for presentation.
Although it's not, you know,
UI we generally recommend,
sometimes some subsystems
might want
to show sheets one
after another.
And you all want those sheets
to appear on top of another
which doesn't exactly
working all cases.
This one will actually
queue them
so as one sheet is dismissed,
the next one will appear.
Now, however, if you're
a subsystem and you want
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
that sheet of your stuff here
immediately for some reason,
there is a big and critical
sheet completion handler
which will get your
sheet to cut--
you know, cut through
the line and up here
on top of everything else.
Clearly this would only be
used for some serious errors,
emergencies, whatever.
But anyway yes you have
that API if needed.
One thing you saw yesterday at
the Keynote is our new support
for multiple monitors and I
mean, here we say full screen
for multi-monitors,
it's actually goes way
beyond full screen as well.
Let me just recap what
this feature looks like.
So, here we have a MacBook Pro
and a larger screen attached
to your MacBook Pro and as you
can see here both screens have a
Menu Bar that Safari
is running on this one
and iPhoto is running
on this one.
So that the MacBook
Pro screen is active
because it's got
an active Menu Bar
and that's the active
application.
If the user goes and
clicks on iPhoto,
the menu on the other screen
is now active and the menu
on the smaller screen is
now appearing inactive
so that's you have a one active
screen at any given time.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So the user can go ahead
and interact with iPhoto put
into full screen mode, go into
edit mode and in fact even put
into gorgeous full screen
editing mode like this,
fairly straightforward.
They can also go ahead
and do the same thing
on their other screen and put
Safari into full screen mode,
again all part of a
standard operation.
They can also go ahead and just
switch between different spaces
on any screen they want as far
as they can switch the maps
or they can switch the pages
or they can switch the
desktop screens and so on.
So it's very powerful,
very flexible environment
and this is all controlled
with really just one setting.
If you launch Preferences
and go to Mission Control,
the setting here displays
out separate spaces is what
controls all this new behavior.
Now, users can go turn them off
in which case they get back
the 10.8 behaviors that--
you know that we had in 10.8.
So this is a user choice
and in this mode what happens
is each screen has its own set
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
of spaces as you saw.
Each screen has its
own Menu Bar as you saw
and Windows do not span screens
so Window will either to be
on one screen or the other
but not span screens.
Since this is a user choice
there's not much control your
application has over it
and there are no new APIs.
There's some changes
in behaviors however.
For instance NS screen main
screen method will now return
the active screen and
active screen being defined
as the screen with
the Menu Bar on it.
And resumed Windows and
resumed applications
so these are state-restored
Windows,
will return to their previous
locations wherever they might be
on all the user screens
and newly opened Windows will
prefer the active screen.
So we believe these
behaviors will be appropriate
for most applications.
If you get a chance, we'll pop
that second screen you're
carrying around in your bag
and try your applications.
And if you don't happen
to bring a second screen,
we do have some downstairs
in the labs and you can hook
up your portables
to those screens
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and see how well your
applications work
in full screen modes.
So next thing I want to
mention is we have an updated
system font.
So how many of you noticed that
we have an updated system font?
I'm not talking about my iOS 7,
OK a few if you have
noticed that's good.
So, yeah we do have a
new font for UI Elements
and it's actually not a
drastic change at all.
It's very similar to the font
we had before-- Lucida Grande.
It's optimized for
retina display
so they're just slight tweaks.
This font is-- it's-they're
slight tweaks
but they're really not
significant enough at all
where they will cause
rewrapping of text and so
on so we're pretty
certain that's the case.
This font is not
intended for general use.
This font is really just
a UI Optimized version
of Lucida Grande so any users
who are using Lucida Grande
in their documents and so
on will continue to
use Lucida Grande.
Now you're saying, "Hey, my
application is UI Elements.
How do I use this font?"
Well, it's pretty simple use it
the exact same way you've been
using before.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
If you're calling NS
Font system font of size,
you will get this new
font now or in Xcode,
in the Attributes Inspector, if
you have selected system font
which is by the way the default
in most cases and has been
for many years, the system
font here is the right one.
So if you're using this one,
you will be getting
the correct font.
So no worries, your applications
might already be using this font
properly in 10.9.
Now, if you ever
bring up a font panel
and to see this font
called Dot Lucida Grande UI,
just ignore it, it's not there.
We hope it will go away soon.
This is-- this might make an
appearance in a few places,
this is not even a final name
or we don't know how this
will land but ignore this.
Don't reference it by name.
Again just use the system
font of size method.
And I want to shift gears a bit
and talk a bit about App Nap
which you also heard about
yesterday in the Keynote
and also State of the Union.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So App Nap is a new system
feature in OS X Mavericks
where the system will throttle,
non for grand applications
that are not doing useful work.
So now some of you are wondering
what this throttle means.
Some of you are wondering
what this useful work means so
and not for grand apps like--
'cause they have to
maybe is the question,
but anyway so there are a
bunch of questions here.
What do all of these mean?
How's it going to do to my app?
And that's maybe the
biggest question.
So first let me define
what throttle means,
the biggest thing about
throttling apps is
that timers will be delayed
and they will be rate limited.
So once an app is decided
as not doing useful work,
it will be put into App
Nap mode and in this mode,
say the app has a timer to
set off to go in one second.
The timer might actually
not go off
for 10 seconds or
maybe even more.
Let's say an application
is that timer that's set
to go 60 times a second.
That timer will now start
going off every 10 seconds,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
so you know it's really
going to be sleeping.
Another thing that
happens is apps
that are napping will have
lower I/O and CPU priorities.
So even when they're
executing code,
their overall throughput
will be somewhat reduced.
Now it's not a drastic reduction
but it will be reduced compared
to other applications, the
foreground applications
and not napping applications.
So the other question is, well
what does useful work mean?
Well so there are
some heuristics
to determine useful work because
as you might guess it's not easy
to tell an application that's
using a hundred percent CPU
and doing something useful
versus something that's
using hundred percent CPU
and not doing anything at all.
So here are our heuristics,
one is handling a user
event or an action method.
So, if we find ourselves
that were in action method
in the main thread,
that's clearly as a result
of the user having hit a button
or chosen some Menu items
so that's presumably
useful work.
Drawing visibly, if the app
is actually drawing something
visibly while the user is seeing
that drawing so we really want
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
that drawing to continue
playing audio as well
and the disabling system sleep.
Now some of you might be aware,
we have this API previously
in fact power assertion API
where an application can say,
"I want to disable
system sleep."
This is where the system goes
to sleep after no activity.
Applications can disable that
and the reason they do that is
because they're doing some
long-running operations
such as exporting images or
doing something else long,
and then they don't want
the system to go to sleep.
So, we take that
as a hint to mean
that the app is doing useful
work and we disable App Nap
for the duration for
that application.
And finally we have some new
APIs that we'll talk about.
You can use APIs to declare
activity formally and then we--
of course say, "OK you're doing
useful work, useful activity,
we won't put you to sleep."
Now App Nap is automatically
applied to all applications.
In fact that's the
goal of App Nap.
You know, we know that
there are a lot of apps
out there probably enough of
yours but there are a bunch
of apps out there that
do misbehave sometimes
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and they're sitting in the
background just chewing
through CPU-- you know maybe
well-intentioned purpose
but again they are still chewing
through CPU and we're going
to apply App Nap to all these
apps who haven't been updated
or who-- you know,
won't get updated maybe
for a few more months or years
or you know, the ones we want
to apply to all these apps
that's why we're applying--
you know, no opt-in required.
Apps will get App Nap however
if some applications
are misbehaving,
users can disable App
Nap for that application
by using the prevent
App Nap check box
in the File Info
Panel and Finder.
That will disable App Nap
for that version of
that application.
Note that this check
box will go away,
will vanish for applications
that are linked on 10.9
with the intent that when you
put up 10.9 linked versions
of your applications, they're
hopefully App Nap savvy
and users don't have to turn off
App Nap for those applications
so that's something
to look into.
Now earlier I mentioned
activity APIs,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
let me just give a
quick overview of those.
These APIs allow you to declare
the activities your application
is doing.
APIs are in process info.
Here's one of them.
Perform activity with options.
I'll talk about the options,
a recent string which is used
for debugging end the block
and this is the Activity
Block that's being executed.
Now if you can't represent
your activity as a block,
you can also call the
Begin and End methods
which are also on process info.
So let me talk a little
bit about those options,
those options that
you specify the kind
of activity that's happening.
One common one is NS
Activity user-initiated.
This is simply an activity where
the user wanted to do something.
They hit some button;
they chose some Menu item
so something is happening
clearly the app should finish
that even if app is
not in the foreground.
Another example is activity
user-initiated allowing
system sleep.
An example of this is
for instance an application
that's sitting there constantly
giving you stock price updates.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
The user might have
initiated that.
However, such an application
typically would not prevent
system idle sleep because it's
an application that's just
giving their-- showing
some status update.
Another example is
activate the background.
That's the kind of activity
that the user did not
necessarily initiate
but it should still
continue but maybe some--
the system should still
be apply some heuristics
to lower power usage.
But however, it's
still is something
that the app should not go to
App Nap during this activity.
An example of this is for
instance indexing in Xcode
or thumbnail generation
in an app like Aperture.
These are not things that
the user directly initiates
but these are things that
are being done on behalf
of the user, so they
should really complete.
There are a bunch of more
activities and you can look
at header files to see
what they're about.
Now, app nap is something
that's applied
to non-foreground
apps automatically.
We also have some APIs that
let you control some of these,
some of these facilities
explicitly.
Timer tolerance APIs
are one of them.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So, NSTimer now is
property called tolerance
and that lets you specify the
amount of delay you're willing
to tolerate on the timer.
So, the timer can fire by
up to that much time later
than the time it specified for.
So, the benefits here are
that this allows the system
to synchronize timers
across the system
so they're firing
at the same time.
And this as you saw yesterday
during the Keynote increases the
amount of time that the CPU
is idle which in turn impacts,
improves battery life.
So, let me show you an example
of how timers work
with tolerance.
So, here is a very
simple timer called
without tolerance you're
creating at one time,
one shot timer to
fire in two seconds.
And here is our timeline,
the timer will fire there.
Now, note that despite
the flaming graphics,
timers don't really fire.
But anyway, so, it will--
the timer will kick-off
at 2 seconds.
Now, if you were to go ahead
and provide the tolerance
of 1 second, then the
timer can fire anywhere
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
between 2 to 3 seconds.
And then if you're to go ahead
and create a repeating timer
with that 2-second time period
but a 1-second tolerance,
the first time you'll
fire is here,
the second time you'll
fire is from 4 to 5
and the third time,
6 to 7 and so on.
So as you noticed, the
timer isn't really drifting.
It's still firing
every 2 seconds.
However, the fire time might
be delayed by up to 1 second.
Another set of API's
we're giving you is the
occlusion APIs.
You can now tell whether
Windows are visible or not
and the advantage here is
by telling that a Window
that you're drawing something
into is not visible to the user.
You can actually stop doing
the work of drawing stuff
and maybe even stop doing some
other work that's supporting
that drawing work.
This API exist on NSWindow
and NSAapplication.
You can tell what the
occlusion state of a Window is.
And there also notifications
that tell you
when that occlusion
state to changes.
We do have a whole talk
dedicated to App Nap.
That's tomorrow morning
at 10:15,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
"Improving Power
Efficiency with App Nap."
In addition we have a lab
right after that Cocoa
and Foundation Lab where you can
ask App Nap questions as well
as any other foundation or
Cocoa questions in fact.
And then we have one more talk.
We actually have a lot of talks
about battery life
and power and so on.
But one that you might
have missed this morning
at 11:30 is maximizing
battery life on OS X
which is a great overview of
this effort and it's given by,
it was given by Bud
Tribble, vice president
of Software Technology.
Bud was also one of the original
designers of Mac OS in fact.
So, if you haven't seen
that talk you might want
to catch it on video.
So the next thing I want to talk
about is another new
facility we've added
to foundation called
the progress,
supporting and cancellation.
This is a new facility for
reporting progress of work.
It also allows the progress
to be presented to the user
and for the user to cancel
the work that's represented
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
by that progress.
And now, this facility
has got some aspects,
it's loosely coupled
meaning the subsystem
that is reporting
progress doesn't know
about the subsystems that might
be displaying that progress.
This facility is composable
across layers meaning
different layers
of software can be generating
progress in their own terms
and they might not even be aware
of other layers of the system.
For instance, the user
might say" Go ahead
and compress this
folder full of images."
So, at the top level we're
processing 42 images,
one image out of 42, two
images out of 42 et cetera.
But at the lower layer as each
image is being processed it's
running through a
Scanline so kind
of Scanline100 and
101 et cetera.
And each layer reports
progress in its own terms
but it's composed across layers.
And this is also across process.
One-- process the application
that's reporting progress might
be different than the
one that's observing it.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
A great example of
this is Safari
which is downloading a file.
It's reporting progress of
that download but Finder
or Dock can be observing
that progress
and showing actually how much
of that download is finished.
And in fact that those
facilities do use NSProgress
in the system.
So let me give you
a quick example
of how you use NSProgress.
Here's a simple method
which does some work.
It runs through an array
of stuff just one by one
and it processes the items
in the array fairly
straightforward.
If you want to make
this progress savvy,
you would insert these
two lines of code.
One of them goes and
creates an NSProgress object
and you specify a total unit
count for an array of elements,
the number of elements in an
array is a perfect unit account
for a file, the byte count
of the file might be the
unit count to use and so on.
And then each time through
the loop we go ahead
and set the completed
unit count.
We increment the completed unit
count to indicate we're done
with one more item, so
fairly straightforward.
Now, you can also go to the next
step and make those cancelable.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
To do that, you would
go ahead and say
if the progress is canceled then
you go ahead and exit the loop
with an appropriate
canceled error.
Of course, this would
also indicate
that you would tell the
progress that's cancelable
and that upper levels would
provide the ability for the user
to cancel the progress.
But you know, you can just
add this code here as a way
to say that, "hey, I know
about cancellation I'll deal
with it if the user did."
Observing progress is also
fairly straightforward.
There are properties
such as total unit count,
completed unit count,
fraction completed
that you can display in your UI.
There's also a localized
description that's generated
fairly generically or
it might be specialized
by whoever is generating
the progress.
In addition, there
are other properties
such as whether the
progress is in determinant
and of course whether
it's cancelable or not.
As I mentioned earlier,
an example of you know,
observing progress
is a finder window
where this file is being
either copied or downloaded
but the little bar at the
bottom is showing the progress
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and the X in the corner there
in the upper left
corner is showing you
that it's a cancelable progress.
So the user can click it at any
point to stop the operation.
So the next thing I want to talk
about is date and time handling.
And this is a favorite
topic of ours
because I think we've talked
about this every WWDC for a few,
for the last few years now it's
because current calendar
computations turned
out to be hard.
They're hard because there
are different calendar systems
in use around the world.
They're hard because there
are daylight savings.
They're hard there because of
their time zones and so on.
So there are a lot of little
complications involved
in current calendar
computations.
So to help with this, we
provided a bunch more APIs.
And I'm just going to
touch upon a few of them.
Some of the APIs are
just what we would refer
to as communions APIs.
They just give you very
simple one-line ways
to achieve some things that
might have been few lines before
or maybe in fact
more lines in fact.
And there might have
been hidden pitfalls.
An example is just
asking a question
like "is date in today?"
Is this NSDate object
some time in today?
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
One-line call now to your
appropriate calendar.
Another one is this
date in the weekend.
That's you know that's not
getting fairly powerful
because you know definition of
weekend might change depending
on what calendar and what
part of the world you are.
Another call along the same
lines "is date equal to date"
in unit ground [inaudible]
in this case,
it will tell you whether two
dates are within the same month
in that calendar
system and so on.
There's a bunch of methods here
I would encourage you to go look
at the header file to
see what we've all added.
We also have a bunch of
new enumeration APIs here.
And again, I will just--
I want to go through them all
just show you one of them.
Enumerate dates starting
after date.
Now, this method here will
enumerate dates you are
providing a date
components instance
which represents your
enumeration parameters.
And then options parameter which
represents what to do in case
of various exceptional cases.
Let me give you a quick example.
Let's say you want to create
NSDate representing 2:30 a.m.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
every day.
You'd create a date
components object set the hour
and the minute like
this to 2 and 30.
And then you would ask
your current calendar
which is usually the
most appropriate calendar
to enumerate.
So fairly straightforward
and you would start NSDate
date it's right now June 11th
at 4 p.m. So, you start running
this program and it will report
to you June 12th at 2:30
a.m. so on and so forth.
March 8th 2:30 a.m.,
March 9th at 3 a.m.
And it will continue
on reporting 2:30.
So what happened there on
March 9th, I think most
of you already can guess it's
when daylight savings
time happens here
in the United States.
So the algorithm chose
to give you 3 o'clock
but it also told you that
the time was not exact.
So you know that
something went wrong.
So where did the 3
o'clock come from?
Well, it came from
this argument here,
NSCalendar match next time.
This option tells you that if
this given time doesn't exist
and in this case of
course there's no 2:30
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
on March 9th time
jumps from 2 a.m.
to 3 a.m. just give
me the next time.
So it gives you 3 a.m.
There are other options which
give you other choices like 3:30
or 1:30 or maybe it doesn't
give you a return result at all
and just generates
an error instead.
So to find out more about the
various challenges and issues
and the various solutions we've
come up with, and to hear more
about these options in
this enumeration case.
You can go to this talk
on Friday at 11:30,
Solutions to Common Date
and Time Challenges.
You know, there are a lot
of hard things actually it
turns out in programing.
Another thing that's
hard is handling plurals.
Now, many of you might say,
"what's hard with that?,
I wrote this code" you know,
if N equals one, yes you know,
there is one and if otherwise
you know percent D files are
selected right?
So many of us are either
proud of within this--
having this code,
or maybe guilty
of having written this code?
So this code is actually fine
for English but it doesn't work
in other languages,
most other languages.
For instance, even French
turns out, treats zero
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and one differently
than the plural cases.
While in English, zero is
treated like the plural case.
And forget about Arabic,
here's what you get,
you get six different cases and
I'm not even going to you know,
run through this code.
But it's not simple
and so if you are going
to write a properly
localized application
that handles all these cases,
there's a lot of if statements
and a lot of localizations
we're having to deal with.
So, we have a solution
for this in foundation
and we call it localized
Populous File
and it was also known as
strings dict resource files.
Those of you familiar with the
way we do localization know
that we have strings file.
Strings dict files as you
can guess is just a glorified
strings file which actually
contains the full-fledged
dictionary in there.
It provides localized
forms based on plurality
as I showed and also gender.
It turns out gender, most of
you know isn't easy either.
Some languages have
one, some have two,
turns out some have
even more like up
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
to five in some languages.
And you know, and who
knows what will happen
when you discover an
alien race with 10 sexes?
So gender is not easy OK?
So anyway the good thing
here is there's no new API
to do any of this.
You just have in fact one
code of path, for instance,
here's a kind of
code you might write.
Just localize a string,
percent D files selected,
it's a nice generic string,
it'll work in case no
localization exist.
It's clearly suboptimal
but it will work.
However if this was
properly localized,
here is what the
localization would look like.
So let's look at a strings
file, the strings dict file.
First of all, avert your eyes
because there are
a lot of XML here.
And XML, you know
is this ugly glass
that makes everything
look unattractive.
So let's hide all this stuff
and maybe just pull out the guts
of what we're trying to look at.
So the string we're
localizing is up here,
percent D file selected.
It's been localized
into this string.
File count selected and that
substring file count is actually
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
being selected out of
this dictionary here.
Either the substring if file is
or the substring
percent D files are based
on the number we
have is one or other.
This works for the English case
and this is the English
strings dict file.
However, if the same
situation was being localized
for other languages, there would
be other cases here such as zero
or two or few or many,
which would apply
to different localizations
and different languages.
So this is the way that we
handle localizations now if you,
and it's a manner
of just you know,
coming up with the
current localization files
which can be done of
course in parallel
to your application development.
So I'm going to talk a
bit about instance type.
Instance type is a
feature we introduced
in 10.8 in objective C.
Instance type indicates
that a method returns an
instance of its receiver.
And you might already
be familiar with it.
It's already applied
implicitly to methods
such as ELAC, NEW and INIT.
Although these are not the
declarations you see in 10.8.
SDKs, this is the way
it works implicitly.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So this means that when you
send NSArray and ELAC method,
the return now is
implicitly assumed
to be an instance of NSArray.
So this is applied only to
a very few methods in 10.8
because many other methods
are not implicitly done.
But in 10.9, we've declared this
on many more methods in a number
of foundation classes including
NSString, NSDictinary, NSSet,
NSDate etc. So let me just
show you how this helps you.
Here is a line of code which
some people might have written
at some point, probably
nobody in this room.
And I'm just going
to put a big X on it
because there's a giant
error in this line of code.
And you know, you're saying
of NSMutableSet mySet
equals NSMutableArray array.
Now the thing is so, in 10.8,
the compiler says OK, whatever.
It doesn't even generate
a warning.
And that's because
the arraignment
to the 10.8 is declared to
return ID so the compiler think
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
that it's a good match here.
Now, what's even sadder
is that if you go ahead
and write the next line
like this, mySet add object,
this also works because add
objects happens to exist both
in NSMutableArray
and NSMutableSet.
So now you've written a code
which is totally not
doing what you intended.
But it is working and the
bad thing is this will work
with a number of
items like 5, 10, 20.
But you know, as you add
more items to the array,
instead of getting
set characteristics
that you might have
been expecting,
you will be getting
array characteristics.
So your performance
will be suddenly showing
weird behaviors.
So, the bottom-line in 10.8, the
compiler is happy, no complaints
and the Apps seems to work.
In 10.9, here's what
the compiler will do,
it will give you a big warning,
telling you yes,
something's wrong.
You won't be clapping
actually once you complied your
applications on 10.9
and get warnings.
However, it's very important to
pay attention to these warnings
because we found out
many cases where we--
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
we've gotten warnings
due to this,
were actually either real bugs
or bugs waiting to happen.
So it's a good idea to pay
attention to these warnings.
They are good for you.
Now, speaking of NSArray, let's
talk about a tidbit in NSArray.
For the longest time, we've had
a method called last object.
And now, we've added a
method called first object.
And because we love you so much,
it actually works
back to 10.6 in iOS4.
So we made that happen to you.
We decided it was about time,
we were keeping it you know,
it was just ripening
on the tree.
So there it is.
Another tidbit about NSData,
so NSData now has basics
for encoding and
decoding support.
You can encode/decode
back the strings and data.
Thank you.
You can also cast the dispatch
data ts to NSData's now
and this is actually a one way--
one way bridging effectively.
They're sometimes you-- you
know, you cross API boundaries
and you need to do this.
And note that since dispatch
data ts, those of you
who are familiar
might know this.
Dispatch data ts can represent
discontiguous blocks of data.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
There's a slight, you know,
maybe mismatch with
NSData there.
If you call NSData, bytes method
will actually make it work.
However, if you want
to be more efficient
with these continuos
blocks of data,
you can actually use this new
enumeration method we've added
which lets you enumerate NSData
in terms of the blocks it has.
And of course, if you
happen to call this on one
of the traditional style datas,
you'll still get just one block.
It will be as efficient as
calling the bytes method.
So it's you know, it's a pretty
good method to use in general.
So just call enumerate
byte ranges using block
and it will return to
you the radius where the,
the ranges where the
discontiguous memory
blocks exist.
OK, NSURL component is another
new class in foundation.
NSURL components is to NSURL
what NSDate components is
to NSDate.
It's a mutable class that lets
you parse and create URLs.
And for those of you
who are into RFCs.
This now allows NSURL to be
compliant with this RFC up here.
The API is fairly
straightforward.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
You can initialize
one from a URL
or you can just initialize
an empty one.
You can go ahead and set
various properties on here
such as the scheme, the
user, the path, the query.
And you just go ahead
and extract the URL.
And just to show you
a quick example, you--
so let me create one just
specify those parameters
and I can go ahead
and ask the URL
and here's the output you get.
So it's much, much
more straightforward
than using the previous
URLs and the APIs and NSURL.
NSURLSession is another
API in foundation.
It's actually a set
of related classes,
it's replacement APIs
for NSURLConnection.
It's-- gives you
improved control
over configuration options
such as authentication
cookies and caching.
You no longer have to fiddle
with the global settings,
you can just set them for the
operation you have at hand.
It has ability to pour out
from out of process downloads
and uploads and it will
notify you when it's done.
And there's also some
convenience APIs in NSURLSession
that lets you do simple
cancelable asynchronous
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
operations which has
a few lines of code.
I'm not going to go
into more depth here
because there's a talk
about NSURLSession,
what's new in foundation
networking.
We have some improvements in
the core data and you heard
about this yesterday as well.
In the area of iCloud
support, we now made it
so that core data does lot more
of the tedious things for you.
For instance, core data will
now manage your fallback store.
You don't have to
deal with it anymore.
Core data will do asynchronous
iCloud initialization,
so you don't have to worry
about writing that code anymore.
And core data will also
automatically handle account
changes for you.
So that's another block of code
that you don't have to write
in your coded applications.
In addition, there are
many other fixes not just
in core data but also
in the iClouds stack,
both in the client and server
that will make your
applications--
that will help make your
applications more robust
than before.
There are other changes in core
data as well and one of them is
that we've enabled
write-ahead logging,
journaling on by default.
This replaces rollback
journaling
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
that was on by default before.
This write-ahead
logging journaling is--
has improved reliability,
concurrency, and performance
so it's a good thing in general.
So you can hear more about
core data changes and core data
and iCloud as well tomorrow
morning in this talk,
What's New in Core
Data and iCloud.
There is also a talk
tomorrow at 2,
core data performance
optimization and debugging.
A new feature in objective C
for 10.9 and iOS7 is modules.
Modules is a better way to
import a framework's interface.
So instead of using pound
import that you're you know,
used to love, it's been
around for a while.
Cocoa/cocoa.h you can now
use at import of coco.
What this does is it loads a
binary representation, however,
I mean, just something
you could do before
with pre-compiled headers,
but it's more flexible
that pre-compiled headers
because you don't have to manage
that list of pre-compiled
headers anymore.
The system will take
care of it for you.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
This is also immune to effects
of local macro definitions
you know,
there's that C programmer
mistake of pound to find int
to you know, short
or whatever you know.
That will no longer be
an issue in this case
because those macro definitions
do not take effect in interfaces
that you've imported as modules.
These are enabled for
new projects by default
and you can also enable it for
your existing projects as well.
So there'll be a lot
more coverage of modules
in advances in objective C.
I just want to mention,
highlight of few new
frameworks we've added.
One of them is MapKit.
It was on iOS6.
It's now available on 10.9.
Sprite Kit, you heard
about Sprite Kit yesterday.
It's a new framework for
doing games or applications
with game-like animations
and physics needs and so on.
And there's also AV
Kit which is used
in conjunction with
AV foundation.
It's you know, you
can replace usage
of queue ticket in
your applications.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
There are talks for this, moving
to AV Kit and AV Foundations,
introduction to Sprite Kit
and what's new in Map Kit.
So I'm going to talk
a bit about Textkit.
Textkit, you heard
about this yesterday
in the State of the Union Talk.
Textkit well, let me choose
Textkit by saying when you look
at Cocoa Text on OS X,
you see NSTextView.
However, if you make
any sophisticated use
of the text system on OS X,
you know that's actually made
up of these underlying classes
which gives you a lot more
power and flexibility.
When you look at Textkit on iOS,
which is a new feature in iOS7,
if I didn't make that clear,
you see that there is
the UITextView class
which has existed
for a long time.
However, if you look
underneath now,
you'll see the same
set of classes.
In addition, they have the same
or very similar set
of APIs as well.
So I'm mentioning this to you
because yeah, those of you
who have a sophisticated
text need of applications
with sophisticated
text users on OS X,
you can now import
these applications
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
to iOS with a lot more ease.
So you can find out
more about Textkit
in the two talks introducing
Textkit and advanced Textkit.
OK so, as I'm running out of
time, I just want to throw
up a list of some other
changes we have bunch
of Table View outline
view improvements,
we have layer-backed
new improvements.
Again please look at the
release notes, read about these.
NSSlider has some new APIs and
we got rid of some crusty ones.
Some built-in services,
additional built-in services
and NSSharingService.
There's some NSCalendar
convenience APIs
which make it easier to move
your code back and forth
between UIColor and NSColor.
We've-- all right, some
people have tried that
and now it's even better.
So we've deprecated some NSNib
and NSBundle nib-loading
methods.
And the new ones
we had introduced
in 10.8 are the ones you
should move forward to.
And in foundation, we have
some further NSURL improvements
beyond the ones I've talked
about including some built-in
character sets for URL handling.
NS metadata APIs and foundation
level attribute names you no
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
longer have to go
to CF level APIs
to get your spotlight
attribute names.
NSUser defaults suite--
whatever, I can't say that word.
If you have a bunch of related
applications and they want
to share defaults, these are the
APIs you would use, thank you.
And then also NSScanner has
support for unsigned long long.
So please refer to the
10.9 release notes.
And now, I want to just put
a reminder of some features
that have come and
I would have still.
If you haven't taken advantage
of these features
please consider doing so.
Some of these have
been around since 10.7.
In fact some earlier than that
and some were introduced
in 10.8.
But these are all great features
that will make your
applications more powerful,
more consistent,
more user-friendly.
So please freeze frame
this on your VCRs at home
and choose the features
you want to implement.
We have a lot of
related sessions.
I'm not going to go through
them, just highlight one here.
I've already put these up
in other slides but one
that I haven't talked about
is if you have an iOS App,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
you're thinking of
bring it to OS X.
We have session Thursday
morning, "Bringing your iOS Apps
to OS X" you might
want to go to that.
And with that, Jake Behrens
is our evangelist if you need
to talk to an evangelist.
And that's it, thank
you very much.
[Applause]