[ 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.
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.
[ 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 ]