Transcript
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
[ Silence ]
[ Applause ]
>> Thank you.
Good morning.
I'm Ned Holbrook and this
is Session 223 Using Fonts
of Text Kit.
So let me give you an
overview of what we're going
to be talking about
during this session.
First we're going
to talk about how
to specify fonts in your app.
We're going to be
talking in particular
about the new Dynamic
Type technology in iOS 7.
We're going to be talking
about font descriptors.
We're going to be talking
about the techniques
for adding fonts to
your application.
And we're also going to be
talking about a couple of topics
that are going to be
particularly relevant
to developers of
multilingual applications.
Language tagging, a
new mechanism available
in both iOS X and iOS 7,
and modifying fallbacks,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
also available on
both platforms.
Now, some of the material for
specifying fonts is also going
to be relevant for OS X as well.
So if you manage to
straggle in with --
in hopes of hearing
something about OS X,
you came to the right place.
First, I'd like to
talk about Text Kit.
I hope you've gone to some
of the other sessions
introducing you
to this great new
technology available in iOS 7.
But since this Friday
morning after the beer bash,
let's have a quick review.
Text Kit is the great new text
framework based on Cocoa text
and brand new to iOS 7.
It allows you to get
amazing control and precision
when it comes to
typography in your app.
And what's most interesting
for this session is
that both Text Kit and
WebKit are built in Core Text
which is our low level unit
code layout engine available
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
on both iOS and OS X.
Now, Core Text is
still available to you
if you've been making
use of it in the past.
And in particular, we think it's
best for very specialized tasks.
In fact, there's one task
that it was built for
and that was enabling
the development
of higher level Text Kit --
text frameworks like Text Kit
and WebKit, maybe you've
even have to build your own.
But really when it comes
down to it, we encourage you
to use the highest level
framework available
that suits your needs.
And particularly with iOS 7,
we hope that will be Text Kit.
Now, no matter which
framework you're making use
of for advanced typography
in your app.
At the heart of it
all, we're dealing
with Unicode text layout.
Now, this is represented
by the equation String
plus Font equals Glyphs.
And when dealing with user
content, there's really only one
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
of those variables
that you have control
over and that's the font.
The string is likely going
to be the user's content.
But we're going to talk
about how you can choose
that font correctly in order
to get the best possible
display of text in your app.
So let's find out
how to do that.
Well you've got a number
of choices when it comes
to choosing a font
for use in your app.
The most exciting one
to me and I hope to you
as well is dynamic
type which is available
for the first time in iOS 7.
There's also the system font
that you are probably familiar
with and you may still may
need to make use of in iOS 7.
We're going to be talking
about UIFontDescriptor
which is the class I use to
identify fonts on the system.
And as I mentioned, we're
also going to talk about how
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
to bring your own apps to your
application or fonts, excuse me.
First, I'd like to
show you an example
of the new dynamic type
technology in iOS 7.
I hope you've seen some really
wonderful examples of this
in previous sessions, but
since I'm going to be talking
about some of the more
technical aspects,
so I thought I'd give you a
quick refresher of this as well.
Here we see the same Mailbox
presented in mail on iOS 7
in three different
content sizes.
Now, this is just three
out of a total of seven
that a user can choose from.
But I wanted to point out here
that on the left I
have the smallest size,
in the middle I have
the middle size,
and then on the right
we're looking
at the largest user
selectable dynamic type size.
So, as we can see, mail is a
very text heavy application.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
But it still has what
we'd like to display
as sort of hierarchy of type.
So, you'll note that there're
several different weights
of type visible in
this situation.
But you'll note that regardless
of the size of that type,
there's a very clear
relationship
between the different
pieces of text on screen.
And one of the great
things about dynamic type is
that it gives you the
tools you need in order
to present information
using the same types
of semantic distinctions in
the text, and we'll be talking
about exactly how to do that.
Note also that as the type size
changes, it's not all being fit
into the same size box.
Mail has a really great
dynamic type citizen
and it's actually
reacting to the size
of the user's preference
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and resizing the table
view cells to match.
So even though by its very
nature as the type gets larger,
the information density
decreases.
Mail itself is reacting to that
and responding to
the user's choice.
Note also that in
addition to the seven sizes
that are available, three
of which I've shown here,
there's also a switch that
can add a bit of weight
to those type styles,
and that's available via
accessibility settings.
So dynamic type is organized by
what we consider to be usage.
Each one of these is a text
style as we like to call it.
As you've seen in the previous
session, there are, I believe,
eight of these different
usage categories
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
for use with text styles.
These are things like
Body, Headline 1, Caption.
And every one of these different
text styles is optimized
for legibility.
We'll be showing you an example
of one of this in particular.
But, again, remember that
the user is responsible
for picking the size
of these text styles.
So, for any given text
style, you're going to see it
in a number of different sizes.
The metrics are going
to change based
on something that's
out of your control.
That is the user
is going to choose.
And so, of course,
we highly encourage
that you adopt auto layout
constraints for resizing your UI
to adapt to the user's content.
But even if you're
not doing that,
you may have some
other techniques.
You should be aware that these
metrics are going to change.
And as I'm sure you've
already seen Interface Builder
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
with Xcode 5 has a great
support for these text styles,
so you can specify
them right in line
where you're designing
your user interface.
Now, let's take a look at one of
these text styles in particular.
On the slide, I've chosen one
of the subhead text styles
and what I have here is what's
called the waterfall chart
which is simply the same
sample text set in all
of the different user
selectable sizes.
Now, you don't have to
be a typographer to see
that this text is
clearly related,
all these different sizes
probably meaning the same thing.
But again, not just sizes.
We have a type system involved
where this particular text style
subhead is related visually
to the other text styles and
so one of these in conjunction
with other text styles
allows you to present a very,
very rich information hierarchy.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
You'll also note that this
particular text style --
all these different sizes
have a very consistent --
what typographers call color.
But let's zoom in and take a
look at what I mean when I say
that these are optimized
for legibility.
So, we're going take
a look at the smallest
and the largest text
styles sizes zoomed
in to the same point size.
And here I've taken the liberty
of annotating the white space
in this example to show you that
besides having different weights
of type in this particular
example,
we've also adjusted
the letter spacing
because a smaller text needs
more room to breathe in order
for us to ingest it
with our brains and eyes
to really dig into the context.
These sizes adjust
both the letter spacing
and also the line spacing
which is hard to show
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
on this particular example.
But -- So, if you can
consider that we have this grid
of these different sizes,
these different styles,
there's really a huge amount
of design effort that went
into these typefaces
and the great part is
that they're all
available to you.
So in order to make use of these
text styles, this huge amount
of design for this
beautiful type,
you'll probably been making use
of UIFont
preferredFontForTextStyle
which is a class
factory method on UIFont
that takes a single
argument which is one
of those text style identifiers
that you can find
in UIFontDescriptor.
Besides the base text
style categories,
you can also make
some changes to those
by modifying them
with symbolic traits.
So the ones in particular
that you're likely
to find useful are Bold, Italic,
and we also have special traits
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
for adjusting the line spacing.
So depending on the content
being presented, you may be able
to tighten the line spacing
a bit if you're dealing
with say a single label.
Or for longer line lengths,
you may find it necessary
to actually loosen the line
spacing to give a bit more
of that white space that's
needed for best legibility,
and we'll be showing
you an example of how
to do that in code shortly.
Note also that all of this
amazing technology is available
in CSS as well.
One of the earlier sessions,
the Intro to Text Kit Session
and you may have also heard
in the WebKit session,
there are properties
corresponding to each one
of these type styles -- text
styles, they're prefixed
with -apple-system, and
so you can find the list
of those elsewhere, but --
so if any part of your UI is
still built using a WebView,
that's all right.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
That's great.
You can still access
this great technology.
Now, text styles are part of a
larger category of fonts that I
like to think of as
being sort of a metafont.
So, you'll note that with
text styles in particular,
as you may have seen in that
example, I know that the weight
of the type was actually
changing in response
to the user preference.
And so naturally, you can assume
that for a given text style,
the actual font that's
used to render that text
to screen may not be the
same in all situations.
And so, we've also
seen this on OS X
where Mavericks brings a new
system UIFont that's optimized
for Retina Displays.
And so, as OS X developers,
those of you in the audience
who have done programming
in OS X, you may be familiar
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
with the various NSFont class
factory methods for getting
at what I would consider
to be this system font,
this semantic notions
of what a font may be.
You may have seen menu font
of size, control font of size,
these types of things.
But, many of you may
have also noticed
that in the past whenever
you used one of these,
you typically got back the same
thing every time, Lucida Grande.
And so you may have said, "well,
you know, I mean this is great,
but I know it's just
going to end
up being the same
thing in the end.
So I may as well just
specify that in my code
or in my zeb [phonetic]
or whatever".
But by doing so, you lose the
ability to adapt to improvements
that are made in the
system font technologies.
You'll note that this is
particularly so when it comes
to text styles because
it's not just
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
that the font may be changing
across releases, they're going
to be changing dynamically
and in the Intro
to Text Kit Session, you saw how
to adapt to that dynamically.
But one thing that's shared
with all of these fonts is
that when you poke around, you
may end up seeing font names
that start with a period.
And, as we all know from
our grand UNIX history,
something that begins with a
period is not meant to be seen.
And so when you're dealing
with these system fonts,
if you find one of these, that's
a sign to you, the developer,
that not only are you not
be presenting those names
to the user directly,
but it's also a note
that there's magic involved.
And so really you should
be dealing with these
by identifying these system
fonts using their semantic
identifiers, this class factory
methods, these text styles.
And never -- would it be
appropriate to drop down
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and grab a CD font and deal
with that moving onwards.
So, UIFont does have one of
these class factory methods
that you've seen
before, systemFontOfSize,
also Bold and Italic variants.
But this is -- there's
a clear distinction
to be made now in iOS 7.
The system font is not meant
to be used for user content,
that's what text styles are for.
And in addition, only if
you recompiled your app
for iOS 7 will that
system font be adopting any
of the new improvements
made to the typography.
So, keep this in mind when
you're designing your app
and your users will thank you.
So UIFontDescriptor or -- also a
very similar technology on OS X,
NSFont Descriptor, is the class
that we use for describing
fonts.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
It's a very, very
lightweight mechanism.
It doesn't involve spooling up
any rendering system in order
to have an actual font on hand.
It's simply the mechanism we
use for getting up that font.
It allows you to access
and in some cases
modify font properties.
We'll be showing
you that as well.
UIFontDescriptor is the
base technology for finding
out what fonts are
available to your app
and it's also the mechanism
by which you can
specify your own fonts
if you've licensed them for
use in your user interface.
So the way we use a descriptor
is by noting that it looks a lot
like a dictionary
with key value pairs.
In this case, those key
value pairs are called
font attributes.
They correspond to any number
of particular properties
that fonts have.
It bears the names, the size,
what typographic
features might be enabled.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And you'll note that using
a descriptor, it's very easy
to create one for a
font that doesn't exist.
For instance, I could use
a descriptor to specify
that I want a font that's
in the Helvetica family
and that its style is purp --
well, until type designers sort
of embrace their
synesthetic side when it comes
to designing fonts,
I doubt we're going
to see purple being a
commonly use style for a font.
But, we're going to need
a mechanism for finding
out whether or not these
descriptors correspond
to actual fonts in the system,
and then the mechanism we use
for that is called matching.
So there's two types of
descriptor matching when we want
to take an abstract
descriptor and turn
into something more concrete,
that is something that's
based on the real font.
And the first is
explicit matching.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
You can invoke
matchingFontDescriptors
WithMandatoryKeys
on a descriptor.
And you'll get back an
array of potentially many --
potentially no font descriptors
that correspond to fonts
that are actually
available to your application
at the time of that call.
There're also various methods
that perform this matching
on your behalf and so this I
like to consider
implicit matching.
So, for instance,
fontDescriptorWithSymbolicTraits
which we'll have a code
example of in just a moment,
when you invoke this method,
it will be using
matchingFontDescriptors
WithMandatoryKeys under the hood
and so the results you get
back will correspond to fonts
that are actually available,
and so in that sense,
it's being done implicitly
on your behalf.
In addition, you
can create a font
from a descriptor directly
because, of course, when we want
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
to materialize that
descriptor into a font,
we need to have something
to use in that case.
And so this method will also
perform matching on your behalf
but it also means that if
you didn't explicitly make
that match before hand, it might
not be exactly what you expected
due to having specified a
font that doesn't exist.
So let's go ahead
and make a match.
On this code example, I'm
creating a UIFrontDescriptor
from a dictionary
of font attributes.
In this case, I'm specifying the
family attribute with the value
of Helvetica Neue, and I want
to see what's available to me.
So, as I mentioned, I invoked
matchingFontDescriptors
WithMandatoryKeys.
In this case, I'm
going to pass nill.
This is the most common
situation, passing nill means
to use all of the keys,
all of the font attributes
in the dictionary
when considering what
constitutes a match.
But if you would like to only
consider certain attributes
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
in the font descriptor, you
can use the mandatory keys
to narrow that down.
But, as I mentioned,
in most cases,
we'll just be passing
nill to use all.
If I run this on iOS 7,
I'll get back an array
with the number descriptors, 14,
I believe, for various members
of the Helvetica Neue family.
I mentioned also that
we can use descriptors
to modify text styles
and other fonts as well.
So in this case, I'd like to
get at a Bold body text style
and there's no category,
no constant for specifying
a Bold body text style,
but I can apply the
Bold symbolic trait
to the standard body text style
if I need some emphasis
in my body text.
In this particular example,
since I'm not starting
from a UIFont, I don't need to
spend everything up just to get
at a font -- just to get another
font, so I'm going to start
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
by getting a UIFontDescriptor
using preferredFontDescriptor
WithTextStyle.
I'm passing in the
relevant constant,
in this case, text style body.
And then we're going
to modify it
with the symbolic
trait for Bold.
In this case, I know
that there's going
to be Bold variant available
but, again, if there's --
if I were using a different font
and they weren't a Bold
style available to me,
then I would be left with
the original descriptor,
but that's OK because
then I'll go ahead
and create the relevant font, in
this case, from that descriptor.
You'll note also that
the size parameter
that I'm passing in is zero.
And that indicates that
when using the descriptor,
I'd like to not override the
size that it itself specified.
So, in this case, zero
simply means don't change.
And now I have my Bold text
style for use in bodies.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Descriptors are also
the preferred mechanism
for serializing font data.
So, of course, from a font
descriptor, we can coerce
to a font and for
any given font,
we can get a font
descriptor that describes it.
So this is relevant when
we have a font that we'd
like to serialize, we'll
use this descriptor.
This is very easy since
font descriptors can form
to the UI -- to the
NSCoding protocol,
but you may have a
mechanism for archiving
and unarchiving objects
that doesn't use NSCoding.
In this case, you should
be accessing the dictionary
of font attributes
on a descriptor.
But note that because of all
of the various possibilities
when describing fonts,
you should be using those
attributes as an atomic entity.
You shouldn't be trying to pick
various attributes out of it
and assume that that's going to
be able to reconstitute a font
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
on the other end, so
just use all of these
and serialize them as necessary.
Descriptors can also be used
to modify font instances.
Now, when I say modify, it don't
mean that you're able to go in
and change the font
data on disk.
But what you can do is
change the behavior of a font
when you make use
of it in your app.
Two examples in particular
that we're going to see are how
to activate typographic
features and how
to remove unwanted characters
to limit the character
coverage of a font.
So, as I mentioned
earlier, of course,
String plus Font equals
Glyphs, Unicode text layout.
Well one of the neat
things about fonts is
that they can often implement
special features that modify
that process in somehow
and these features are
called typographic features,
and in this particular example,
I have a font where normally
when I layout text using this
font, I get one appearance
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
as you can see on the top here.
It says 11:15.
And you'll note that even
though this particular font, 12,
you can't really see it, but
this font is a proportional font
that is it's not monospaced,
different characters
have different widths.
You'll note that the
digits in this font,
they're all monospaced, the
ones the same width as the five.
And this is a very common design
that you'll see from fonts
because it makes it easy to
line up figures in columns,
but I'm no accountant and
I know that in this case,
this particular string
means that I'm trying
to display a font --
a time to the user,
let's say for time stamp
in a table that I have data
that I'd like to present.
And so I've been
told by my designer
that this particular font
has typographic features
that allow me to apply
a time appearance to it.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And one of those is one that I
can use in other cases as well
and that's to make these
digits proportional.
And so in this particular
example,
you can see very clearly how the
ones now have a narrower width
and since I'm dealing with
time, this font, I've been told,
has another great
feature that I can use
and that's an alternate
set of glyphs.
In this case, the alternate
set includes a different colon
that clearly looks
like a time separator.
Rather than being rectangular,
you can see that it's circular
and it's brought up
off the baseline a bit.
So -- And this is
what I'd like to use,
how can I do this in code?
Well, first I'd like to build
up an array of feature settings.
So feature settings are
these -- are the identifiers,
the handles onto these
typographic features
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
that can be implemented
by a font
and you can programatically
query the fonts to find
out what's available,
but in this case,
I've been told specifically
which ones I need to use.
I'm using the Objective-C
literal syntax for doing that,
and so if we unpack this,
you can see it's an array
of two dictionaries and each
of those dictionaries is
specifying both the type
and a selector as the key
and the values are relevant
to those particular
features that I'm trying
to enable on this font.
So, the first one you can see,
it's very clearly
described number spacing type
which is kind of a
grouping of features
and then the proportional
numbers is what I'm going
to be enabling.
And this other one, this
character alternatives,
you'll note this pesky little
magic value, magic constant 1.
Well, so there are a number of
predefined typographic features,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
names that we've given
because we have seen them
in so many fonts, but remember
that typographic features are
kind of like an API to a font.
And so a font is free to define
its own typographic features
and that's exactly what
this font has done.
It's defined a particular
selector
in that character
alternatives type of 1.
And so if that font came with
a header, somehow we could,
you know, give it
a magic cons --
maybe we'll give it
a name in your code
so we know what's going
on, but in this case,
our designer has told
us this is how to enable
that particular change
that you'd like to make
in the appearance of the glyphs.
So once we have that
array of feature settings,
what we're going to do
is we're going to assume
that we've started with the
font already, that original font
in the original appearance
that you saw in the example.
We're going to get
its descriptor.
Now, we're going to
create a new descriptor
by modifying the
original descriptor
by adding attributes to it.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
In this case, there's
just one attribute,
it's the feature settings
attribute and the value
for that is going to be the
array of feature settings
that we defined above.
And then finally, we're going to
say, UIFont, fontWithDescriptor.
We're going to pass that
descriptor that we just created
with those feature settings.
Again, we're going to
pass zero for the size,
meaning don't change it.
And so now, the only difference
between the original font
and time font that we've
made here is it's going
to be the same font but it has
these new features enabled.
And so the font gets
to participate
in that glyph selection process
and during layout it will say,
"oh, I know exactly
what you want
for those ones and that colon.
I know you want this
other glyphs instead."
And these feature settings can
be quite amazingly powerful.
Not only can they change
which glyphs are selected
for certain characters, but they
can also change the interaction
between various glyphs,
ligatures are a great
example of this.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So another example,
as I mentioned,
is limiting the character
coverage of the font.
So, I've got this
really great app.
It's kind of technical and so
I think Menlo is a great choice
of a font for my --
presenting my user's content.
And as I'm sure it happens
to you a lot -- I --
so many at my documents include
the Unicode snowman character,
of course.
You know, again, I think
I've picked the right font
for this particular
very specialized app,
but I don't know about you, but
I think it's kind of a bit early
in the morning for Menlo
snowman, he's just too happy.
So really what I'd like to
do is I want to use Menlo,
but I don't want to
ever see Menlo snowman.
And so I want to create
a font instance that acts
as if it doesn't
even exist and I'd
like to just let the system
pick a different font,
follow back to different font
whenever it sees a snowman.
Anything will be
better right now.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So I mentioned earlier
in passing
that UIFontDescriptor can be
used to access font properties.
And so in this example,
I am going to be ultimately
creating a new descriptor
by modifying an existing one,
but the value of the attribute
that I'm going to be modifying.
First, I want to get from
my original descriptor.
Let me show you how that works.
So, again, we're going to
assume that we have our font,
in this case, in
the example I gave,
it's going to be
a font for Menlo.
We're going to get
this descriptor again,
the original descriptor.
Now, in order to compute what
its character set is going
to be, first we're going to
get its original character set
by invoking object for key
on the original descriptor
getting the character set.
We're going to mutate that by
removing that one character,
just that one snowman character.
And so now we have a character
set which is exactly identical
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
to the original font's character
set minus that one character.
And then just as before, we're
going to make a new descriptor
by adding an attribute and the
nice thing about this method is
that it's defined as using the
new values to override anything
that is already in the font.
So there is no conflict here.
It's going to know that this new
character set attribute is going
to be the one that I want
and when I create a font
with that descriptor -- now
whenever I use that font
in my app, it will use Menlo
for all the text except
that snowman character and in
that case the font subsystem is
going to pick up fallback fonts
to use that to run to
that character instead.
So there're also some
great opportunities for you
to bring your own fonts to
your designs, your app design,
and this goes not
only for iOS but also
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
for OS X Mavericks as well.
So, if you're design
includes something custom,
this is how we'll make it work.
So bringing your own font
to the table is pretty easy.
We've got lots of options.
So when you're talking to
your designers or the foundry
from what you're going
to license your font,
they may ask you some
of these questions.
And so, these are the answers
you're going to need to know.
We support both -- two type,
an OpenType font containers,
both individual fonts and
as collections and in terms
of the layout information in
those fonts, we support both AAT
and OpenType layout information.
So, really, you shouldn't
have any problem being able
to get the font in a
format that we can support.
And then in order to make use
of that, it's very simple,
you simply place
in your app bundle
because that's how your
resources are bundled.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And then the system can
automatically make those
available to your app on iOS
by using the UIAppFonts
Info.plist key
to specify the location on
those fonts and your bundle.
There's also a corresponding
Info.plist key with us,
different name on OS X, but
you may find, and I should say
that once you've
done this, it's --
it acts like any other font
that was previously
installed in the system.
So you can say, "UIFont
fontWithName and the name
of that font that you've
added and there will be.
But we found in some cases
that for various reasons,
this isn't what you want to use.
And some cases, we found that
foundries asked the developers
like you, you know, not have
their fonts just sitting
on unencumbered in
the app bundle
to prevent casual snooping.
And so in these cases,
you might want
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
to have [inaudible] the font
data in some way and in fact,
we have code example
available online
for how you might
accomplish this on your app.
But once you've done
that, of course,
the system can no
longer automatically make
that font available to
you, and so you may need
to add that font manually.
There're two different types --
there're two different ways
in which you can do that.
The first is by adding the font
as what we call a
registered font.
Using one of these
CT font manager APIs,
you can specify the location
of font data to be referenced
by name after it's been added.
These registered fonts, again,
behave just as if they had been
in your app bundle and
activated automatically,
so you just referenced
them by name.
There's another way in which
you can add fonts however
in which they're unregistered.
In this case, the font's
names can never be matched.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And you might say, "well,
how was that even useful?"
Well, it's really great actually
because what you get back
from these CT font manager
APIs are new font descriptors.
Now, of course, these
are CT font descriptors,
cortex font descriptors, but
they are toll-free bridged
with UIFontDescriptor on iOS.
So, just a little bit of
casting is all you're going
to need to make this work.
Once you have one of these
descriptors, of course,
we've seen several times now
how you can create a font
from a descriptor, and that's
exactly what you can do
with these.
So even though you can't say
font with name, your fonts name
and get back the fonts.
In this case, you can
create a font directly
from a font descriptor.
This could also be
helpful for instance
if you license a
particular version of a font
that already exists
on the system.
And so, if you for some
reason has special layout
considerations and need to
use your own copy of one
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
of our fonts, this is a great
way to make that happen.
Now, for making it this far in
the conference, in the session,
we'd like to show you
another little surprise here.
So in iOS 7 -- well,
iOS in general,
we've long had the problem
where on OS X, we have a bunch
of really amazing
beautiful fonts.
But until we can get that shrink
ray working, it's really hard
to squeeze a terabyte of storage
into a little phone that goes
in your pocket and so many of
these fonts we've had to leave
out of iOS because there's
just not enough room.
But there are cases when you
might know that you just need
to use a particular font.
And so, what we've done for iOS
7 is we've made a huge number
of fonts available to you.
We've licensed and hosted these
so that you can make
use of them.
These include literally
hundreds of fonts,
all of the fonts installed in
OS X as well as additional fonts
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
for particular support
of international scripts.
And the way -- thank
you [applause].
So the way you take
advantage of this is
by using a very long
API CTFontDescriptor
CreateMatchingFont
DescriptorsWithProgressHandler.
And really, what this is,
is it's a very special type
of descriptor matching.
So we've talked about
this already
and before we saw how
simple it was to match
on a descriptor and
get the results.
Well, with downloadable
fonts of course,
were at the mercy
of the network.
And so essentially what this is
API let's you do is it lets you
perform that descriptor
matching asynchronously.
And so the progress handler
is a block that you pass
in that gets called to handle
the various states during
the download.
And so what this means is that
in order to make effective use
of these downloadable fonts,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
your app will probably have the
design some UI to allow the user
to recover from various
failure states.
But with that in
mind, it's very simple
to query fonts are available
via this download mechanism
by matching on the
downloadable attribute.
And we'll also be
publishing a list
of those fonts online as well.
So, to make use of
one these fonts, I --
your app can simply download it
and then the user's
content is available
in that particular app.
Note also that with iOS 7,
fonts can be installed
by managed profiles.
This could be great if you're
in an enterprise
distribution scenario
and you have multiple
apps that you want
to conform to a house style.
And so, those fonts can be
included in the profiles
and activated in that way.
Note however that this is
the first time in which fonts
on iOS can change while
your app is running.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And so, if you'd like to react
to fonts becoming
available via a profile,
you'll want to subscribe
to the registered fonts
changed notification
so that you can react
when that happens.
So, as I've been talking,
we've been focusing
on Unicode text layout.
And Unicode is really
an amazing specification
because it allows us to
communicate using nearly any
of the world's languages on a
computer which is no small task.
But one of the sort of
problems with Unicode is for --
in certain situations, the
characters themselves --
we know that they can take
on different appearances
via the font
but there're also situations in
which the appropriate appearance
of that character is
dictated by the language.
That is its information that the
user has that isn't reflected
in the text, can't be.
And so, the system by default
does the very best job it can
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
in resolving these scenarios.
Typically, it does
solve by looking
at the user's preferred
language.
So, if the user is using
her phone in Japanese,
in the text appearing
in Japanese,
the system will select
appropriate Japanese behaviors
for text.
But there are cases in which you
or your content may know more
about what the appropriate
language is and the mechanism
for doing that is
by language tagging.
So, there's -- on
Mavericks and iOS 7,
there's a new string
attribute that allows you
to specify the language
as an ISO language tag.
And the presence of this
attribute indicates that,
that particular language
should be used
to override the default system
behavior in various ways.
You're going to be looking
at glyph substitution,
line breaking, and
font fallbacks.
So the first example is
one that's kind of --
may not be a particularly useful
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
because this relies
on a particular font.
But this is another example
of how fonts can participate
in the layout process.
In this case, I'm going to be
displaying a particular string
with two very specific Unicode
characters and I'm going
to be showing you the appearance
of that string when laid
out using one of two
different languages
that I've tagged
the string with.
In the case where I specified
English as the language,
we'll get, for these characters,
their default appearance
which you can see kind of looks
like a little hook or tail
on the bottom of each of
these, the S and the T.
But what's interesting
about these characters is
that when use for Romanian
text, they actually take
on a different appearance.
In this font, Verdana, actually
implements that appearance.
And so if I specified that
language as being Romanian,
you'll see that rather than
having a little hook or tail
on each of those glyphs,
we have what looks more
like a comma or a stroke.
And this is great as a
feature because it allows fonts
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
to be more responsive
to the user's languages.
Another way in which language
tagging can affect the behavior
of text is in line breaking.
So here we have an example
where I have a Japanese string.
You'll note that I've asked to
lay this out in the space up to
that dotted red line
on the right there.
And you'll note that when
I'm doing so in the context
of an English user, the line
break position is actually
different than for Japanese.
That's because in the
absence of any information
about Japanese --
the Japanese text,
the system uses the default
Unicode character properties
which isn't really
appropriate for Japanese text.
Now, again, as I mentioned
earlier, if the user is running
with Japanese as their
primary language,
they'll get the correct
behavior by defaults
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
but you may be writing
an app in which you know
that text should always have --
should always be
treated as Japanese text.
Maybe you're writing
a dictionary app
or maybe the content is
being specified using HTML
and tagged as Japanese.
And so in these cases, the
system can adapt accordingly.
And one of the most common
examples when dealing
with this quirk of Unicode
is for languages like Chinese
and Japanese where many
of the characters actually
overlap in Unicode.
They can have the same character
but different appearances.
In this particular example, we
have a very obvious difference
of appearance when we're dealing
with either Japanese or Chinese
as the language for this
particular character.
So in this case, what the
system actually does is --
note that I haven't specified
a font on my attributed string
and so this is going to
immediately trigger fallback
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
which is the process
of finding a font
that can actually
render that character.
And by specifying the
language attribute,
I've told the system
exactly what it needs to know
to make the right choice,
not just a good choice
but the right choice.
And in this case, it's going
to select one font for Japanese
and a different font
completely for Chinese.
So beside the appearance
of just this one character
in a real world situation,
the user would notice
that there're other
stylistic differences
or even other glyph differences
between those two fonts
and so this can be
done automatically.
So on that note, I'd like to
talk about one other technique
for changing the behavior
of fallbacks and that's
by making use of a
custom cascade list.
We've seen how an
app can tag a string
with the appropriate language to
get language specific behavior
but there are other cases beyond
just that when we might want
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
to make a change to
the fallback behavior.
The cascade list attribute is
a font descriptor attribute
that you can add that allows
you to specify an array
of font descriptors that will
be used before the default list
when performing fallbacks.
So, what does that mean?
Well -- so remember, I mentioned
that the system has
a default behavior
that works as best it can.
But in this case, you have
the flexibility and the power
to insert something that's going
to be checked before that list.
So let's take a look an
example to try to clarify this.
So let's say I'm marking
on an Arabic dictionary app
and I have a -- I've specified
a really great font in my design
for the English headwords but
the behavior I'm seeing is
that when the text system
encounters the Arabic characters
in that string, they're
falling back --
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
the fallback font
that's selected
to render those characters
is Geeza Pro.
Now, some people will call
Geeza Pro time tested.
Others would call it
long in the tooth.
But more importantly, I think
what's important to note here is
that Arabic is a writing system
with a very rich
calligraphic history
and so there are a
number of different styles
in which I could expect
this text to appear
and Geeza Pro is just
obviously one style.
So what I've done is I've
licensed a really beautiful
Arabic font for use in
my dictionary and I'd
like the system to
manage the transition
between those fonts
automatically.
And so what I'd like instead is
when I specified my original
font from my headwords,
I'd like to let the system
take care of the fallback
by overriding the default
behavior, not going to Geeza Pro
and selecting my font instead.
So in order to do
that, I'm going to want
to specify my own cascade list.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So I've got a font descriptor.
We'll, assuming that I've
constructed font descriptor
for my licensed Arabic
font and then I'm going
to build a cascade list which is
pretty simple using Objective-C
literal syntax, I'm just
going to have an array
with this single
object and that's going
to be that descriptor.
I'll assume that I have my
font for my English text.
Again, like we've seen before,
I'm going to get the original
descriptor and I'm going
to create a new descriptor
by adding my cascade list
attribute to that descriptor.
Now, whenever I make use
of the font that I can make
from that descriptor,
what will happen is --
I know that this font doesn't
support Arabic characters.
And so whenever the string
contains those characters,
the system is going to need
to consult the fallback
to find an appropriate
font to render that.
And so, this cascade list --
since I know this covers Arabic
characters, it'll be used rather
than the default fallback
which is Geeza Pro.
So, you may note also that this
particular example could be
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
quite powerful when combined
with a previous example
of modifying the character set.
And so they're depending
on the needs of your app.
You may even be able to
combine the various techniques
that I've shown you for
a very precise control
of the fallback behavior.
For more information, there
are various resources available
to you.
There are a couple of
sessions that are available
on instant replay to you and I
encourage you to review those
because there're some really
fascinating concepts in there
as well as several of
the design sessions
on designing your user
interface for iOS 7
because that will give you I
think some really great ideas
for adapting text
style in your apps.
And I, as a user,
I'm really excited
to see what you guys
can come up with.
In summary, I just like
to drive home a couple
of points one more time.
The first is to -- in
order to adapt dynamic type
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
in your iOS 7 app, you'll
do so using text styles.
Remember that this is -- this
requires a bit of flexibility
on your part in order
to adapt appropriately
to the user's desired
content size.
So please investigate using
auto layout but keep in mind
that those font metrics
are going
to change based on
user preference.
For developers in
multilingual situations,
language tagging is a great
feature that allows you
to specify language
sensitive behavior.
And what's really great
about it is that --
in those examples I showed you,
that attribute will flow right
up to your Text Kit and
you'll get perfect behavior.
For various specific
needs involving fallbacks,
you can influence the
systems fallback behavior
by adding a cascade descriptor.
Remember also that
profiles can install fonts
and so this is a new tool
available to you as well
and those fonts are
available systemwide.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So with that, I'd like to say
thank you very much for coming
to hear about fonts and Text
Kit and a little bit of OS X.
Thank you very much.
Enjoy the rest of
the conference.
[ Applause ]