Transcript
[ Cheering ]
[ Applause ]
>> Good afternoon, everyone.
[ Applause ]
Welcome to Choosing the Right
Cocoa Container View.
My name is Raleigh Ledet.
I'm an engineer on the AppKit
team, and I'll be joined a
little while later by Troy
Stephens.
Another engineer on the AppKit
team.
Let's get right into it and
let's start by playing a game.
Which of these is not like the
other?
We have five different views
here.
Which one of these views is not
using the same style of basic
container view as the other
ones?
Now, look carefully.
It might be a little bit tricky,
I see a disclosure there, I see
some stuff that's indented.
You've got in mind which one is
not like the others?
OK, here we go.
If you choose the mail sidebar,
you would be correct.
The mail sidebar is an outline
view.
The other four are table views.
Let's have one more round.
Which of these three views has
got a different base container
view than the other ones?
Now, hopefully from our last
slide, you realize maybe it's
not so easy.
I see a disclosure triangle on
one of them.
You know which one is different?
If you picked this one, you'd be
correct.
This is a grid view.
The other two are collection
views.
My colleague Troy will take you
on a brief tour of some of
AppKit's more powerful and
interesting container view
classes.
These are carefully designed,
versatile and reusable
components that you see employed
throughout the system and
third-party applications.
And they're ready for you to
pick up and use to easily build
your own user interfaces.
Interfaces composed from
familiar standard components
that people already know how to
use, enabling them to quickly
get up to speed and be
productive using your amazing
apps.
Troy will outline the design
purposes, capabilities and
strong suits.
Then I will turn to walk us
through some interesting
examples of real UI's and
provide some helpful guidelines
for how to choose the most
suitable container views for
your applications, from AppKit's
extensive library.
With that, I'd like to hand it
over to Troy.
[ Applause ]
>> Thank you Raleigh.
Hi, everyone.
Before we leap right into our
whirlwind tour, I'd like us to
take just a moment to remind
ourselves of some of the
foundational aspects of AppKit's
view system.
What is a view in its most
basic, fundamental, reductive
geometric sense, but a rectangle
on the screen, where you can
present some content to your
users that they can potentially
interact with?
And as you're preparing to
present that content, one of the
most basic things you need to do
is determine and apply the
desired layout.
You want to figure out the sizes
and positions of the items that
you're going to present to the
user; they may be items, they
may be views.
And AppKit provides a very
powerful, generalized,
open-ended auto layout systems
that gives you all the parts
that you need to build very
intricate, arbitrary layouts
that adapt to re-size.
Component by component,
constraint by constraint if you
want to.
But part of the take home point
to our talk today is to remind
you that there are also some
existing solutions to a lot of
the common user interface design
patterns that you're going to
want to put in your apps, we
have lots of off-the-shelf parts
in AppKit's vast storehouse of
prefab view classes.
So, whenever possible, you want
to keep it simple.
You want to reuse these common
solutions that we've already
designed for you.
All of the views that we are
going to talk about today
accommodate arbitrary content.
Even though you're using
standard off-the-shelf parts,
your views don't have to look
prefab.
You have complete latitude,
creatively, to design your views
however want.
You can put whatever content you
want in each of these.
Let's start with a really simple
example.
Maybe the most basic thing we
want to do.
We have a series of views here.
It doesn't matter what kind they
are, they're just kind of black
boxes to the layout system.
And we want to lay them out in a
linear fashion.
Maybe in a row like this.
Or, maybe vertically as a
column.
AppKit provides a really simple,
easy-to-use solution for this,
an invisible container view that
we call NSStackView.
StackView provides a really easy
way for you to flow views in a
single column or row, and
without having to manage the
auto layout constraints
yourself.
The neat thing about StackView
is it presents a high-level
easy-to-use API.
Where you configure properties
to specify the alignment, and
metrics that you want, and
StackView takes care of
automatically managing all of
the required layout constraints
itself.
This can become especially
useful if you're going to have
the content of your StackView
dynamically change.
You're adding and removing
items, and you don't have to
worry about updating layout
constraints yourself.
So, some of the things you can
configure in a StackView include
the edge insets, which are sort
of like the margins around the
area where your views are laid
out.
You can configure the alignment
that you want for your views.
So, in this case we might was to
horizontally align our items on
their setters, or right align
them, or left align them.
Or maybe we want all the items
to be the same width and fill
the available space.
All of these things are pretty
easy to configure with
properties without having to
mess with auto layout
constraints yourself.
The only thing you really need
to be concerned with providing
yourself is ensuring that each
of your items that you put in
the StackView has a well-defined
height.
Or, if it's a horizontal
StackView, then you want to have
well-defined widths.
Now, often you can determine
this base on some inherent size
to your content, right?
Here we have some labels, and
because of the font that we
chose, they have a certain
height and we want to leave a
certain amount of space above
and below.
So, the total natural height of
each item ends up being
determined by that label height.
But once we set those up,
StackView takes care of the
rest.
Spacing between items is
configurable and doesn't even
have to be uniform, there are
lots of different options for
that.
So, it's really a very versatile
view.
StackView also has the ability
to accommodate dealing with
space constraints.
So, if you want, you can put
hundreds of items in a
StackView, you can put in a
scroll view if you want so that
you can show more items than
will fit in the window.
But often times you may be using
StackView in a context where you
have inherently limited space.
And StackView provides an API to
deal with space limitations.
It makes it very easy for you to
specify how your stack should
adapt on resize.
And the way that you do that, is
by identifying the relative
priority of your views to
StackView.
So, we could tell it, say that
view number two here is relative
low priority.
So, when space is really tight,
the window is resized smaller,
StackView will automatically
eject those low priority views
to make sure that your most
important views are still
presented to the user.
This is very similar to the
behavior you'll see in toolbars
and in Touch Bar.
StackView also provides the
concept of gravity areas, which
are sort of like sections.
So, in a vertical StackView, you
have top, center and bottom
sections.
In horizontal StackView, you
have leading, center and
trailing sections and notice
that we're making a point of
talking about things in terms of
leading and trailing, rather
than explicit left and right, by
thinking in advance in these
flexible terms, we're setting
ourselves up to handle right to
left layouts much more easily.
So, in a left to right language
the leading section will be on
the left, the trailing section
will be laid out on the right.
But if we run our app in a
language that flows text from
right to left, then the leading
and trailing sections
automatically get swapped.
And in fact, all of the sub
views in that horizontal
StackView get laid out in the
opposite order.
So, by encouraging us to think
in the right terms in advance,
StackView makes it really easy
for our layouts to automatically
adapt in right to left
languages.
StackViews are also
compose-able.
So, let's say we have a set of
views here that we want to stack
vertically, maybe some
checkboxes, we can put them in a
StackView.
Now maybe we have a sidebar we
want to put next to them.
Well, we can take another
StackView, a horizontal
StackView and put those views in
it.
Maybe we want to put some
buttons at the bottom, put those
in a StackView and then take a
fourth StackView and group those
two.
This is the kind of thing that
we really love to do in
programming whenever we can,
right?
To compose things well
understood simple parts in a
very modular way and it enables
you to build things that are
potentially complex but are
really easy to maintain.
So, there's a lot you can do
just with StackView alone.
And there was a great Mysteries
of Auto Layout Talk a couple
years ago that went into
StackView in detail.
Shows you how to configure it to
get different effects.
It's well illustrated.
I highly recommend you check it
out.
As you know, sessions from past
years are available in video
form online on the developer's
site.
Also, in the auto layout guide,
there is a section called "The
Auto Layout Cookbook" that goes
in great detail about different
ways you can use StackViews and
configure them.
So, let's take what we just
learned and try applying it to a
new kind of layout that we want
to implement.
Let's say we've got this
particular piece of UI from
appearance preferences.
Now, to me it looks like we've
got a couple of lists here.
We've got a list of labels on
the left.
And on the right, we have a list
of corresponding controls.
Both flowing downward.
So, this might be a case, where
we might naturally think, maybe
this is a chance to use a couple
of StackViews side-by-side to
solve this problem.
What we quickly find out as soon
as we try that, is that these
StackViews work great
independently, but they're
operating entirely without
regard to one another.
So, they each do a great job of
stacking what they're given, but
the problem is that a couple of
our labels here on left no
longer have the needed visual
correspondence to the controls
on the right.
So, this is going to be a
problem for usability for our
app.
You know, we could kluge this by
maybe giving the appearance
label an artificially larger
height or something like that.
But you know this is Cocoa, we
don't kluge things.
So, we really want to have an
elegant, maintainable solution.
So, the desire to do layouts
like this in really easy,
maintainable ways that was the
impetus for the development of
GridView.
And as GridView, makes it easy
for you to lay things out in
coordinated rows and columns.
It will align the corresponding
views in a given row or column
very nicely for you.
And as with NSStackView, it does
all of this, using very
high-level API that doesn't
require you to maintain the auto
layout constraints yourself.
You configure high-level
properties to set the size,
alignment and spacing of your
rows and columns.
And GridView takes care of the
rest.
Also, like StackView, GridView
automatically adapts for right
to left languages.
So, in this particular layout,
we'd expected in a right to left
language the labels and the
controls would swap and indeed
that's what we get if we run in
RTL.
The "What's New in Auto Layout"
Talk from last year was
fantastic.
And it goes into GridView in
particular and all of its
capabilities.
I highly recommend you check
that one out.
So, now just with GridView and
StackView, we've already got a
lot of stuff we can do,
especially if we take
composition and modularity into
account.
These are great for really
easily laying out and presenting
arrays of views.
But what if we need to do
something that falls outside
that?
What if we need to deal with
obviously other kinds of layouts
that aren't so linear?
But more importantly, what if we
need to be able to support user
interaction?
Things like the ability for the
user to select items, or
drag-and-drop.
Moreover, what if we don't know
how many items we might be
dealing with at runtime?
Maybe based on the user's data
set, we may have tens or
hundreds of thousands of items
to present.
It kind of gets beyond the scope
of what GridView and StackView
are designed to do.
You can put lots of items in
them, you can put them in a
scroll view, but they don't make
any attempt to deal with
efficient resource usage.
Paging just the items in that
are needed to display, and a
little bit of extra for
scrolling smoothly.
So, we want to step beyond
those, we're going to need to if
we want to solve those kinds of
problems.
Let's start with an example
where we focus on interactivity
and scalability.
What if next we want to build
sort of a more interactive grid?
And here's an example that's
familiar from one of our system
apps, Activity Monitor.
Visually, what we've got here
looks like a grid, right?
We've got rows and columns.
But the way that we're using it
is really more as a list.
So, we have items flowing down,
each row represents a process.
And we're using the columns
going across to show different
properties of each process.
We want the user to be able to
select items singly, and
multiply.
And since we're displaying
columns of data, it'd be kind of
nice if we gave the user a hint
as to what's in each column.
Also, we want to have a header
view at the top where each
column is labeled.
Now, we can offer the user the
opportunity to click on a column
heading to get the app to
automatically sort the list
according to that column's
property.
We can let the user drag reorder
columns to help them to sort of
visualize relationships in
whatever way is most useful to
them.
All of these capabilities are
encapsulated in AppKit's
NSTableView.
TableView is an interactive
vertical list view.
We usually think of them as
multicolumn.
You see a lot of multicolumn
TableViews around.
But they're also just as great
for displaying a simple single
column list.
And you'll see lots of cases
where this is used throughout
the system that may be hard to
recognize, as Raleigh's pointed
out, because the appearance is
very customizable.
Here are a couple of examples.
A really simple one on the
right.
We've just got a list of textual
labels.
So, you can do that with
TableView.
On the left, this is also a
TableView, where each item is
represented by an image and a
corresponding label.
In a modern view based
TableView, you can depict your
items content anyway you want.
Any view subtree that you can
construct from AppKit's standard
controls, your own custom views,
you can use that to represent
the items in your TableView.
So, you have a lot of creative
design latitude as to how your
items are presented.
TableView supports type
selection, keyboard navigation,
that's all done for you.
And TableView also offers group
rows.
Sometimes it makes sense to
group your items according to
certain categories.
And here we have an example.
The top yellow box actually is
outlining the header view, but
below those, those other yellow
boxes are outlining the group
rows, which are sort of like
headings, they can be any view
you want, of your own design.
And you can use those to
categorize your items which are
indented underneath them.
Here's another example where
we're using group rows.
And you'll note that the group
rows in this case, have
different heights because we
want to show a larger icon next
to them.
The item rows underneath them
are shorter.
And you can have variable row
heights throughout your
TableView.
So, they're very flexible
layout-wise.
TableViews also support row
actions you may be familiar with
from iOS, where you can swipe on
a row and that will reveal some
action buttons or maybe
instantly commit an action.
TableViews also support change
animation.
So, if you have a model that's
dynamically updating without the
user doing anything, you can
give them visual cues that items
are being inserted and removed
and they can see how their model
is changing.
Instead of just doing it
instantaneously.
Most importantly TableViews are
scalable to large item counts.
TableView is very cautious and
sparing about instantiating
views only for the items that it
needs to display plus a little
bit of prefetch area so that we
can be ready to scroll smoothly
when the user scrolls.
TableView will recycle items
that have been scrolled out of
view rather than instantiating
brand-new items.
All of this enables it to scale
very well so that you can have
smooth scrolling and dynamic
interaction with potentially
very large item counts.
TableView is very flexible as to
how you get your content into
it.
You can use bindings, if you
want to take a minimal code
approach.
Or you can use the row
index-based data source API.
It's very flexible that way.
And all in all, it's a very
versatile, easy way to present
either tabular data or simple
lists on macOS.
There's a TableView programming
guide for Mac that describes in
great detail how to use
TableView.
Also the crafting modern Cocoa
apps talk from last year goes
through an example of creating
and wiring up a modern view
based TableView step-by-step.
I highly recommend it.
So, okay we've dealt with grids
and lists.
But what about if we want to
deal with inherently tree-based
data.
What if we have something like
files, within folders, within
folders, or any other kind of
hierarchical tree structured
data model.
Well, that's where NSOutlineView
comes in.
And OutlineView has all of the
capabilities of a TableView,
because it is a TableView.
NSOutlineView is a subclass of
NSTableView.
So, everything you learned about
TableView, all of its
capabilities, all of that is
applicable to OutlineView.
On top of that, OutlineView
graphs a hierarchical data
model.
So, it will track the model
object that you tell it about,
and their children, and those
nodes children and so on.
And user interface-wise, one of
the nice things about
OutlineView is it doesn't force
your users to browse the entire
displayed out tree all at once.
You can start out
programmatically with certain
interior nodes disclosed or
collapsed, however you want.
And the user has the option by
clicking the disclosure
triangles, or you have the
option programmatically to
selectively disclose certain
subtrees that are of interest to
explore.
Another nice thing that
OutlineView is that it enables
the user to explore multiple
branches.
Multiple subtrees of your
hierarchy simultaneously.
That can be very handy for
example in finders' ListView
when you have a subtree of
folders and you want to move
some files around within that.
Very, very easy view to do that
in.
As I said, everything that
applies to TableView also
applies to OutlineView.
So, the TableView programming
guide is a great reference for
this.
And there's an OutlineView
programming topics supplement
that concisely sums up the
differences between OutlineView
and TableView.
We also offer another option, if
you have tree based data that
you want the user to be able to
browse, and we call that
NSBrowser.
Here's an example of an
NSBrowser with two columns.
The column on the left displays
our sort of root level list of
items.
The column on the right displays
the children of the item that's
selected in the left-hand
column.
Here's another example that's
similar to Finder's ColumnView.
We have three columns here.
A folder selected in the column
on the left and then we're
displaying the contents of that
folder, and the preview on the
right.
So, NSBrowser is a column based
drill down UI.
As the user clicks to select an
item in a column, we have
additional columns to the right
of that, or the left if we're
running RTL.
And the user can drill down in
that way to navigate a
particular branch of your tree.
The columns are user sizable.
So, the user can configure
things to use horizontal space
efficiently.
It has new features like
optional custom header views.
You can put any view you want at
the top of the column.
And if you want to build a sort
of browser-based master detail
interface, you can offer a
custom preview view controller
to the browser.
You configure it this way, then
when the user drills down to a
leaf node, you can display in
the next column over a view that
shows a detailed description of
the properties of that object,
as used here in this Finder's
similar column view.
A user interface difference
versus outline view with
NSBrowser.
The user really can only explore
one branch of your tree at a
time.
But for many cases, that's find
and sufficient and it does have
the advantage of using vertical
space a bit more efficiently.
There's a browser programming
topics guide and also some
sample code you can refer to, to
get started using Browser.
So, lastly, what about custom
layouts.
I mentioned we might want to
branch out beyond grids and
lists.
That's where NSCollectionView
comes in.
NSCollectionView is a very
flexible, versatile,
customizable, and scalable item
view.
It supports arbitrary developer
defined layouts if you want any
series of rectangles that you
can specify programmatically,
you can plug into CollectionView
as a layout and it will size and
position your items accordingly.
It also provides an easy wrapped
layout called flow that flows
the items as much as text might
be flowed on a page.
You can also float them in
columns if you want.
CollectionView supports the
ability to divide your items
into sections if you want.
If you want to group them that
way.
Each section can optionally have
a header view and a footer view.
These are entirely of your own
design.
And it supports user interaction
features, like the ability to
select items, and drag-and-drop
them around, both within the
CollectionView for reordering,
drag them out, drag them in.
Item representation, as with
view based TableView and
OutlineView is arbitrary.
Any view subtree you construct
out of your own custom views,
standard AppKit views as in this
case.
And like view based TableView
and OutlineView, it's very smart
about sparingly instantiating
just the items it needs,
recycling items.
So that we can keep performance
high even when dealing with a
large number of items.
It can also animate, inserts,
deletes, and moves like
TableView and OutlineView.
And also, transitions between
layouts as we saw.
We had an entire session devoted
to CollectionView two years ago.
It's much more similar to
UICollectionView now and there's
a Cocoa slide collection code
sample that went along with
that.
I highly recommend you check
those out.
So, we've looked at just 6
views, 6 view classes out of
AppKit's vast storehouse,
prefab, off-the-shelf parts
today.
And already we've got a bunch of
different capabilities.
Because each of them is fairly
versatile, we also have some
overlap in what each of them can
be used for.
So, it'd be nice to have some
guidance as to what's
appropriate to use in different
used-interface design
situations, different use cases.
So, to set us on the right road,
give us some guidance, my
colleague Raleigh Ledet is going
to show you some use cases and
help you get on the road to
building fantastic UI's.
>> Thank you, Troy.
>> Thanks Raleigh.
[ Applause ]
>> So, by now you've got a good
grasp on what's going on with
each individual style of
ContainerView, and you probably
already know where you're going
to use some of them in your
application.
But sometimes it's a little bit
more difficult to choose.
So, I want to take a step back
and look at things as a whole,
as a collective.
To start off with, broadly, we
can split our ContainerViews
into two large categories.
You have what, in StackView and
GridView what we call our pure
layout containers.
And that's all they do is they
provide layout for you so you
don't have to deal with all of
the constraints.
They make it easier for you to
do that kind of layout.
They don't do any drawing or any
selection.
And then with CollectionView,
TableView, OutlineView, and
Browser, we have what we call
the data back ContainerViews.
And these views handle
efficiently adding and removing
views depending on the content
that you provide with some sort
of data source or bindings.
If we take a look at the data
source set of CollectionViews,
we can break those up a little
bit more.
If you have tabular data, a good
place to start might be
TableView or OutlineView.
If you have a tree structure
style of data, you might want to
look at OutlineView, no
NSBrowser.
If you have a grid style layout,
or you really need to have
custom layout, then you might
want to start off looking at
CollectionView.
To bring this all together, I
want to take a look at some case
studies and some real examples.
And let's start with mail.
In particular, I want to start
with message list of mail to
figure out how did we come up
with this design and why did we
land here?
So, let's start with our list of
CollectionViews.
And think about the different
types of properties that your
mail message list might have.
Now, I don't know about you, but
I have thousands of email
messages in my inbox.
So, your email client is going
to need to be able to deal with
an unbounded number of emails.
So, immediately we're going to
want to use one of the data back
storage ContainerViews, so we
get a nice efficient use of
views and of memory and
responsive scrolling.
Of course, we're going to need
selection, so we know which body
of which email to show to the
user.
And each email has lots of
properties.
Such as the sender, subject,
date, so forth.
At this point, if you look at
all the various properties, it
starts to sound like you have
tabular data here.
And indeed, this isn't
structured exactly like a tree,
so we don't need CollectionView
or Browser.
But, think about it a little bit
more.
We can take all the email
messages that are part of the
same conversation and group them
together.
So, we can perhaps collapse
them.
And so, OutlineView becomes a
great choice.
And if you look at mail's
classic view, if you turn that
mode on, that's exactly what you
have, you have an outline view
with the body of the email in
the panel below.
This is great, but let's
critique the use of space here.
In particular, I want to talk
about the body of the email
here.
I can't even view the entire
message here without scrolling.
And it's not a very long email
that I have here.
Now, as user, I can just add
more space by changing the split
view, but then I would subtract
space away from the OutlineView
and my list of messages, and I
would have to scroll even more
to find the messages I'm
interested in.
If we rearrange things a little
bit, we can end up with this
design.
What we've done here, is we've
used a complex table cell.
So, it's a single column table
view, and each cell is a complex
cell, so, we put all the
properties into this one cell.
And this opens up the whole
other side of the window that we
can put the entire body of this
particular email message.
So, now as the user can read
more of the email message with
less scrolling, and since we
have now a vertical split, no
matter how the user changes the
size of the split view, I'll
always be able to see the same
number of emails in the column
list, so I won't have to change
how often I have to scroll
depending on how the split view
is changed.
Let's dig into this a little bit
further and consider the
trade-offs.
One of the things is there's no
way to sort.
Without table headers, the user
no longer has a way to sort.
And changing that sort order can
be very useful.
So, mail had to go in and add
additional control to allow the
user to sort.
User has less control over the
size of each property.
When it was individual columns
they could change the size of
the column and add more width
for the sender for example, or
maybe more width to the subject,
so they could read more of the
subject at a time.
However, we gain the ability to
provide emphasis on the most
used content.
So, for example if we look at
just one of these cells, we have
the sender of this email message
in a nice bold text.
And then we have over to the
right of it we have the date.
And we could put both of these
in a StackView and let StackView
automatically handle the layout
of these two views right next to
each other.
So, as the date needs a little
bit more space depending on the
exact data, it will
automatically take space from
the sender.
This is also similar with the
subject.
It's in a nice bold text, we can
contrast that with the
single-line preview of the body
of the message which is in a
greyer text.
So, we can provide emphasis on
the sender and then on the
subject of the email.
And we could put that in a
StackView as well to line up
with the size of the message.
And we have the flags and a few
other properties in here, we can
put the rest of this and embed
it inside of a GridView.
So, we've ended up with a
TableView for our mail list,
which is composed of a GridView
that has embedded StackViews
inside of it.
Next up, preview.
In particular, the sidebar.
So, I'm showing a PDF here of
the US tax code.
And we want to show on the
sidebar a preview of each PDF
page.
So, let's start off again with
all of our ContainerViews and
think about the properties of
our PDF.
Well we can have a large number
of pages.
The US tax code is over 6500
pages of PDF information.
Of course it needs to be
selectable, and it's even
reorderable.
Preview allows you to reorder
the pages in the PDF and resave
the document out.
A feature if you don't about
that I particularly like to use
to take blank pages out of PDF
documents and resave it that
way.
But this means we're going to
need something that's going to
be data source backed.
So, again StackView and
GridView, we'll take those out
of contention.
And we'll consider this a little
further.
We have a single column vertical
layout.
So, we're not going to need
Browser.
And we also need collapsible
categories.
That screenshot I showed you at
the beginning, we had this
little disclosure triangle next
to the name of the PDF.
Preview allows you to view more
than one PDF at the same time in
the window.
And this works out really great
to actually move pages between
documents and rearrange things.
And once we need collapsible
categories TableView is out of
the running and we're left with
CollectionView or OutlineView.
This gets to be a rather
interesting choice here.
Which one should we use?
Well, what happens when we
resize the sidebar here?
You see that the previews of the
pages grow in both the vertical
and horizontal dimensions
proportionally.
Traditionally, this is something
that would've taken more code
with OutlineView for you to
handle as you needed to adjust
the row heights and handle that
as the user is moving the split
view.
However, in macOS High Sierra,
this is something that
OutlineView can handle for you
automatically.
Let's dig a little bit further
and look at another part of the
interface with preview, and this
is the contact sheet.
And you notice the contact sheet
also shows you a preview of the
page, along with the page
number.
It looks a lot like the sidebar
except you have a GridView of
them.
And this allows you to actually
reuse your data source.
If we use a CollectionView for
both the sidebar and the contact
sheet, we can reuse our data
source code.
So, that's great.
And we're just going to change
the flow layout for the
CollectionView.
And in fact, that's exactly what
preview does, in this case.
This is the Internet Accounts
Preference pane.
And I want to take a look at the
account types right here.
You click on an account type, a
sheet comes down and you go
ahead and enter the details so
you can create that new account
type.
Again, we'll start off with our
list of ContainerViews.
And the account types, there's a
small number of account types,
there's only 10, we can put all
of those and have just a little
bit of scrolling.
So, we don't need to worry about
having views come in and out
dynamically.
It's a one-dimensional vertical
layout.
So, we're really limiting down
to deciding between StackView
and TableView.
We don't need selection.
In fact, each one of those
items, there's a button.
We don't want to provide a
selection there, we want to drop
the sheet down as soon as the
user presses the button.
So, this is really starting to
look like a StackView.
And given the requirements that
I've laid out, this is exactly
what I would recommend that you
use today, is a StackView.
But then the accounts preference
pane is using a TableView.
Part of the reason is
historical.
The Internet Accounts preference
pane was written before we had
StackView and AppKit, and it
works just fine.
You can tell TableView not to
have a selection.
The code's already in place.
It works great.
But if we dig into it a little
bit more, if we scroll down to
the bottom, there's this add
other account.
You click on that, 7 new account
types are added.
So, now we have 17 items to
scroll through.
StackView can handle this quite
easily.
But you have to manually start
adding the items to the
StackView.
Not a lot of code.
But at this point, the data is
dynamic.
I would start to lean toward
using something that's data
source back, and that you can
just tell the table to reload
and to provide the dynamic data
from the data source.
So, at this point, I would start
recommending TableView.
This is terminal's new remote
connection.
And this is a great example of
NSBrowser.
I want to critique this entire
interface here, looking at the
size and shape of the UI.
In particular, the use of
vertical space versus horizontal
space.
And I think the best way to
examine this is to compare it to
what it might look like if we
used an outline view instead.
Well, immediately, over on the
right-hand side we have this big
blank area.
So, this is not really great use
of space.
Further, as the user turns down
different services to look at
the various servers, they'll end
up with a lot of similar names
and you'll have to do a lot of
scrolling to find what you want.
And lastly, I have two sets of
plus and minus buttons.
What do they do?
Well, obviously, they might add
servers and services, but which
one adds servers and which one
adds services?
With Browser, we get a nice
interactive division.
It's very clear which column is
for servers, which column is for
services, which plus and minus
button act on which column.
But sometimes, one size does not
fit all.
And a canonical example of that
is the Finder.
The Finder has the segmented
control so that you can browse
your files by list view or by
icon view, and by column view.
So, given all the situation and
type of data, the user might
have their own preference, and
you might have to implement more
than one style.
So, you have to consider this as
well.
As another example, here is a
screenshot of Image Capture.
These are images that had
recently taken on my phone.
And they showed up in Image
Capture in an icon view.
I can quickly find the photo I'm
looking for and drag it over and
copy to my desktop.
But sometimes finding the photo
can be a little bit difficulty,
especially if I'm trying to find
a movie that has a similar
preview as one of the pictures.
Well, user preferences has this
little control way down here in
the bottom, it's a segmented
control, so it allows us to
switch from icon view over the
list view.
Now, in list view, I've got a
nice column here multiple
columns.
I can click on their headers,
reorder it by type, and find the
movie that I was looking for.
And at last, I want to
deconstruct the printer's
preference pane here.
We have an NSTableView here.
It's using group row headers.
It supports printers, faxes, and
even scanners.
And then over on the right-hand
side, we have a tab less
TabView.
But we haven't talked about
TabViews in this session at all
yet, but I want to point out
something very interesting about
tab less TabViews.
With a tab less TabView, you can
set up your interface for the
different types.
For example, a printer is going
to have very different
properties, detailed properties,
than a fax machine is going to
have.
So, I could set up those
different properties in a tab
less tab, and then
programmatically select the tab
as the user changes the
selection in the TableView.
And then the tab will do all the
hard work of loading up the
appropriate Zip file and adding
the views in the view hierarchy
automatically for me.
We looked into the detail list,
here.
We can have a collection of
StackViews here.
And we'll break that down even
further.
We can see that we have GridView
of the detail properties of
their labels, and the detailed
properties of the printer.
And even the page size and the
default printer and its
associated pop-up menus.
And now, with all of this in
place when the user switches to
Arabic, everything flips
appropriately for the right to
left language and an Arabic user
has a great user experience.
So, to review, AppKit has a
number of ready-made views that
could be used for many uses.
Use the chart that I had earlier
and use some of the use cases
that I've talked about and how
to breakdown your user
interface, critique your space,
and figure out which type of
ContainerView best suits your
needs.
And don't forget that you can
compose things.
So, you can stick GridViews
inside of StackViews and vice
versa.
Just to recap some of the learn
more information that Troy had
showed you earlier for StackView
and GridView.
Some more information for
TableView, OutlineView and
Browser.
And lastly some more information
for CollectionView.
And of course, you can find
links to all of this information
and more at the more information
for session 218 on the
developer's site.
Related sessions, we have
"Advanced Touch Bar" later today
at 5:10 where they will even
talk a little bit about using
some of these ContainerViews in
the Touch Bar.
And of course, please check out
the Cocoa Development Tips, and
they'll give you some more
interesting tips.
And with that, enjoy the rest of
WWDC, thank you.
[ Applause ]