Transcript
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
[ Silence ]
>> Welcome to Accessibility
in iOS.
My name is Sam White, I am one
of the iOS Accessibility
Engineers here at Apple.
Today, I want to talk to you
about developing great
applications for everyone.
And I want to show you how to do
that by implementing
a little bit
of Accessibility in
your applications.
So before we get
started, what do we mean
when we say Accessibility
in this context?
Well, in iOS, Accessibility
is really
about supporting different
abilities and more broadly
than that, supporting
different users.
So, if you look at the
iPad and the iPhone,
you see these amazing
devices, you know, they help--
they let you communicate
with your friends,
watch movies, browse
the internet.
But the user experience of these
devices is very much one size
fits all.
And so, if we look at, you know,
two users of these devices,
no two users are
the same, you know,
so this is the problem we have.
And more specifically,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
no two users have the exact
same abilities so this is
where Accessibility
comes in on iOS.
Accessibility is the thin
layer that sits between you
and your device and it
transforms your input
into something more appropriate
for the device and similarly,
it transforms the
device's output
into something more
appropriate for you.
So today's talk is broken
into two main parts,
I'm going to start by giving
you a brief introduction to some
of the Accessibility
features that we offer on iOS.
And this should give you an idea
of how users will experience
your accessible application.
And while we're at
it, I'm really excited
to say we're adding a brand new
Accessibility feature in iOS 7
so I'm really excited
to show you that.
And then for the remainder
of our time and really,
the bulk of the talk,
we're going to be doing some
Accessibility development.
So, I've brought an
application with me
that has some Accessibility
issues.
So, we're going to fix
them kind of from--
starting with the most
basic, working our way
up to the advanced
issues then I'm going
to use some brand new
API on this application
that we've added in this release
to do some really cool stuff
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
that was never before
possible and it's going
to let you do some cool
stuff in your applications.
And then, we're going to
wrap up the day by looking
at some brand new
API we've added
to Guided Access
in this release.
And I'm going to show you
how you can use that API
to really customize
the user experience
of your application on the fly.
So, iOS Accessibility features.
One of our most powerful
features is called VoiceOver
and VoiceOver is a screen reader
application that lets blind
and low vision users
use iOS in the same way
that everyone else does.
And so, VoiceOver works
by intercepting all touch
and Multi-Touch gestures and
transforming those into commands
that drive a cursor
around the screen,
the cursor you see
in this image.
And so, what that does
is it allows a blind
or low vision user to explore
an interface and have it spoken
to them to learn about it before
they chose to interact with it.
We also added a feature in
iOS 6 called Guided Access.
So we introduce Guided
Access to deal
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
with the problem
of distractions.
So if we return to, looking
at the iPhone and the iPad,
we realized these devices
have a great number
of distractions associated
with them.
If we look at the hardware,
they have many hardware buttons,
you know, volume
buttons, lock buttons
and the interface itself
responds to, you know,
a variety of touch and
Multi-Touch gestures.
And what this means is, if
you're a user who, you know,
maybe has trouble
focusing or a child,
these distractions can
really get in your way.
And so, what Guided Access does
is it gives you a setup screen
that allows you to remove many
of these distractions
on a per app basis.
So, you can really focus in on
exactly the content you want to.
Also in iOS 6, we added Made
for iPhone hearing aids.
And so, Made for iPhone hearing
aids let you control your
hearing aids right
from your iOS device
which you likely
already have with you.
And so, this let you do
things like adjust the volume
or adjust the balance
between your hearing aids
if you have more than one.
I mean it even lets
you quickly select
from multiple audiologist
tuned presets that you have
in your hearing aid
and on your device.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So, if you walk into say a noisy
environment like a restaurant,
you know, you can quickly
change your hearing aid
to an equalizer setting
more appropriate
for that environment.
And similarly, maybe if
you walk into a movie,
a very quiet environment, you
can again pull out your iPhone
and quickly choose a
preset more appropriate
for that environment.
And the last Accessibility
feature,
I wanted to give you kind
of a brief introduction
to today is called
Assistive Touch.
So, we added a Assistive
Touch to iOS in iOS 5.
And really, the goal of
Assistive Touch is to help users
with physical and mobility
impairments perform the complex
Multi-Touch gestures and
hardware button presses
that are really necessarily
to use iOS effectively.
And so, Assistive
Touch does this
by giving you a single
on-screen menu
that contains all these gestures
and hardware button options.
And can be activated
by just a single touch.
And also, Assistive Touch can
be driven using an external
Accessibility device
such as a joystick.
So, I want to return
to this idea
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
of supporting different
abilities
with Accessibility for a moment.
Now that we've seen some
of the more visible
Accessibility features,
this starts to make
sense, right?
We introduced Guided Access to
offer some cognitive support,
we have VoiceOver that
offers visual support
and so the question arises,
you know, where do we go next?
Over the years, we've built
up a pretty rich
Accessibility environment on iOS
and it's really second to none.
And so, to answer that
question of where we go next,
I want to explain the picture
you see in front of you.
And what you're seeing is
what's known as a Switch User
and switch software is designed
to allow a user to interface
with the computing device
using just a single switch.
And so, this is accomplish
by scanning
through the interface
automatically and listening
for those switch presses
from a user, you know,
when the thing they are
interested in, you know,
becomes selected via
the scanning process.
And so, as you may have guessed,
I'm really excited to say
that we've worked really
hard, you know, day and night
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and we've gone ahead and baked
a complete switch software
solution right into
iOS in this release.
And so rather than talk
about it, you know,
a picture is worth
a thousand words,
I'd love to just give you
a quick demo right now.
As with all of our Accessibility
features, you can find them
by opening up the Settings
application, go into General
and then to Accessibility.
And so, as I mentioned before,
you can see that the
Accessibility features
on iOS are really
grouped by needs.
So, we see the vision
heading followed
by the vision related
Accessibility features,
similarly hearing
and hearing features.
And if we scroll all the way
down, we see physical and motor
and that's where
switch control lives.
And so, before I turn it on, I
just want to scroll down a bit
and give you an idea of how
customizable this feature is.
Again, we think it's really
important for each user
to be able to tune this feature
to really meet their abilities
and work with-- work
well with them.
And so again, we've built
in an incredible amount
of customization here so users
can really set it up in a way
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
that works well for them.
And so, if I go ahead and
turn Switch control on,
you can see a cursor that begins
scanning through the interface.
And so, this in itself
is pretty amazing, right?
If you've seen Switch
software before, usually,
the solution is to, you know,
drive-- if you're on a desktop,
it's to drive a mouse
cursor around the interface.
And, you know, if
you're on mobile device,
maybe you drive some false
finger around the interface.
But because of your help in
years passed and, you know,
our work on the OS end, we've
already marked up the interfaces
with this great Accessibility
API.
And so, we can just jump
in and leverage to that API
and build this feature
on top of it
because we know these
elements exist.
And so, that's how we were able
to build an element
scanning switch solution.
And so now, this
cursor is scanning
through the interface
waiting for switch presses.
And so, ahead of
time, I've gone ahead
and paired my external Bluetooth
switch with this device
and right out-- right
off the bat,
we're supporting a large
number of external switches
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
that will work for you.
And so, as this cursor scans the
interface, I wait for, you know,
what I'm interested
in to be selected,
and then I can press my switch
to bring up a context menu.
And so if I bring up the
context menu here, you can see,
I'm presented with options
that are appropriate
for this element.
And in this case, I'm
just going to wait
until the Home button group
becomes selected and I'm going
to drill into it with
a single switch press.
And then again, press
right on the Home button
and you can see it's
the equivalent
of just pressing the
Home button yourself.
And so, let's say we want
to take a look at, you know,
how Apple stock is doing today.
And so again, we'll just wait
until the group with stocks
in it is selected and there
it is and now, I'll just wait
for stocks to be
highlighted and press again.
And again, you can see
this context menu pops
up with anything I might
be interested in, you know,
for this element, anything
this element responds to.
And so, I'm going to wait
until touch is selected
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and maybe I want to see
the graph associated
with Apple stock.
And so again, I'm going to
walk down to the Apple stock
and use touch to drill in.
I can see how you get the
graph related to Apple stock.
And so again, this is a
really powerful feature
and we think it's going to open
up iOS to a whole new group
of users and we're really
excited to get it in your hands
and to get feedback from you.
And so, that's Switch control.
OK. So as I said before,
the rest of today,
we're really just going to
dive in and do some development
and fix some Accessibility
problems.
So before we do that, I want to
give you a brief introduction
to how UIAccessibility
works under the hood to try
and give you a better
understanding of that process.
After that, we're going to
do an Accessibility audit
of the application I brought
today and this will allow us
to quickly find any
Accessibility issues we have
in our application so we
can kind of get a game plan
of how we're going to fix them.
And then once we've
identified these bugs,
we're going to use the
UIAccessibility API
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
to fix them again, you know,
starting with the most basic
and we'll see how far we can
get just using those basic
Accessibility attributes.
And then we'll work up to
some more advanced problems,
use a little bit
of advanced API.
And again, the brand
new API is going
to let us do some some cool
stuff that we're excited to see
where you guys take that
and then we'll finish
up by looking at Guided Access.
So, how does UIAccessibility
work?
The easiest way to
explain this is to look
at an Accessibility
feature in action.
So here, you can see
VoiceOver is on the far left,
the Calculator application
is on the far right,
and we see UIAccessibility
in the center tied
to the UIKit stack as it is.
And so, as I said before,
when VoiceOver is on,
it is intercepting
all of the touch
and Multi-Touch gestures
on the screen.
And what it's doing when
it intercepts those is it's
transforming them into questions
that it can ask your application
using UIAccessibility.
And so, if a user were to
touch on a Calculator app say
in the center of the screen,
VoiceOver then internally,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
you know, computes
this question,
what is the element
at this point?
And so, VoiceOver goes over
through UIAccessibility
to answer this question.
And if your application has
correctly implemented, you know,
the appropriate UIAccessibility
methods,
VoiceOver can then pull things
like the accessibilityLabel
and the accessibilityFrame right
from your application and back
over through UIAccessibility.
And so once VoiceOver has this
information, it can transform it
into output that's
appropriate for the user
so that output may be
speech or possibly Braille.
Great. So now, we have
kind of a general idea
of how Accessibility features
will query our application.
So, how can we make sure our
application correctly responds
to these queries?
How can we make sure
we are playing well
with these Accessibility
features?
Well, as I said before, really,
the easiest way to do this is
to do an Accessibility
audit of our application.
And so, if you're working in
a simulator, we have a tool
for you called the
Accessibility Inspector.
But even better, if
you're on the device,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
we can just use the
Accessibility features
themselves and this
is really going
to give us a great understanding
of how our app works
with Accessibility.
Both of these features
can be found
in the Settings application
under General Accessibility
as we saw before.
And it's worth noting that we
also have a great extra feature
called the Accessibility
Shortcut,
some of you may know it as its
former name, just triple-click.
Accessibility Shortcut lets you
tie an Accessibility feature
or more than one feature to
three clicks of the Home button.
And so, this lets you quickly
click the Home button three
times, turn something
like VoiceOver on,
do an audit of your application,
click the Home button three
times to turn VoiceOver off.
So, it's really handy
for this audit process.
And so now, let's dive in
and find our accessibility
bugs today,
let's see what we
have to deal with.
Okay, as we said, we're going to
open the Settings application,
General Accessibility,
same as last time.
I'm going to scroll all
the way to the bottom
and I see the Accessibility
Shortcut.
So again, I'm going
to pair VoiceOver
with my Accessibility Shortcut
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and I really recommend
you use VoiceOver.
I mean, you know, you
can use Switch Control
if you're feeling courageous.
But VoiceOver has the
easiest learning curve
and it's really a, you can turn
it on, and just hear what's
under your finger,
navigate around.
It's really a quick and easy way
to do a great accessibility
audit.
And so now, if I
click three times--
>> VoiceOver on, settings.
>> VoiceOver comes on
and it reads what's
under the cursor as expected.
And if I click three
times again-- -
>> VoiceOver off.
>> VoiceOver turns off
so it's really easy.
And so now, let's
open our application
and see what we're
working on today.
So the application we're going
to be making accessible
today is a floor--
a series of floor plans
of the convention center.
And so, let's exam it before
we turn accessibility on
and see what-- and, you know,
see what we're going
to have to fix.
So if we look across
the top, we have a label
of the convention center and
it looks like an indicator
of what floor we're looking at.
On the left hand side, I
see an Elevator control
that as expected,
let us increment
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
or decrement the
floor we're seeing.
And at the very bottom,
a control called Coffee
and if I swipe it, it
shows us, you know,
where you can find Coffee in
the convention center right now.
And so, if we triple click
to turn VoiceOver on-- -
>> VoiceOver on.
Landscape.
>> Great.
>> Home button to the
left, top and center.
>> So it comes on as
expected and it lands
on the first thing it finds and
in this case, it finds a label
at the top of the screen
and that label is already
accessible so that's great.
Let's try and touch the floor
value next to the label.
So, it looks like I'm
not getting anything
when I touch the floor
number next to the--
or next to the heading,
I'm going to try touching the
control on the left hand side.
Again, I don't see anything
VoiceOver doesn't know anything
is there, the control at the
bottom, nothing and as expected,
the map in the center,
again, not accessible at all.
So, it looks like we've got
our work cut out for us.
This is going to be, you know,
you think this might be a
tough job but you're going
to be amazed that
just in a few minutes,
we're going to take this
completely inaccessible
application and make a great
accessibility experience.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Okay, so we have an idea of the
bugs we need to start tackling,
you know, how are we
going to fix these bugs,
what API are we going to use?
So as I said, we're going to
start with the basic API first
and work our way up, pick off
the low hanging fruit, take,
you know, take off--
take down the easy bugs.
So, the two most important
accessibility attributes we're
going to be working with
are isAccessibilityElement
and accessibilityLabel.
So, for isAccessibilityElement,
you want to return yes
for any element that you
want VoiceOver to see.
When we were using
our application,
we saw that VoiceOver
wasn't even aware of most
of the elements on screen.
And so to fix this, this would
be the appropriate piece of API.
And it's worth noting that if
you're using standard UIKit
controls or labels like
UILabel, this is on by default,
VoiceOver knows about
these by default.
You really get a lot of
accessibility for free
when you use the
built-in classes.
And second, as I said
is accessibilityLabel.
Here, we want to return
a textual representation
of the element and in
the case of VoiceOver,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
this is the first thing
VoiceOver is going
to speak to the user.
And the last three pieces of
easy API we're going to need
to use are accessibilityHint,
accessibilityValue,
and accessibilityTraits.
So, for accessibilityHint,
we're going to want
to provide some additional
usage information
to the accessibility
features like VoiceOver.
And we're going to want
to do this in cases
where maybe the implications of
using this control or element
as it were are non obvious.
So in the case of our Coffee
control if we think back,
you know, when you use
the Coffee control,
it changes something
somewhere else.
So this would be a great
place to add a hint
to let the user know, you
know, what's happening.
Coffee is, you know, the--
activating the switch will show
or hide Coffee in a
different location.
We also have accessibilityValue
so the--
usually, an elements
label is quite static
but a value is meant
to be changed.
So, if we think back to
the header across the top
of the application, we
remember we had a static label
that said Moscone West but
we also had a floor value.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And so again, this is a great
place to use accessibilityValue.
That floor can change
as we adjust the elevator
control up or down.
We can view a different
floor and we always want
to make sure we're returning the
correct information to VoiceOver
because it's going to call
into these APIs a lot.
And so, the very last piece
of basic API we need
is accessibilityTraits.
So accessibilityTraits are a
bit mask of unsigned integers
that you can or together to
really convey the behavior
and intended use
of that element.
And so, traits are a little
tricky, you know, a little hard
to wrap your head around
if this is your first time.
So, let's take a look at an
application that's already
in iOS and see how the
traits are applied.
Well first, we see this
header across the top
of the application, you know,
it really contains the city
and the temperature of that
city and this really conveys,
you know, the most information
for this application.
And so here, it would
be appropriate
to use the header trait.
Similarly further down, we
some static text, you know,
these days of the
week do not change,
so the static text trait
would be appropriate here
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and it would give
VoiceOver an indication
of how to speak this item.
Further down, we see
a Standard button
and the button trait
will be appropriate here
and it's worth noting that since
this is, you know, built on top
of a standard UIButton,
a UIKit class,
it already has this
UIAccessibility trait of button,
we don't actually
need to add it.
And again, this is the case for
a lot of these built-in classes,
you know, they have the
isAccessibilityElement yes,
they're visible to VoiceOver,
they have the appropriate
traits.
If you've assigned a
name to your button,
if you're just using a
standard round rect button,
VoiceOver will use
that as the label.
So, VoiceOver is
very intelligent
about these standard classes.
So, it's a good way to
get the most accessibility
for your buck.
And then lastly, we have this
page control across the bottom
and again, by default, this page
control is an adjustable item.
And if you are rolling
one yourself, you know,
a selector type control,
here is where you'd want
to use adjustable and this
really will lend itself well
to that elevator control we
saw on the left hand side
of the screen because it is
basically just an increment
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
or decrement or up and down
the change of the floor.
Great. So now, we know what
pieces of API we need to use
to get us most of the way
there, how do we use them?
Well, if your interface is
quite static and you are working
in Interface Builder, the good
news is you can handle most
of it right there.
So, we have an Accessibility
enabled check box
that corresponds to
isAccessibilityElement.
Similarly, we have a
text field that is--
that corresponds to
accessibilityLabel.
A text field that corresponds
to accessibilityHint
and then you see a series
of check boxes below
that correspond to
accessibilityTraits
and you're going to want
to select all the traits
and they are, you know,
under the hood or together
to really convey the behavior
and usage of this element
to VoiceOver or any
Accessibility feature.
So, what if you're
working in code?
Well again, if your
interface is quite static,
we can set these attributes,
we don't have to override them.
And so, you know, we find
an appropriate place to do
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
that like awakeFromNib
our header is created
and then we're going to set the
isAccessibilityElement value
to yes.
We're going to set
our accessibilityLabel
to something appropriate.
And then, we're going to
set our accessibilityTraits
to something appropriate.
And again, in this case
maybe the header trait was
most appropriate.
But your interface isn't
always static, right?
I mean our interface that we're
working on today is not static
so what do you do in
these dynamic cases?
Well, here is where
you're going to want
to override these methods
and make sure you're always
returning the appropriate value
at the appropriate time.
And so here, we've
overridden accessibilityValue
and we're always returning
the actual floor number
that we're on.
And so again, we're going
to use accessibilityValue
in our application for
exactly this purpose.
Great. So now that
we have an idea
of the basic API we're
going to use, let's go ahead
and see how well
we can do with just
that in our application, OK?
So, let's start by taking
a look at this, you know,
header information across
the top of the application.
So, if I find the class, I
know that is my titleView,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
I'm going to go ahead and just
grab the basic accessibility
attribute stubs and drop them in
and just go right down the list.
So first, we want
VoiceOver to see this element
so isAccessibilityElement
YES is absolutely necessary.
Secondly, we need a label
for this element and we saw
that because we have a
standard UILabel as a sub view
of this view, you know,
it was already accessible,
it already had-- it lends
itself well to accessibility.
So, what we're trying to do
here is combine the floor
and the label together because
they really only make sense
together out of context if
you just heard, you know,
two out in the middle
of nowhere,
it really makes no sense.
And so again, we're
combining this information,
we're combining these
sub views together.
And so, we're going to do that
by simply returning the value
that title label was
already giving us,
titleLabel, text, great.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So, this is a pretty
obvious element,
accessibilityHint is not
really necessary here
but we do have a use for value.
And for value, if I
jump to the header,
I can see that this element,
you know, has a representation
of the floor internally.
And so this is a great
place to use that.
[ Pause ]
Okay.
[ Pause ]
And I'll leave traits
out of this one.
It's worth mention that
Accessibility is just
like application
design in general.
You know, there is often
no exact right answer,
just like you're
designing your interface
to convey what you want
to convey to the user,
you do that with
Accessibility as well.
And so, you know, you need
to make these choices
as you progress.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And I should also make note,
you know, we always want
to localize our labels
and use number formatters
as appropriate.
VoiceOver works in a huge number
of languages but for brevity,
we'll leave that out today.
So next, let's take a look
at this Coffee control
on the bottom of the screen.
We're going to start
the same way as before.
The first thing to do is make
sure Accessibility can see
this control.
Again, we need to return a label
for this, something appropriate
and go ahead and call it Coffee.
And as we said before,
you know, the implications
of activating this switch might
not be obvious to all users
so let's go ahead and return
a hint here, maybe something
like show or hide
Coffee locations.
So, what should our value be?
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Well, we do have a value
associated with this control,
right, and that value
is off or on.
And so here, if I jump
to my header again,
I see that it does have
a state of off or on
and so I'll just go
ahead and use that state.
And if it's on, let's return
a string that says on.
And similarly, if it's off,
let's just go ahead
and return off.
And lastly, traits, what
should the traits be for this.
Well, I'm thinking that the
most appropriate trait here
is button.
This really is a
stateful button.
If you, you know, press it,
you can get it to go on,
if you press it again,
you can get it to go off.
And so, we'll see
how button works.
Let's see lastly, let's take a
look at this Elevator control
on the left hand side of the
screen for our, you know,
to see how to use our basic API.
And so, let's find
it, Elevator control.
We'll drop in our stubs.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Again, let's make it
visible to Accessibility,
that's our first step.
We need an appropriate label
for Accessibility features
to speak or use as they need.
And here, let's do Floor.
It, you know, there's really no
need for a hint in this case.
Again, it's pretty obvious.
The same as before, we're
going to need to convey
that floor value and if
we flip to our header,
we see that this control too has
or this element too has a
floor value associated with it.
So, let's go ahead
and return the-- oops.
And lastly, traits,
what traits do we want?
Well, as I said before,
this is really an
incrementor/decrementor and
so, this is one of those times
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
when you as the implementer,
you know,
have to make these
decisions yourself just
like you're designing
your application.
We're going to have to make
some Accessibility choices.
So, we could make the
top button, you know,
an increment button
and the bottom button a
decrement button.
But again, I've decided that, I
think, it would be most useful
if we just made this
an adjustable control
that you could easily
flip up and down.
And so, let's go ahead do
that, I'll try adjustable.
Great. And so now, let's
go ahead and push this
to our device and see how we did
with just a little
bit of accessibility.
>> WWDC maps.
Double tap to open, VoiceOver.
>> VoiceOver is a
little jumpy, anxious.
[ Pause ]
Okay, so if we switch back
over to our application,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
let's turn VoiceOver back on.
>> VoiceOver on, landscape.
Home button to the left,
Moscone West, floor two.
>> Great. So if we check
the title or the header
across the top of the screen.
We see that, we've now mashed
all of that information together
into one element and it
really makes sense, you know,
the context and the label are
really all there together.
So let's try the control
on the side of the screen.
>> Floor two, adjustable.
Swipe up or down with one
finger to adjust the value.
>> Great. So VoiceOver can
see this element as well.
And since we've used
the adjustable trait,
it even gives us a hint
on how to use this element
and it's telling you
to swipe up or down
to increment or decrement.
So, I'm going to swipe up.
>> Two.
>> Unfortunately,
we hear the bonk
so there's something
we're missing there.
We're almost there so we'll
have to handle that one again.
And the Coffee control
at the bottom.
>> Coffee, up button.
>> Great.
>> Show or hide Coffee
locations.
>> And we heard the hint which
gave us some more information
about what this control actually
does, you heard it speak button
because we applied the
button trait to this control.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And so now, let's
go ahead and try
and double tap to activate this.
>> Coffee, off.
>> OK. So we still have
an issue there as well.
You know, VoiceOver is
unable to activate it.
By default, when you double
tap, VoiceOver is going
to send a touch to the
center of that element.
And in this case, since
our control is using swipe,
this touch sent to the center is
not going to do what we want it
to do but we're in
great shape, right?
We fixed a huge amount
of the interface
with just a little bit of work.
So, let's see how we can
get the rest the way there.
Well, the elephant in the
room in this application,
the big hurdle we have left
to get over is that map.
How do we convey this
rich spatial information
out of what is essentially
a custom drawn view.
So, the answer to that is
we use something called the
UIAccessibility container
protocol.
And here, we're going to
create Accessibility elements
that represent everything we
want to convey to the user
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and return them using the
UIAccessibility protocol.
And so, the three methods,
we're going to be using are
accessibilityElementCount,
accessibilityElementAtIndex,
and indexOfAccessibilityElement
and you might be thinking
these look like array methods.
Well, that's great.
They line up very
well with an array.
So, what we can do is
create these elements,
put them in an array and I've
called my array rooms here
and I just rely on
those, NSArray methods
to really return
this information
to Accessibility as needed.
And so, let's look at how we
would do that, how do we fill
that array with accessible
elements?
Well, the first thing we need
to do is create an accessibility
element for every room.
And so, this is an example
of us doing it in a loop.
Secondly, accessibility
elements unlike UIView elements.
If, you know, if we're
talking about UIView elements,
they have an accessibleFrame,
an accessibilityFrame rather
by default, and that
accessibilityFrame is just
pulled from the actual
frame of that element.
But we're creating these
elements, you know,
out of thin air so they
don't have a frame,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
so we need to figure out what
we want this frame to be.
And so, I have a helper
method that's, you know,
giving me a Frame for each room
and we have a nice convenience
function in UIAccessibility.h
that lets you convert your
frames from view coordinates
to screen coordinates because
all of the accessibility works
in the screen coordinates.
But the great news is you don't
really have to worry about it,
just use this convenient
function.
And the last thing
we need is a label.
So, we need to, you know,
convey a textual representation
of these accessibility
elements to VoiceOver
or whatever the accessibility
feature is.
Another problem we had
was that Coffee control
across the bottom of
the screen, right?
We double-tapped on
it, nothing happened.
And again, you know, our
hypothesis is that that is
because it was only
activatable by swipe.
We-- in this case, we're
using a UIGestureRecognizer
under the hood and it's
just looking for swipe,
it's not handling touch at all.
And so when you get yourself
into cases like this,
we've added some brand new
API in iOS 7 that's going
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
to allow you to, you know, get
yourself out of this corner.
And the way you can do that is
overriding accessibilityActivate
on any method.
And if you handle Activate,
you simply return yes
after you handled it.
And so here, what we're going
to do is take that default input
from VoiceOver and transform it
into, you know, the equivalent
of a swipe so this
control just works.
And then lastly,
some really cool API
that we've added is
accessibilityPath.
So, in-- historically, VoiceOver
has only worked with, you know,
the cursor has only been a rect.
And the problem with
this is that we're unable
to convey spatial information
to users, you know, if--
you can imagine if this Map used
a rect for every single element,
it wouldn't really help us.
We wouldn't really get any of
that rich spatial information.
But now in iOS 7, we can
override accessibility path
or set accessibility path as
necessary and this is going
to be preferred
over accessibilityFrame
any time it's present.
I mean you can see
what this is--
on the screen, what this
is going to allow us to do.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Great. So, let's now go
back to the application
and implement some of
this more advanced API
and see what we can do.
OK. Again, I'm going to go
ahead and grab my stubs,
I'm going to find my
floorPlanView and drop them in.
As we said, we need
somewhere to cache this.
We don't want to be making these
elements all the time, right?
That would be expensive so let's
create an array to store them in
and I'll call my array,
how about axRooms?
Great. And so now, as we saw
on the slide, we can simply go
through these, use our array,
and fill these in
as appropriate.
So, for
accessibilityElementAtIndex,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
we're just going to use the
corresponding method on NSArray.
Similarly for
accessibilityElementCount,
we just go right to the array.
And then as expected lastly,
for indexOfAccessibilityElement,
we can just align that
well with indexOfObject
and pass that element in.
Great. So now, we're returning
these elements as needed
but we still have to
create them, right?
And to do that, let's go ahead
and grab our helper
method and walk through it.
So here, we're lazily
creating an array
to hold these accessibility
rooms and so, this won't happen
until Accessibility asks
us for them, you know,
and at the very last minute
lazily, they will be created.
And then you can see, I
have a helper method here,
floor plan features.
Under the hood, that
is returning to me all
of these paths that
are being drawn
because that's really
what we need.
And so, you might notice that we
are enumerating this backwards
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and there is a reason
we're doing that.
We're enumerating backwards
because I've ordered my bezier
paths from biggest to smallest.
And so, it's important--
the array of elements that
we're creating are actually used
for hit testing as well.
As a user drags their finger
around the screen, you know,
that's how we're hit testing
for these accessibility
elements that we've created.
And so we have to order these
from smallest to biggest.
We want, you know,
elements that are
above bigger elements
to be hit testable.
If we put the largest
element on top, you know,
none of the smaller sub-elements
would ever be reached.
So, it's important in this case
that we go backwards
through the array.
And then again, at every step,
we're going to create an
accessibility element,
we're going to get an
appropriate accessibility label
for that element and
we're going to get
and set an appropriate
accessibility path
for that element.
And just like we have
a convenience function
for converting frames
to screen coordinates,
we also have the convenience
function for converting paths
to screen coordinates
so it's really helpful.
So, that's not it, we
have one more thing to do.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
What happens when we change
floors or show or hide Coffee?
Well we're going to need to
throw this array of elements
out occasionally, right?
If we select a different floor,
those accessibility elements
we created are no longer valid.
And so, anytime we set a floor,
we can just simply
throw those rooms out.
And similarly, if we change
the visibility of Coffee,
we can just, again,
throw the rooms out.
And the next time, VoiceOver or
an Accessibility feature calls
in looking for them, they will
be just created, you know,
with new updated information.
Great. So, two more
problems we had.
One, we still have to
fix our Coffee control,
so let's go ahead
and do that now.
And as I stated, the
new method we're looking
for here is
accessibilityActivate.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And so if we jump to the header,
we again see that on state
and really, all we want to
do is toggle that on state
when VoiceOver double taps.
So we can do self.on
equals not self.isOn
and that should take care of it.
And as I said before,
if we are handling it,
we want to return yes and
in this case, obviously,
we're handling it every time.
Maybe you have some
more complex logic
and this return value
is not constant.
And then lastly, we have
this elevator control.
We need to swipe up and
down to work appropriately.
So, let's go ahead and find
the elevator control again.
And the last two methods we need
to implement are two methods
that work hand in hand
with the adjustable trait
and those methods are
accessibilityDecrement
and similarly,
accessibilityIncrement.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And so, it just so happens,
I have a decrement floor
and increment floor method and
so, this will be really easy.
I can just go ahead and
call decrement floor
in the accessibilityDecrement
method and similarly,
increment floor in the
accessibilityIncrement method.
Great. So let's clean
and go ahead
and build our application
and see how we did.
[ Pause ]
Okay, let's turn VoiceOver on.
>> VoiceOver on landscape.
Home button to the left.
>> So, let's go down and try
the elevator control first.
>> Floor two.
>> I'm going to stop
VoiceOver Speech
by doing just a two
finger tap on the screen.
Now, I remember the VoiceOver
told me to swipe up or down
to adjust this so
let's swipe up.
>> Two.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
>> And it did not
work and that happens.
And so let's-- -
>> Take time.
>> Let's try repushing.
>> Double tap to open.
>> WW-- floor three.
>> Okay, there we go.
We just-- Xcode problem,
it was angry with us
but so we repushed the code,
we can do the swipe up and now,
we get the third floor.
And if we swipe down-- -
>> Two.
>> Second floor.
>> One.
>> First floor.
Great.
>> Coffee--
>> Let's try that
Coffee control.
I'm going to double tap on it.
>> Coffee on.
>> And you can see
that VoiceOver produces
the appropriate noise
to let the user know
that yes, this worked.
Everything is happy,
we now see Coffee.
And now really, the biggest
issue is how did we do
in terms of the path?
So, let's touch in to the lobby.
>> Lobby.
>> Great. So now, we can see
that VoiceOver knows
about the lobby.
And if I move my finger
down, take the escalator.
>> Escalator.
>> I see the escalator.
And now, I can just
kind of move up and I'm
in the lobby, I'm
still moving up.
>> Stairs.
>> And I get to the
stairs eventually.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So you can see that this allows
VoiceOver users to, you know,
move their finger around the
screen and really get a sense
of the spatial nature
of this Map.
>> Hold hot coffee.
>> Thankfully, even
Coffee works.
>> VoiceOver off.
[ Pause ]
[ Applause ]
>> Great. So as I said, you
can see we took this really
inaccessible application
and made it Accessible
with just a little bit of work.
And, you know, I
think you're going
to find that's the
case for you as well.
And so now, let's move
on to Guided Access.
I want to talk about a
few things we learned
from Guided Access since
we introduced it in iOS 6.
And so, the first thing we
learned was hardware buttons
are useful.
Our initial approach
with Guided Access was
when Guided Access is active.
We kind of remove all
hardware buttons, you know,
none of them work,
we really want
to remove all those
distractions.
But we got some feedback and,
you know, it turns out a lot
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
of really powerful
great, you know,
camera apps use the
volume buttons
and other apps use more
buttons for different things
so lesson number one,
hardware buttons are useful.
Lesson number two is if you want
to occlude a region from touch
in Guided Access, currently,
you know, you draw an area
around that region on the--
that area becomes grade out
when Guided Access is active.
And so, that works great.
You can disable buttons
as you need to.
The only problem is this doesn't
address the visual distractions
associated with the application
and so, that's the problem
and we think we can do better.
And lastly, developers
are eager to adapt.
A lot of you reached
out to us and, you know,
that's what drove this API.
And so, we're really
happy to show it to you
and see how you use it.
And so, the best way to
explain this is to jump right in
and just give a demo
of Guided Access.
[ Pause ]
So now, I'm going to return to
the Accessibility Settings menu,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
to General Accessibility.
I'm going to scroll down, remove
VoiceOver from my shortcut
and instead, add Guided Access.
I'm going to go ahead
and set a passcode
for Guided Access, nobody look.
Great. So we're all setup,
let's open our application.
And so, if I click three times
and enter the Guided
Access workspace.
So, what if we want to share
this application with someone
or maybe we're a
developer that wants
to develop one application
for two purposes?
One application to give to
users of say a conference
at this venue and that same
application to maybe post
around the halls and
just display the floors.
So, maybe you want to
hide certain controls
or really change the user
interface on the fly.
And so up until now, really, the
only option you've had is again,
to circle these controls
you want to occlude
and then VoiceOver or-- and
then Guided Access will disallow
touch from happening
in these places
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and so users won't be able
to change these things.
But again, especially if you're
developing one application
for both users in Kiosk, these
visual distractions still exist
and it, you know, it looks
pretty unprofessional
in that case.
And so, let's go ahead
and remove those regions.
And so now, in Guided Access
in iOS 7, any app that's bought
into this developer API
will have this new option
that we can see in the
bottom right corner
and you're presented with
options button and an icon
of your application and
your application's name.
And so, when I touch
that options button,
up pops this list of
all of the restrictions
that my application wants
to provide to the user.
And so in this case, we see that
we have a controls restriction
and some detail text that kind
of explains the implications
of using this control.
In this case, these
controls adjust the floor
and show Coffee.
And so, if I go ahead and
turn those controls off
and resume Guided Access,
what happens is we call
into your application and
we tell you, you know,
the user wants to make
these changes, you know,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
act appropriately, and
then it's your job--
this is your opportunity to
then go into your application
and make the appropriate
visual changes
or respond otherwise
accordingly.
And so similarly, if we go back
in, turn the controls back on
and resume, you can see
that your application is given
another call and, you know,
here is your chance to
re-add those controls
to your view hierarchy.
So that is the new Guided
Access Developer API
so let's take a look
at how it works.
So right off the
bat, the first things
to note are these restrictions
are per application,
they are not per view they
are not per view controller.
And because of that,
the appropriate place
to implement them is on
your UIApplicationDelegate.
So, this protocol exists
there and there alone.
The second thing is we
wanted to make buying
in as easy as possible.
We really wanted to
lower the bar and,
you know, make adaption easy.
And so for that reason,
state persistence comes free.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
You don't have to maintain
state in your application
of what the user has currently
set this restriction to.
We do that for you and we simply
call you anytime you need to,
you know, update your
interface as appropriate.
And so, the first three
methods that we're going to look
at are guidedAccessRestriction
Identifiers,
textForGuided
AccessRestrictionWith
Identifier: and detailed
TextForGuided
AccessRestrictionWith
Identifier:.
And so let's start from the top.
In Guided Access restriction
identifiers, you're going
to want to return a unique
restriction identifier
for every restriction that you'd
like to enable the
user to control.
And so in this case, I've just,
you know, made a static string
for this to, again, for
brevity to kind of shorten it.
But the header offers
more on the way to do this
and we really recommend that
you use reversed DNS notation.
These all need to be
unique in your application.
So again, here is where
you would return an array
of these strings.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And then, the other two
methods we're going to call
into your application
when we detect
that you have a restriction
you'd
like to convey to the user.
Then for each restriction
identifier,
we call in your application
and we say, you know,
what is the text you would
like presented to the user
for this restriction identifier?
And similarly, what is
the detail text you would
like presented to the user.
So this is your chance
to give that to us
and we will display
it to the user.
I mean you can see here, I'm
not actually checking the
restriction IDs, we only have
one restriction so, you know,
we can go ahead and safely
just return the values
for our one restriction.
And the last method is mouthful
that we want to take a look at.
guidedAccessRestriction
WithIdentifier:did ChangeState:.
So, this is what I was
talking about before
and the reason you don't
have to maintain state
in your application,
we're doing that for you.
And anytime the state for
restriction identifier changes,
we simply call into this
method with the restriction ID
and with the new state
of that restriction
and this is really your chance
to update your user
interface as appropriate.
And so here, we're doing self--
set control enabled enabled.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And lastly, we do
have a helper function
that will let you check
the state of a restriction
at any time if you need to.
So that's Guided Access and, you
know, we're really happy to get
out there, we're excited to see
what you're going to do with it.
You know, you asked
for it, we delivered it
but there's one more thing that
you asked for over the years
and we're really happy
to give it to you today
and that's a brand new
Text-to-Speech API.
[ Applause ]
So, we know a lot
of applications
in the App Store have some
Text-To-Speech functionality.
And really, up until today,
your only option has been to,
you know, roll your own
Text-To-Speech ability
into your application
and while this works,
it can make your
application quite large.
And so, we have gone
ahead and added this in
and the good news is it's
extremely easy to use,
you can use it in
just three lines,
you can make your
application speak.
And now, you have this,
you know, this option.
First you just allocate and
initialize a synthesizer object.
Second, you make an
utterance out of a string
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
that you'd like to speak.
And last, you just speak the
utterance and it's that easy.
You can make your app
speak with just three lines
and it's also worth noting
that this works in Safari.
There are some Web Speech,
there is a Web Speech ability
that you can leverage to get
this to work right from Safari
if you're working on
a web application.
Great. So for more
information, go ahead
and check our documentation.
We have a great wealth of
Accessibility documentation
that should help
you get started.
And if you, you know, you
have deeper questions,
the dev forms are always
a great place to go
for those deeper questions.
For related sessions, there is
a desktop accessibility talk
in this room directly
following this so stick
around if you're interested
in desktop accessibility.
Or if you are interested
in developing, you know,
Made For iPhone hearing aids,
or switches for our Switch
Control feature, you can come
over to the designing
accessories for iOS and OS X.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
I mean, that is also directly
following us over in Nob Hill.
So in summary, we saw that
adding accessibility is easy,
I mean, we made this application
accessible with just a few lines
and it was, you know,
virtually inaccessible before.
It's going to get you more
users and great feedback.
We've always found
throughout the years
that the Accessibility
communities provide us
with great feedback.
And then lastly, you know,
we take accessibility
very seriously here.
And so, we want you to too
and it's that partnership
that has made iOS really the
best mobile accessibility
platform out there.
Thank you all for coming.