Explore enhancements and updates to UIKit and learn how to build better iOS, iPadOS, and Mac Catalyst apps. We'll show you the latest features and improvements in UIKit and share API refinements, performance improvements, and much more.
♪ ♪ Dima: Hello, and welcome to "What's new in UIKit in iOS 17”. I'm Dima, an engineering manager on the UIKit team. UIKit, the powerful framework behind your applications, has been upgraded to support new features for iOS 17. In this video, I will guide you through: New key features and core architectural improvements, advances in building interfaces for all users irrespective of the language setting, improvements for iPadOS apps, as well as numerous general enhancements included in the release.
We've introduced major architectural enhancements to UIKit, making it easier to create powerful applications, as well as dramatically improving integration with SwiftUI. I am going to guide you through 5 key new features. I'll go over the Xcode previews support, view controller life cycle updates, advances in the trait system, animated symbol images, and a new API to represent empty state in your apps.
First, a big change. You can use Xcode previews directly with UIKit. To take advantage of this feature, use the Preview macro to specify the name of the preview and return a view controller. I can set any properties on the view controller just to configure and populate the preview with data.
You can also preview UIViews directly, no view controller necessary. Previews help you visualize UI components and give immediate feedback as you iterate on your code. And once your app has been created, Xcode Previews enable testing across an array of configurations and settings. Next, I'd like to cover an important improvement to the view controller lifecycle during appearance transitions, such as when you present a view controller, or push or pop in a navigation controller. There's a new view controller callback named viewIsAppearing, which is called after viewWillAppear but before viewDidAppear. viewIsAppearing is the best place to do things each time the view appears. When it is called, both the view controller and the view have an up-to-date trait collection. Additionally, the view has been added to the hierarchy and has been laid out by its superview. This makes viewIsAppearing an ideal callback to run code that depends on the view's initial geometry, including its size. Lastly, this new viewIsAppearing method back-deploys all the way to iOS 13, so you can take advantage of it even if your app runs on older versions of iOS.
Here is an illustration of how the new viewIsAppearing callback fits in with some other key events during a typical view controller appearance transition. I'd like to point out a few things.
First, note how viewWillAppear gets called before the view is added to the hierarchy, and before layout begins. This is why it's too early to use the trait collection, or to do anything that depends on the view's size or other geometry.
Next, notice how viewDidAppear is called in a separate CATransaction at the end, after any animations take place. This means any changes you make in viewDidAppear don't become visible until the transition completes, so it is too late to make changes you want visible during the transition. On the other hand, viewIsAppearing is called within the same transaction as viewWillAppear. This means any changes you make in either of those callbacks become visible to the user at the same time, right from the very first frame of the transition.
Finally, though their timing may be similar, there's a key difference between viewIsAppearing and layout callbacks like viewWillLayoutSubviews.
Layout callbacks are made whenever the view runs layoutSubviews, which can happen multiple times during the transition, or any time later on while the view is visible.
But viewIsAppearing is only called once during the appearance transition, and it still gets called even if the view doesn't need layout. This is why I like to think of viewIsAppearing as the Goldilocks callback: it's not called too early, or too late, or too often. It is just right. The trait system in UIKit has been upgraded in iOS 17. Traits automatically propagate data through your app's hierarchy. UITraitCollection contains many system traits, such as user interface style, horizontal and vertical size classes, and preferred content size category.
Now you can define custom traits to add your own data to UITraitCollection. This is an entirely new way for you to propagate data to the views and view controllers in your app.
We've also added new trait override APIs to easily modify trait values on any view or view controller.
You can also adopt more flexible APIs to receive callbacks when traits change value, instead of needing to override traitCollectionDidChange in a subclass.
Finally, you can bridge custom UIKit traits with custom SwiftUI environment keys to seamlessly pass data between UIKit and SwiftUI components in your app.
To learn all about these exciting new enhancements, check out the video "Unleash the UIKit trait system".
Across all our platforms, SF symbols enable a consistent look for toolbar icons, navigation bars, and other UI elements. They are designed to automatically align with text labels and can be easily customized for weight, scale, and appearance to match your app's design. In iOS 17, UIKit supports animated symbols with the new symbol effects API. These effects can be applied to any symbol image, even custom ones.
To apply symbol effects, use the new addSymbolEffect() method on UIImageView. Here, I add a bounce effect, which causes the symbol to bounce a single time. Now I'll add a variable color effect. Unlike bounce, the variable color effect animates indefinitely when added. Use the removeSymbolEffect() method to end the effect. Finally, I can use the new setSymbolImage() method to perform a transition effect across symbols.
There's a lot more to symbol effects than the three features I went over. Check out the video "Animate symbols in your app" to learn more. Next, we've added a new API to make it easy to represent empty states. Empty states are moments in your app where there is no content to display.
They typically occur upon the first launch of your app, as no content has been created. They also arise when your app can't display content due to a limitation, such as a lack of Internet connection. UIContentUnavailableConfiguration is a composable description of an empty state, and can be provided with placeholder content, such an image or text. In this example, I inform that there are no favorite translations to display. To represent this empty state, I set the configuration as the view controller's contentUnavailableConfiguration. In addition to the .empty() configuration, UIKit offers the .loading() configuration to represent content that is being prepared. What's more, you can leverage the UIHostingConfiguration API to represent your app's empty state with a SwiftUI view. This works just like using UIHostingConfiguration with cells.
The best place to update your view controller's content unavailable configuration is inside the new method, updateContentUnavailableConfiguration (using: state).
This example uses the .search configuration which has been designed for queries that return no results. The configuration provides localized primary and secondary text, with the query interpolated from the nearby search controller.
Whenever the availability of content in your view controller changes, call setNeedsUpdateContentUnavailable Configuration to request an update. Across all Apple platforms, it is essential to deliver a consistent, high-quality experience, irrespective of the language setting. To facilitate that, we've made significant advancements in the area of fonts and text rendering.
In this section I will tell you about the dynamic line-height adjustments that help prevent clipping and collision of text in certain fonts and languages. You'll also learn about the improved line-breaking and hyphenation rules, as well as the new API to request images based on the locale. First, a closer look at fonts and their metrics.
Font metrics are defined using several terms. The baseline represents an imaginary line upon which letters or words rest. The line-height refers to the space between these baselines. And, the x-height is a line that sits atop lowercase letters.
Some fonts have ascenders and descenders that extend beyond these lines. Ascenders are the parts of a font that extend above the x-height. Descenders, on the other hand, hang below the baseline. For some languages like Arabic, Hindi, and Thai, these elements require significantly more vertical space than Latin letters, leading to possible collisions or clipping issues. To prevent the overlapping of ascenders and descenders in all languages, we introduced a dynamic line-height adjustment feature. This ensures that text elements, such as UILabels, automatically adjust their line-heights and vertical dimensions for optimal readability. We also made substantial enhancements to line-breaking behavior for languages such as Chinese, German, Japanese, and Korean.
These improvements apply different rules based on what kind of text style you're using.
This will work automatically in most cases, as long as you adopt text styles, but for more information about best practices and how to make sure your app works with all languages, check out "What's new with Text and Text Interactions." In certain situations, a significant portion of the UI may be displayed in a language that differs from the user's selected language. For example, when the content comes from the web. In these cases, you can use the new typesetting language trait to indicate the interface's language, which will help adjust line-height and hyphenation rules accordingly. UIKit now supports accessing specific localized variants of images. For example, the character.textbox SF Symbol has eight different locale-based variants.
By default, UIKit pulls the variant matching the current language setting on the device. So if the current language is U.S. English, then the Latin variant is displayed.
On iOS 17, apps can request specific variants by providing a Locale in the image's configuration. Here, I look up the Japanese version of the symbol by providing a configuration with a Japanese locale. With all of these changes to text rendering and locale support, your apps can feel closer to home for everyone.
Now, I'll take you through improvements for building apps for iPad.
I'll cover improvements in 5 areas: a new window dragging interaction, enhanced sidebar behavior in Stage Manager, keyboard scrolling support, advancements in building document-centric apps, and the new Apple Pencil features and APIs.
In iOS 17, we've updated the window dragging functionality in Stage Manager by expanding the area in which the drag gesture can begin.
Now, dragging anywhere inside of a UINavigationBar will start moving a window. This gesture plays well with other gesture recognizers that might be present in your app, such as pan or swipe gestures. If you're not using a UINavigationBar as part of the UI in your app, you can adopt UIWindowSceneDragInteraction and add it to any view. You can also set up gesture relationships with other pan gestures in your app to make sure there aren't any conflicts. This also works with Mac Catalyst right out of the box. Column-style UISplitViewControllers have gained graceful new resizing behavior in Stage Manager. Sidebars are automatically hidden when necessary, and they'll remain hidden until specifically requested to be shown. When sidebars are requested at narrower widths, UISplitViewController uses overlay or displace behavior as necessary.
An overlaid sidebar persists as the window resizes larger. When dismissed and recalled at the larger width, it will come back tiled. Triple-column split view controllers, such as in Mail, behave similarly. This new behavior happens with UISplitViewControllers created with the double-column or triple-column style. To summarize: the automatic behavior tiles the columns whenever possible, hides sidebars as necessary when width is decreased, overlays or displaces the secondary column with the sidebar if there's not enough room to tile when the sidebar button is tapped, and you can override the behavior in your application using preferredDisplayMode and preferredSplitBehavior. In iPadOS 17 we've improved the support for document-centric apps. UIKit offers a new UIDocumentViewController that serves as the base class of your content view controller. It ensures a system default experience and offers many features without additional adoption, such as automatically configuring the title menu, sharing, drag and drop, key commands, and more. Additionally, UIDocument now conforms to UINavigationItemRenameDelegate and offers a full renaming experience when set as the rename delegate of the view controller's navigation item. To learn more about these and other new features for apps focused on document management, check out 'Build better document-based apps'. Apple Pencil adds an extra facet to iPadOS apps and there are a lot of new APIs as well.
With the new iPad Pro and iOS 16.4, we introduced hover with Apple Pencil. To capture hover from the pencil you can use UIHoverGestureRecognizer. The z offset reflects the normalized hover distance from the screen, ranging from 0 to 1. You can also capture the altitude and azimuth of the pencil while in hover range to accurately render the preview of what your brush stroke might look like on screen.
With pencil hover, you can also hover across the home screen, and toolbar icons in apps. If you're using UIPointerInteraction, no additional adoption is required. However, it's worth noting, the visual interactions when using mouse or trackpad input versus Apple Pencil input are slightly different. For example, pointer styles such as the system pointer aren't visible while using Apple Pencil.
Make sure to try out pencil hover with your app.
In iOS 17, PencilKit becomes even more expressive and introduces new inks. The monoline pen is great for detail, giving you a consistent sized width. The fountain pen mimics calligraphy, with thick downstrokes and thin upstrokes. Watercolor allows for beautiful strokes and expressivity. And crayon is a fun addition. With the new inks, keep backward compatibility in mind. Previous versions of iOS cannot load the PKDrawings that contain the new inks.
A new content version property on data model types like PKDrawing, PKStroke, and others indicates which PencilKit version is required to load the object. A content version of 1 denotes inks that shipped in iOS 14 and 2 is for the new inks in iOS 17.
To provide a good user experience, use this API to detect incompatibility and provide a message or render a fallback image. When maintaining backwards compatibility isn't possible, use the new maximumSupportedContentVersion API to limit which features are available via the canvas and toolpicker.
To make iPads even more powerful when paired with a hardware keyboard like Magic Keyboard, we have added support for keyboard scrolling. New in iOS 17, UIScrollViews can be scrolled using Page Up, Page Down, Home, and End keys, if available. You can override this behavior using a new API on UIScrollView, allowsKeyboardScrolling. Lastly, I'm going to guide you through general enhancements we've made in multiple areas of UIKit.
I'll tell you all about 8 general enhancements: collection view improvements, new spring animation parameters, text interactions, and more.
I'll start with collection views which have been greatly optimized, with many performance improvements in iOS 17. These graphs show how much faster collection view is in iOS 17 when performing operations with a large number of items.
iOS 17 is nearly twice as fast as iOS 16 to invert the sort order of a collection view containing ten thousand items, and it's almost three times as fast to perform an update that deletes half those items. What's more, when you perform updates without animations, collection view performance is improved even further. Whether you're applying snapshots to diffable data source, or manually performing batch updates, collection view is faster across the board in iOS 17. These improvements make your app feel more responsive and result in fewer hitches in your apps. Now, I'll talk about a powerful new feature in Compositional Layout, by first starting with an example of a fairly typical layout. Here is the brand new Health app on iPad, where the favorites section is using a compositional layout with rows of 2 items, all self sizing using NSCollectionLayoutDimension.estimated. Notice how the medications cell has a height that doesn't match that of the cell next to it. This would look much better if the items in this row had the same height.
In iOS 17, Compositional Layout gets a brand new layout dimension: uniformAcrossSiblings.
This new feature allows self-sizing items in your layout to receive a consistent size based on the size of the largest item. When you need this kind of layout, simply replace your estimated dimensions with uniformAcrossSiblings. Keep in mind, when you use this feature, it requires all sibling items to be created and sized to determine the size of the largest item; so avoid using it when you have large numbers of items in a group.
Back to this example of the Health app. There are two items in this group with different item heights. We updated all the items in this layout to use uniformAcrossSiblings, so the Medications cell grows to match the height of the Sound Levels cell, getting the layout we want. Next, for spring animations, we've been refining a new way to specify parameters that is easier to understand and to work with.
It uses just 2 parameters: duration and bounce.
The duration defines how long until you perceive the spring animation to settle, not how long the animation takes to fully complete, and it is independent of bounce. And increasing the bounce from zero adds bounce to the animation, without changing how long the animation feels.
We've added a new method on UIView that takes these spring parameters. And all of them are optional, so now you can even write just "animate" and get a spring animation that matches the system default.
Watch the “Animate with Springs” talk for more insight into this new way of describing springs.
Next, I'll cover new features and APIs for interacting with text. We've made some significant improvements to the text cursor and text selection UI in iOS 17, including a new redesigned selection loupe. Developers who have custom text views, for example word processors, can now use the system-provided views for selection UI without adopting all of UITextInteraction.
Text item interactions in text views are now more customizable through new APIs on UITextViewDelegate, making it possible to modify the primary action or menu for text items like links or text attachments.
Moreover, you can also tag custom ranges of the content to enable interactions on them, making it easier to add actions or menus to text that are not links.
To learn more about the text cursor improvements and the text item actions and menus, watch "What's new with text and text interactions." Now I am going to provide an update on a well-established element of iOS: the status bar. The status bar styling on iOS is controlled by the application under it, with a default style that switches based on the app or view controller being in dark or light mode. There are cases with user content that can be tricky to get right to ensure contrast.
The default style here is dark because the app is using a light user interface. But some of the user content is dark.
Now, in iOS 17, the default style continuously adjusts to the content of the app and automatically changes between dark and light styles in order to maintain contrast. It even allows the status bar to spilt styles when needed.
Since apps no longer need to specify dark and light explicitly for all of these cases, there are opportunities to remove customization code and make use of the default style. Drag and drop is getting more powerful in iOS 17. Supported files and content can now be dropped onto icons on the Home screen and opened directly in the respective apps. This will work automatically today for many document-based apps without any changes. The system uses CFBundleDocumentTypes as defined in your app's Info.plist file to determine if the dropped file is supported. On drop, the files are opened using the existing scene delegate methods, just like any other URL. Simply make sure your app defines its supported document types to opt into this feature. UIKit adds support for ISO HDR Images, allowing you to easily display these images with UIImageView, and to manipulate them with UIGraphicsImageRenderer.
Additionally, the new UIImageReader gives you more control when loading images, including converting some HDR image formats, such as those from the Camera Roll to ISO HDR. For more information check out the session "Support HDR images in your app." UIPageControl has gained new features to represent fractional page progress. Today, page controls are commonly used in apps to display slideshow content that automatically page on a set duration, or along video content. With the new progress and timer progress API, you can now represent the fractional page progress in the active indicator to provide better context on when the page will change. To set up a fractional progress page control, simply set the new progress property on UIPageControl with a progress object.
UIPageControlTimerProgress has a built-in timer to make it easy to configure each page's duration.
UIPageControl will automatically change its page when the timer duration is met.
For pages that need to follow video players or external timers, which have their own source of truth, use the base UIPageControlProgress type to manually update the currentProgress value as the content progresses. iOS 17 and macOS Sonoma introduce Palette Menus.
Palettes are a row of menu elements generally used for choosing from a collection of items. This style of control can be found in the Books app on iOS, or in Mail and Finder on the Mac. Now it's available as a first class control in UIKit. To turn any menu into a palette, just add .displayAsPalette to its options like this.
Since elements in a palette are relatively small, selection isn't indicated with a checkmark, as it is in regular menu elements. Instead, UIKit will choose the appropriate selection indicator based on the provided image. If all elements in a palette use monochromatic SF Symbols or template images, the selected element is tinted with the app's tint color. If the elements have multi-colored SF symbols, a tint-colored stroke is drawn around the selected one. If you're using entirely custom images for your menu elements, or if you'd like to override the built in behavior by providing your own selection indicator, you may use the new selectedImage property on the UIMenuLeaf protocol. In this example, the selectedImage is being set in the UIAction's initializer.
UIKit's menu APIs are available on iOS, iPadOS, and Mac Catalyst, allowing you to build complex menus with the same familiar API. And starting with tvOS 17, all of the same APIs are available on Apple TV with a brand new appearance and native tvOS behaviors. Wow! We've covered a lot of ground. UIKit has certainly acquired an array of features, enhancing its capabilities even further.
What's Next? Compile your app using the iOS 17 SDK. Incorporate the new UIKit features and take advantage of Xcode previews in your projects. And ensure that your UIs are flexible to accommodate varying text metrics in non-Latin languages. I hope you enjoyed the brief overview of these topics. For a more in depth look, check out the related videos. Thank you. ♪ ♪