Streaming is available in most browsers,
and in the Developer app.
-
What’s new in UIKit
Explore everything new in UIKit, including tab and document launch experiences, transitions, and text and input changes. We'll also discuss better-than-ever interoperability between UIKit and SwiftUI animations and gestures, as well as general improvements throughout UIKit.
Chapters
- 0:00 - Introduction
- 0:55 - Document launch experience
- 1:24 - Updated tab and sidebar
- 2:43 - Fluid transitions
- 3:35 - SwiftUI animations in UIKit
- 4:24 - Coordinated gesture recognizers
- 6:02 - Automatic trait tracking
- 7:44 - List improvements
- 11:18 - UIUpdateLink
- 12:55 - SF Symbol animations
- 14:36 - Sensory feedback
- 16:14 - Text improvements
- 18:14 - Menu actions
- 18:58 - Apple Pencil Pro and PencilKit
Resources
Related Videos
WWDC24
- Elevate your tab and sidebar experience in iPadOS
- Enhance your UI animations and transitions
- Squeeze the most out of Apple Pencil
- What’s new in SF Symbols 6
- What’s new in SwiftUI
WWDC23
WWDC21
-
Download
Hello and welcome to “What’s new in UIKit”! I’m Dima, a manager on the UI Frameworks team.
UIKit has many enhancements in iOS 18. In this video, I will guide you through: New key features and UI improvements, More integrations between UIKit and SwiftUI in the same app, As well as numerous general enhancements and API additions.
UIKit has major improvements that streamline the user interface, and make it more delightful to use.
I’ll guide you through 3 key features. I’ll go over document launch experience improvements, major updates to tabs and sidebar, as well as support for new, fluid transitions across the system.
First, there is a redesigned launch experience for document-based apps, enabling them to showcase their distinctive identity.
With full control over the launch view’s design, and first-class support for template document creation, you can gracefully guide people in creating their first document, all while maintaining a great browsing experience. To learn more about it, be sure to check out the video “Evolve your document launch experience”. Next, tab bars have visual updates, and have a new, combined sidebar experience and customization features. On iPadOS 18, tab bars have been refreshed with a new compact look that reduces the amount of empty vertical and horizontal space, bringing app content to the forefront.
Existing sidebar apps can adopt new UITabBarController APIs to get a combined tab and sidebar experience. When minimized, the sidebar animates back into the tab bar.
This keeps your app's content prominently displayed.
The new bars allow for quick navigation using the tab bar, while providing access to deeper sections of the app through the sidebar. The new bars also include customization features to allow people to personalize the sidebar and tab bar through drag and drop.
The new UITab and UITabGroup APIs enable apps to describe their structure to build a tab bar and a sidebar.
In addition, they adapt for a native experience on both Mac Catalyst and visionOS. To learn more, check out the video, "Elevate your tab and sidebar experience in iPadOS". Across iOS, transitions are used to link different parts of apps visually, while navigating through them. In iOS 18, there is a new zoom transition. It works with both navigation and presentations.
And it’s not just a new visual appearance, it is also continuously interactive, allowing you to grab and drag it around, from the beginning or during the transition.
In parts of your app where you transition from a large cell, the zoom transition increases the sense of continuity in your app, by keeping the same UI elements on screen across the transition. iOS 18 enhances the interoperability of SwiftUI and UIKit, making it easier to use them interchangeably in apps.
I’ll cover updates in two areas: animations and gesture recognizers.
First, an incredibly exciting update for animations! You can use a SwiftUI Animation type to animate UIKit views! This lets you use the full suite of SwiftUI Animation types, including SwiftUI CustomAnimations, animate UIKit views! In addition, this makes it easy to build fluid gesture-driven animations using the SwiftUI spring animation.
To use it, animate your views both when the gesture changes. and when it ends. This seamlessly maintains continuous velocity across the interactive, and non interactive parts of your animation. For an animated overview of this exciting update, check out Russell’s friendly video “Enhance your UI animations and transitions”. Animations are typically paired with gesture recognizers, and it’s now easier to coordinate gestures across UIKit and SwiftUI as well. The gesture systems have been unified in UIKit and SwiftUI, and they now adhere to consistent rules. In iOS 18, dependencies can be specified between gestures, across both frameworks. Here is an example of a SwiftUI hierarchy nested in a UIKit one, where I want the single tap gesture in UIKit to coexist with the double-tap gesture in SwiftUI.
Here, the gestures are recognizing at the same time. To prevent this from happening, I set a failure requirement between these two gesture recognizers. First, I specify a name when setting up the SwiftUI gesture: “SwiftUIDoubleTap”.
Then, within the UIKit delegate, I check the name of the other gesture recognizer to identify the one associated with the SwiftUI gesture. This way, the single tap gesture recognizer coming from UIKit will only fire when the double-tap SwiftUI gesture fails, achieving the desired effect.
In iOS 18, you can now add your existing UIKit gesture recognizers directly to SwiftUI hierarchies by using the new UIGestureRecognizerRepresentable protocol. See the video “What's new in SwiftUI” for more details on how to adopt UIGestureRecognizerRepresentable in your apps. Lastly, I’ll guide you through some general enhancements of UIKit.
The trait system in UIKit propagates data to the view controllers and views in your app’s hierarchy. In iOS 18, it's easier than ever to use traits and handle changes. UIKit now supports automatic trait tracking inside common view and view controller update methods, such as layoutSubviews and drawRect. When UIKit calls one of these supported methods, it records which traits you access inside that method. Then, when any of those traits change value, UIKit automatically performs the associated invalidation for that method, such as setNeedsLayout or setNeedsDisplay. In this example, I have a UIView subclass which overrides layoutSubviews, and reads the horizontalSizeClass trait from the view's traitCollection to determine which type of layout to use. Before automatic trait tracking, I would need to manually register for the horizontalSizeClass trait, and call setNeedsLayout on this view whenever it changes.
With automatic trait tracking in iOS 18, I can delete the manual trait change registration entirely! This is because when layoutSubviews is called, horizontalSizeClass trait usage is recorded.
And when that trait changes for this view, it automatically receives setNeedsLayout to update for the new value. Automatic trait tracking delivers maximum performance by only creating trait dependencies that are needed. This new feature is always active within supported update methods.
Refer to the documentation for the complete list of supported methods. Next, collection and table view APIs have been updated, making it easier to update your cells! All views in UICollectionView list sections and UITableViews now have the list environment trait set.
The list environment describes the style of the list that the view is in. Use this trait to ensure that cells are styled appropriately in any given list. UIListContentConfiguration and UIBackgroundConfiguration now take advantage of this new trait.
When updated for a new state, they adjust their properties to match the list environment from the configuration state’s trait collection.
This removes the need to know the style of the list when configuring a cell.
Instead, the cell configuration code only needs to know the style required by the content being represented, a regular cell, a header, or a footer. For example, consider the Browse tab in the Files app.
It uses a UICollectionView with compositional layout to display a list of locations, favorites, and tags in two different styles, depending on the context. In portrait, the Browse list uses the insetGrouped appearance. In landscape, the same Browse list is presented in a split view controller sidebar, and the Files app uses the sidebar appearance when configuring its UICollectionView’s compositional layout.
Here’s a function from the Files app that generates content and background configurations for a location in the Browse List. This is how the function was implemented in iOS 17.
It receives a file location struct as well as the list appearance as arguments. First, it checks whether the list appearance is the sidebar style and stores the result in the isSidebar local variable.
Then, it manually picks the content and background configurations based on the isSidebar variable.
Because the configurations were created manually, the cells using them needed to be manually reconfigured when the Browse list changed appearance, so this function would run again for the updated appearance.
In iOS 18, this function can be greatly simplified! The Files app uses the cell constructor for the content configuration, and the new listCell constructor for the backgroundConfiguration! When configurations are applied to a cell, they are updated for the cell’s configuration state. Since the new list environment trait is in the configuration state’s trait collection, these configurations now automatically update their properties to match the style of the list! For UIListContentConfiguration, the existing cell, subtitle cell, and value cell configurations now automatically update their appearance from the list environment trait.
New header and footer configurations do the same. For UIBackgroundConfiguration, there are 3 new constructors: listCell, listHeader, and listFooter.
These background configurations also update their appearance automatically from the list environment trait.
Take advantage of all these new list additions to simplify your code! UIUpdateLink is new in iOS 18, making it even easier to implement complex animations that require periodic UI updates.
If you’ve used CADisplayLink before, UIUpdateLink will be familiar.
It has more features, such as automatic view tracking, so the link automatically adjusts to the display that the view is on, as well as the ability to put the system in a low-latency mode for drawing applications.
In addition, it allows to achieve better performance and battery efficiency by using its advanced features.
Here’s an example of a view being animated up and down using a sine function: When I create a UIUpdateLink, I specify a UIView instance. UIUpdateLink activates automatically when the view is added to a visible window, and deactivates when the view is removed from it. In the update function, I use updateInfo's modelTime for update timing. In addition, I set requiresContinuousUpdates to true to ensure that the updateLink fires continuously while it’s enabled. When false, the update link fires only when something else drives updates, such as a gesture or layer changes.
For more information and more advanced use cases, go to the UIUpdateLink documentation page.
SF Symbols ensure a consistent appearance for toolbar icons, navigation bars, and other UI elements.
SF Symbols in UIKit are expanded with new symbol animations! There are three new animation presets in UIImageView and UIBarButtonItem. The .wiggle effect oscillates a symbol in any direction or angle to draw attention.
The .breathe effect smoothly scales a symbol up and down to indicate ongoing activity. The .rotate effect spins part of a symbol around a designated anchor point. The new .periodic behavior allows apps to specify both a repeat count, as well as a custom delay between repetitions. There’s also a new .continuous option that seamlessly animates the effect across repetitions, until the animation ends. Also, some of the existing presets have been enhanced with new features. The default .replace effect now prefers the new magic replace behavior, which smoothly animates badges and slashes. This behavior automatically falls back to a standard replace style if needed. For example, Magic Replace isn’t supported across the mic and video symbols, so the DownUp replace style is automatically used as a fallback. There is also new API to specify an explicit fallback style. In this case, the .upUp style.
If you’d like to know what else is up-up with symbols, like the updated SF Symbols app, the new annotations for variable color timing, and additional behaviors for bounce effects. Check out “What’s new in SF Symbols 6” And for a refresher on how to adopt symbol effects, check out “Animate symbols in your app”. Sensory feedback is a wonderful way to enhance iPhone apps. In iPadOS 17.5, this capability was expanded to iPad with Apple Pencil Pro and Magic Keyboard. UIFeedbackGenerator supports these new ways of providing feedback, and can be attached to a view as an interaction. When providing feedback, apps should now pass the location within that view where the feedback-triggering action occurred. There is also a new UICanvasFeedbackGenerator, ideal for iPad apps that have large drawing or art board views. I’ll go over how all of this comes together in an app. Consider a shape drawing app that provides feedback when shapes are dragged and snap to a grid.
This is a great use of UICanvasFeedbackGenerator. When the feedback generator is created, I associate it with a view.
And when the feedback is triggered, I pass in the location.
In this case, it’s the location from the gesture recognizer that triggered the alignment of the dragged shape.
Now when Apple Pencil Pro is used to drag the shape to align with a snapping guide, the pencil provides haptic feedback.
Keep in mind, feedback generators are not just for haptics.
Depending on the platform and settings, a generator may play haptics, audio, both, or neither.
Apps should always use the same generators on all platforms, regardless of the expected effect.
In iOS 18, text formatting capabilities are expanded. Take advantage of the new text formatting panel, providing a consistent, customizable experience for apps that offer text formatting options. UITextViews that allow editing text attributes have a new Edit menu action that brings up the new formatting panel, with a default set of options.
With text formatting, changing fonts and sizes, adding lists, and modifying other attributes is clear, and easy.
The formatting panel also supports a new text highlight feature.
It works by applying two new attributes. textHighlightStyle, for the range of text that should be highlighted, and textHighlightColorScheme, for the color used to render the highlight.
There are 5 predefined color schemes, in addition to the default, which uses tint color.
Customize available controls and layout of the formatting panel by setting a custom UITextFormattingViewController.Configuration, using UITextView’s new textFormattingConfiguration property. Opt out of new behavior by setting the property to nil. To tailor the presentation of the panel, use the new UITextFormattingViewController and its delegate.
Writing Tools is a great new feature that provides advanced text editing experiences.
UITextViews get the Writing Tools UI by default.
Editable text views get the full inline-editing proofreading and composition support, while non-editable text views get the overlay panel.
UITextView has additional API for tracking and modifying this user interface experience, including delegate notifications and a property for limiting the behavior. Menu actions provide all of an app’s commands in the macOS menu bar, and in the iPadOS and visionOS keyboard shortcut menus.
iOS 18 makes menu actions more useful for iPhone-only apps. Ready your apps with UICommand, UIKeyCommand, and UIActions to support other system invocations. UICommands, UIKeyCommands, and UIActions can be invoked by the system to control apps. For example, when your app is used through iPhone Mirroring, UIKeyCommands will be invoked from the Mac keyboard. To learn how to add commands to the main menu system, check out the video “Take your iPad apps to the next level”. Now, I’ll go over the additions to UIKit and PencilKit for integrating drawing experiences with Apple Pencil Pro, and for providing a rich tool picking experience with less code.
New in iPadOS 17.5, UIKit has support for all the great new features of Apple Pencil Pro.
The squeeze gesture is a quick way to switch tools, or show the picker when needed, right where the pencil is hovering. Updates to feedback generators work great with Apple Pencil Pro, elevating the experience of drawing and writing. UITouch and UIHoverGestureRecognizer provide barrel-roll angle, helping to make your app's drawing tools even more expressive.
And for all apps with undo support, squeezing Apple Pencil Pro presents an undo slider, the quickest way to work through undo history.
New in iPadOS 18 and visionOS 2, PKToolPicker now lets you define the available tools. You can use the tool picker with PKCanvasView, your own drawing canvas, or a combination of both! There is a new API to build the tools from your custom drawing canvas into the tool picker. With deep support for Apple Pencil Pro, there’s never been a better time to adopt PKToolPicker. Check out the video “Squeeze the most out of Apple Pencil” to learn all about the new Apple Pencil APIs. Wow! So many improvements! UIKit has certainly acquired an array of features, enhancing its capabilities even further.
What’s Next? Compile your app using the iOS 18 SDK. Adopt the new UIKit features Take advantage of the improvements to transitions and animations, tab bars, as well as the new document launch experience And continue to experiment with new ways to integrate both UIKit and SwiftUI in your app! Thank you!
-
-
0:01 - Using SwiftUI to animate UIViews with gestures
switch gesture.state { case .changed: UIView.animate(.interactiveSpring) { bead.center = gesture.translation } case .ended: UIView.animate(.spring) { bead.center = endOfBracelet } }
-
0:02 - Setting failure requirements between gestures
// Inner SwiftUI double tap gesture Circle() .gesture(doubleTap, name: "SwiftUIDoubleTap") // Outer UIKit single tap gesture func gestureRecognizer( _ gestureRecognizer: UIGestureRecognizer, shouldRequireFailureOf other: UIGestureRecognizer ) -> Bool { other.name == "SwiftUIDoubleTap" }
-
0:03 - Responding to horizontalSizeClass trait
class MyView: UIView { override func layoutSubviews() { super.layoutSubviews() if traitCollection.horizontalSizeClass == .compact { // apply compact layout } else { // apply regular layout } } }
-
0:04 - Using the new automatic content and background configurations
func configurations(for location: FileLocation) -> (UIListContentConfiguration, UIBackgroundConfiguration) { var contentConfiguration = UIListContentConfiguration.cell() let backgroundConfiguration = UIBackgroundConfiguration.listCell() contentConfiguration.text = location.title contentConfiguration.image = location.thumbnailImage return (contentConfiguration, backgroundConfiguration) }
-
0:05 - Using UIUpdateLink
let updateLink = UIUpdateLink( view: view, actionTarget: self, selector: #selector(update) ) updateLink.requiresContinuousUpdates = true updateLink.isEnabled = true @objc func update(updateLink: UIUpdateLink, updateInfo: UIUpdateInfo) { view.center.y = sin(updateInfo.modelTime) * 100 + view.bounds.midY }
-
0:06 - An example of providing UICanvasFeedbackGenerator with additional context
@ViewLoading var feedbackGenerator: UICanvasFeedbackGenerator override func viewDidLoad() { super.viewDidLoad() feedbackGenerator = UICanvasFeedbackGenerator(view: view) } func dragAligned(_ sender: UIPanGestureRecognizer) { feedbackGenerator.alignmentOccurred(at: sender.location(in: view)) }
-
0:07 - Using new attributes for highlight
var attributes = [NSAttributedString.Key: Any]() // Highlight style attributes[.textHighlightStyle] = NSAttributedString.TextHighlightStyle.default // Highlight color scheme attributes[.textHighlightColorScheme] = NSAttributedString.TextHighlightColorScheme.default
-
0:08 - Customizing formatting panel
textView.textFormattingConfiguration = .init(groups: [ .group([ .component(.fontAttributes, .mini), .component(.fontPicker, .regular), .component(.textColor, .mini) ]), .group([ .component(.fontPointSize, .mini), .component(.listStyles, .regular), .component(.highlight, .mini) ]) ])
-
-
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.