It's a SwiftUI party — and you're invited! Join us as we share the latest updates and a glimpse into the future of UI framework design. Discover deep levels of customization, advanced techniques for layout, elegant strategies for sharing, and rock-solid structural approaches for designing an app top-to-bottom in SwiftUI. We'll also have some celebratory fun as we play with the latest graphical effects and explore APIs.
♪ instrumental hip hop music ♪ ♪ Hi, I'm Nick. And I'm Franck, and we are SwiftUI engineers. Today, we're going to cover "What's new in SwiftUI." SwiftUI is growing alongside our operating systems, each pushing the bounds of the other. We continue to be amazed and delighted by what you are making with SwiftUI. We take to heart all flavors of feedback from the community. That's why we're especially excited to share what we've focused on this year. With this year's APIs, we've gone deeper. We've made more custom experiences possible. We've introduced some amazing new graphical techniques. We've architected a new SwiftUI app structure, and much more. SwiftUI enabled us to build designs and features that reflect the future of our platforms. From redesigns of classic apps to completely new features to deep system integrations. This comprehensive adoption within Apple further pushes evolution of SwiftUI. Many of these new designs and features are only possible because of how SwiftUI has evolved how we write apps at Apple. Today we're celebrating these APIs, And we're also celebrating SwiftUI's birthday, Franck and I are the lucky cochairs of the party-planning committee. Let me tell you about the activities we've got planned for the party. I'll introduce you to a brand-new framework called Swift Charts that allows you to create delightful data visualizations across all of our platforms. I'll show off SwiftUI's data-driven, strongly-typed model for navigation and new window techniques. Franck will take you through a suite of new controls and deeper customizations of existing controls. Then he'll show you how we've brought sharing elegantly into the universe of SwiftUI with the Transferable protocol. Finally, I'll close with whimsical new graphics APIs and advanced new layout APIs. Let's get going with Swift Charts. Swift Charts is a declarative framework for building beautiful state-driven charts. The fundamental design principles that make SwiftUI great and the process of plotting data have been composed harmoniously to create Swift Charts -- a world-class data-visualization framework. This is a bar chart plotting the number of party tasks Franck and I need to complete before the party can start. Swift Charts has built a magnificent, customizable chart from only a few lines of code. Like SwiftUI, Swift Charts picks intelligent defaults. Here, the framework chose satisfyingly round numbers for the y-axis values, and provided a default color for the bar marks.
If you know SwiftUI, you can already read the declarative, state-driven syntax of Swift Charts. Chart is just some View, and you declare it just like you do lists and tables -- by providing data and then building the chart content with that data. For this chart, I've chosen a BarMark, but if I switch to a LineMark and add a foreground style to group by category, I can see more to the story as Swift Charts draws individual lines for each category and adds a legend to the chart automatically. It's fun to give these charts a little personality. I can add points to the line with the symbol modifier on the LineMark. These modifiers are no different from SwiftUI modifiers. You can even use SwiftUI views within a chart. Like List, the data argument to Chart can instead be passed to a ForEach. This allows adding more marks to the Chart builder, like a RuleMark to show our daily goal.
The spirit of SwiftUI shines through again, as Swift Charts handles localization, Dark Mode, and Dynamic Type automatically, and of course, works across all of our platforms. If you want to see how to make your own charts, check out "Hello Swift Charts." If you're interested in advanced plotting techniques, follow it up with the "Raise the bar" session. Next up, let's talk about navigation and windows. SwiftUI already supports the most common app navigation patterns, such as immersive push-and-pop navigation stacks; expansive, detail-rich split views; and powerful, multi-window experiences.
This year, SwiftUI has big updates for all three of these patterns. Let's start with stacks. SwiftUI is introducing a new container view, simply called NavigationStack, for supporting push-and-pop-style navigation. A NavigationStack wraps a root content view, like this food inventory list for our party-planning app. As you'd expect, it works great with existing APIs like NavigationLink and navigationTitle(). When we select a link, SwiftUI pushes its detail view on top of the stack. In our app, each detail view contains more links for related food items for quick browsing.
This approach might be all you need. But there is a new way to present views and have programmatic control over that presented state. If you need control of a navigation stack's state, adopt the new data-driven APIs. The new navigationDestination() modifier lets us associate navigation destinations with specific data types.
And this year, we taught NavigationLink a new party trick: instead of a destination view, it can take a value that represents a destination. When tapping on a link, SwiftUI will use its value's type to find the right destination and push it on the stack, just like before. Because we now use data to drive our stack, it's possible to represent the current navigation path as explicit state. In this case, the navigation path is simply an array of all the food items that we've visited. With direct access to this state, it couldn't be easier to add a button for quickly jumping back to the first selected item. As views are pushed onto the stack, items are appended to the selectedFoodItems array. In the button's action, we can just remove all the items from the path except for the first one.
And with a tap, we're right back where we started.
Now let's talk about split views for multicolumn navigation. We're introducing another new container called NavigationSplitView for multicolumn navigation. NavigationSplitView can declare two- and three-column layouts. Party Planner uses a simple two-column layout, wrapping a sidebar list of our party-planning tasks and a detail view that changes its content with the selected task. Split views work great with the new value-based NavigationLinks we saw earlier, using the link's value to drive the list's selection. NavigationSplitView will automatically collapse into a stack on smaller-size classes or devices, making it a great tool for building adaptive, multiplatform apps. NavigationSplitView and NavigationStack are designed to work together and can be directly composed to build more complex navigation structures. We use this in the Party Planner app to turn the detail column into its own, self-contained navigation stack, which also shows off the new support for navigation stacks on macOS.
Well, we've talked a lot about food, but I hear that my colleague Curt is cooking up a storm over in his talk, "The SwiftUI cookbook for navigation." Check it out to learn even more about navigation stacks and navigation split views. But for now, let's step outside the box and talk about new scene APIs. You're likely already familiar with WindowGroup, which is a great way to build the main interface of your app, and can generate multiple windows to allow different perspectives into your app's data. New this year, we're adding window, which -- you guessed it -- declares a single, unique window for your app. Here, I've added a Party Budget window that shows the total cost of the party.
By default the window is available and can be shown by selecting its name in the app's Window menu. But we can make that even easier by assigning a Command-0 keyboard shortcut to open the window. To make sure I stay a budget-conscious party planner, I'll add a toolbar button with an action that also shows this window. Using the environment action openWindow, I can now programmatically open new SwiftUI-managed windows. In fact, we've added a whole suite of new window customizations this year, including modifiers for default size, position, resizability, and more. I don't want the party budget getting in the way, so by default it appears as a small corner window. But if I adjust its position or size, SwiftUI will automatically remember that across app launches. The new standalone window scene is great for little auxiliary windows like this one on the Mac, but Party Planner is a multiplatform app, and we need a better design for smaller screens. For example, on iOS we've chosen to display our budget within a resizable sheet instead. This is possible with the new presentationDetents() modifier. In this case, I configured a resizable sheet that sticks to two different sizes: one at 250 points, and another at a system-defined medium height. It is simple to iterate between platforms this year with multiplatform targets in Xcode powering up your SwiftUI-based apps. One target can be deployed to multiple platforms. Just pick your platform from the usual pull-down menu in Xcode's toolbar. Watch "What's new in Xcode" and follow it up with "Use Xcode to develop a multiplatform app" to learn more. For the final new scene type, we can turn our attention to the menu bar. With macOS Ventura, you can now build MenuBarExtras entirely in SwiftUI! These can be defined alongside other scene types in your application and will always be shown in the menu bar while your app is running. Or, you can build an entire app using just a MenuBarExtra! These are such a fun way to bring even the simplest of ideas to life on macOS. "Bring Multiple Windows to your SwiftUI App" has more detail on how to take advantage of all the new scene types and features. Now that we've got control of windows, I'll pass it over to Franck, to put controls in windows. Franck: Thanks, Nick! This year, we have a variety of enhancements across all our APIs for building interactive content. We have a lot to cover, so let's get this party started with some fun enhancements to forms. macOS Ventura comes with a brand-new System Settings app, that features a streamlined navigation structure, built using the navigation split view and stacks that Nick just walked us through. It also sports a fresh and modern interface style. Settings interfaces are control-heavy, so this style was specifically designed to present forms containing many controls in a consistent and well-organized fashion. We've also adopted this new design within our Party Planner app. Let's take a look. Our Event Details view also features many different types of controls grouped into sections, serving a similar purpose as a settings interface. This makes it a great candidate to adopt the new visual style from System Settings.
You can enable this design using the new grouped formStyle on macOS. And thanks to the flexibility of SwiftUI's declarative APIs, content and controls within the form will automatically adapt to the new style. For example, sections will visually group their content below their headers; and controls will consistently align their labels and values to the leading and trailing edges. Some controls may adapt their visual appearance as well, such as how toggles display as trailing mini switches for consistent layout and alignment. And since the form itself provides a lot of visual structure, other controls adapt to this context with a lighter-weight visual appearance, and reveal more prominent control backings on rollover. SwiftUI makes it easy to align other types of content to this new style, using the new LabeledContent view, which can be used to build new controls or even just display some read-only information. In this case, we're displaying some text for the location of the event, and SwiftUI automatically adjusts the styling and allows selection of that text.
But LabeledContent can also wrap any kind of view, like if we wanted to use a custom view for displaying more entire addresses. SwiftUI is now smarter about applying default styling to text in other cases too. It will hierarchically format multiple pieces of text within a control's label to form titles and subtitles. This new form design looks great on macOS, but we can also share a lot of this same code with the iOS version of our app.
You'll notice some improved designs on iOS as well, like these pop-up menu pickers with a visual style inspired by macOS, but with their interactions and appearance optimized to fit beautifully within a touch-based interface. Of course, the same code works great on iPad's larger screen, and together with the Mac, you can see how SwiftUI's declarative model helps you share code when building shared interfaces, helping you bring the party to every platform. Of course, we're also improving controls beyond just form styles. So let's take a lightning-round tour of some other new control features we're using in the Party Planner app. Let's start with the New Activity page in our iOS app. Text fields can be configured to expand vertically using the new axis parameter, growing their height to fit the text and, if specified, capping their height to the line limit. But the lineLimit modifier now also supports more advanced behaviors, like reserving a minimum amount of space and expanding as more content is added, and then scrolling once the content exceeds the upper limit. Below our text fields, we also see an example of the new MultiDatePicker control, supporting noncontiguous date selection to help us spread our party activities throughout the week.
Now at this point, maybe you're having some mixed feelings about the party theme for this talk. The great news is you can now express those feelings in SwiftUI, using mixed-state controls! Here we have a group of toggles that can be collapsed into a single aggregate toggle. The inner toggles each take a single binding whereas the aggregate Toggle takes a collection of all the bindings displaying a mixed state if their values don't all match.
Pickers work the same way. This decoration theme picker changes its value to reflect the currently selected decoration. But if we select multiple decorations, it will show the themes for all them using a mixed-state indicator. Now, let's switch back to our iOS app. We have a few button-style toggles for choosing the event hashtags. We can help differentiate each toggle by simply adding a bordered button style. Button styles like this will now apply to any control that supports a button-like appearance, including toggles, menus, and pickers. Moving on to steppers, you can now provide a format for its value. On macOS, a formatted stepper will display its value in an editable field. And steppers are also now available on watchOS. Apple Watch sports one of my favorite new features: Accessibility Quick Actions, an alternative way to perform actions by clenching your hand. A Quick Action can be defined just like any other UI action, using a button, allowing us to share the same code for both visible buttons and their equivalent Quick Actions. All right, we just covered a lot of different controls, but of course, controls are not the only sources of interactivity. So let's take a look at what's new with larger interactive containers, like tables and lists.
I am excited to share that tables are now supported on iPadOS. As you would expect, tables on iPadOS are defined using the same Table API we introduced last year for macOS, making it easy to share code between platforms. Our Invitations table shows three columns for the name, city, and invitation status of each person, taking advantage of the iPad's large display. But this table will also render appropriately in compact size classes, including on iPhone, showing just the primary column within the smaller screen space. Let's switch contexts and check out this table on macOS. It's looking great! But speaking on contexts, I'd love to add some context menus for performing common actions within the table. This is a job for the new selection-based contentMenu modifier. The modifier takes a selection type, and will be enabled within any compatible table or list that supports selection. Within the menu builder, you are given a collection of the current selection, allowing you to build advanced context menus that can operate on a single selected row, multiple selected rows, or even no row selected, such as when clicking on the empty area of the table. Context menus reveal actions directly within the table, which is great for speed and efficiency. But I would also like to make these actions more discoverable. A great way to improve discoverability is by displaying common actions as buttons in the toolbar, and iPadOS has a new and improved toolbar design to help achieve that extra level of polish. iPad toolbars can now support user customization and reordering, which your app can implement by providing explicit identifiers for each toolbar item, the same API available on macOS. These identifiers allow SwiftUI to automatically save and restore custom toolbar configurations across app launches. Note that on iPadOS, not all toolbar items allow customization. Customizable actions are configured using the new secondaryAction toolbar item placement, which shows up in the center of the toolbar by default, or in an overflow menu in compact-size classes. All right! The word is spreading around and it looks like the number of attendees is growing exponentially. Let's help our table manage the scale by adding support for search. SwiftUI already supports basic search with a searchable modifier. And new this year, search fields can support tokenized inputs and suggestions to help build more structured search queries. To help with filtering results, SwiftUI now supports search scopes, which appear in a scope bar beneath the toolbar on macOS and as a segmented control within the navigation bar on iOS. We have only scratched the surface of what is possible with SwiftUI on iPad this year. Check out the "SwiftUI on iPad" series and learn more. Now that we have a bit more control over the event details and logistics, let's share the news and get people even more excited. Sharing content with other people, as well as sharing data across applications are essential parts of many apps. Taking advantage of these features makes your app even more integrated into the workflows of the people who use them. This year we have a few exciting areas to make that even easier. Let's start with PhotosPicker, a new multiplatform and privacy-preserving API for picking photos and videos. Since photos are an essential part of any party, I've added a feature to the Party Planner app that adds fun birthday effects to photos that were taken. The new PhotosPicker view can be placed anywhere in your app, and on activation, presents the standard photos-picking UI to select photos or videos from the user's library. PhotosPicker take a binding to a selected item, which provides access to the actual photo and video data.
It also has additional rich configuration options, such as filtering the type of content, preferred photo encoding, and more.
This is the most photogenic cupcake I have ever seen. But one cupcake isn't enough. Let's apply the special effect as we move on. Now that we have our customized photo, we're ready to share it with the new ShareLink API. Each platform has a standard interface for allowing people to share content from your apps. With watchOS 9, you can now also present the share sheet from within your watch apps. The new ShareLink view enables presenting that system share sheet from within your app. You can simply provide it with the content to be shared and a preview to use in the share sheet, and it automatically creates a standard share icon button.
On tap, it presents the standard share sheet to send off the content. Share links adapt to the context they're applied to, such as in context menus and across platforms. PhotosPicker, ShareLink, and more all take advantage of the new Transferable protocol, a Swift-first declarative way to describe how types are transferred across applications. Transferable types are used to power SwiftUI features like drag-and-drop, which makes it easy to drop images from other apps into the Party Planner gallery. This makes use of the new dropDestination API, which accepts a payload type, in this case, just an image. The completion block provides a collection of the received images together with the drop location.
Many standard types, such as string and image, already conform to Transferable. So it wasn't much work to get the ball rolling in our app, but you can easily take things further and implement Transferable in your own custom types. When it's time to do that, your conformance declares the representations appropriate for your type, such as using Codable support and a custom content type. To learn more about Transferable, other representations, and advanced tips and tricks, check out the "Meet Transferable" talk. While we were preparing the cupcakes, Nick was laying out all the supplies. Nick, how's it going over there? Nick: Almost done! I'm arranging these party horns in a completely custom layout, but I'll need a little more time. Let's talk graphics first. ShapeStyle has new APIs to achieve rich graphical effects this year. We'll use these APIs to give this guest card some party pop! Color has a new gradient property that adds a subtle gradient derived from the color. These look great with the system colors.
ShapeStyle also got a new shadow modifier. Adding it to the white foreground style adds a shadow to the text and to the symbol. And the detail of this shadow is remarkable. The drop shadow has applied to every element of the Calendar symbol.
With the whole world of SF Symbols and the new SwiftUI ShapeStyle extensions, you can make some absolutely gorgeous icons.
Now, it's time to bring that grid of SF Symbols to the party. We'll iterate quickly on it using SwiftUI Previews, which has some fantastic improvements this year. Previews have always been a convenient way to see a view in multiple configurations at the same time. With Xcode 14, we're making this easier than ever with preview variants. These let you develop your view in multiple appearances, type sizes, or orientations at the same time without writing any configuration code. We can use that same gradient again, or we can style it as an elliptical gradient to give these images a soft glow. and preview it in dark and light appearances.
Previews now runs in live mode by default. It can't be a great birthday party without a little dancing, so let's get these SF Symbols dancing. ♪ Electronic dance music ♪ ♪ Those jovial icons demonstrate something profound. SwiftUI has taken text and image animations to the next level. Let's watch that text animate again in slow motion. Text can now be beautifully animated between weights, styles, and even layouts. And the best part: this takes advantage of the same animation APIs used throughout the rest of SwiftUI. Let's close by talking about my absolute favorite part of UI programming, applied geometry -- or as we call it, Layout. SwiftUI has added new ways to lay out views. Grid is a new container view that arranges views in a two-dimensional grid. Grid will measure its subviews up front to enable cells that span multiple columns and enable automatic alignments across rows and columns. In fact, you already got a look at grid earlier.
Using Grid, GridRow, and the gridCellColumns modifier, you can build up a grid piecemeal. Of course, just like all layouts in SwiftUI, they're built for composition. We introduced SwiftUI's layout model with the first release, providing a toolbox of primitive layout types to achieve some of the most common layouts. Most of the time, you can get the job done with these primitive layout types, but sometimes, sometimes, you want that imperative layout code: the size, the minX, the frame.origin.x minus frame.midX divided by 2 plus 3. It's times like these when you should reach for the new Layout protocol. With it, you have the full power and flexibility we used to implement SwiftUI's stacks and grids to build your own first-class layout abstractions. Using Layout, I built this bespoke seating chart layout for the guests at our birthday party. Should our party guests sit in rows or pods? With the power of Layout, we don't have to choose. Using the Layout protocol, you can build all kinds of efficient layouts, tailored to the specific needs of your view hierarchies. To learn how to adopt Layout and about other new, great layout techniques, check out the "Compose custom layouts with SwiftUI" session. I've prepared a taste of Layout especially for you. Using the new AnyLayout type, I can switch between the Grid layout and a custom scattered layout I've written. As this session draws to a close, there's one surprise left: You're invited! ♪ You are invited to celebrate SwiftUI's birthday and all of the new APIs with us this week. There is a lot of detail left to explore in the APIs we covered, and even more APIs that we didn't have time to include. Enjoy the party, and enjoy WWDC 2022. And we are going to enjoy some cake. ♪ instrumental hip hop music ♪ ♪
Looking for something specific? Enter a topic above and jump straight to the good stuff.
An error occurred when submitting your query. Please check your Internet connection and try again.