WWDC23 — What’s new in UIKit / SwiftUI

ganeshrajugalla
12 min readJun 9, 2023

--

UIKit

Key features

Xcode previews

Xcode previews can be summarized in a single picture.

It can be UIView as well as UIViewController.

View controller lifecycle updates

A life cycle function is added.

UIViewController.viewIsAppearing(_:)

This function is called between viewWillAppear(_:)and .viewDidAppear(_:)

viewIsAppearing(_:)is a good function to update the UI just before the view is shown on the screen. To be precise at this point,

  • Updated traitCollection of view controllers and views.
  • The view is added to the superview and displayed.

I can express it like this. viewIsAppearing(_:)Inside, it's suitable for code that specifies position and size, etc.

viewIsAppearing(_:)is available since iOS 13.

viewWillAppear(_:)is too fast to size or position. This is because the views are just starting to be included in the superview. viewDidAppear(_:)is performed after Transaction animates. I also viewDidAppear(_:)felt that the update of the view was a bit slow.

I have experience using layoutIfNeeded() because of this problem, viewIsAppearing(_:)but I don't know if this new answer can be used. viewIsAppearing(_:)Since viewWillAppear(_:)corresponds to the same transaction time as , it will be able to provide a more natural view to the user.

For reference, you can check the viewWillLayoutSubviews(), in the capture. viewDidLayoutSubviews()These two callbacks layoutSubviews()are executed together when a view executes , but a newly created viewIsAppearing(_:)callback is executed only once in the life cycle of a view controller.

Anyway, I guess I’ll have to try it out.

Trait system enhancements

Starting from iOS 17, the trait system is improved.

You can now store custom traits in a UITraitCollection. You can also store data here.

Changes in traits can also be captured with traitCollectionDidChange implemented by subclassing.

These custom traits are also available in SwiftUI.

Details are covered in Unleash the UIKit trait system.

Animated symbol images

Literally. Icons found in SF Symbol are static, but animations can be added.

// Flinch animation. Executed only once.
imageView.addSymbolEffect(.bounce)

// An animation that repeats multiple colors. Repeat until stopped running.
imageView.addSymbolEffect(.variableColor.iterative)

// Stop the above animation.
imageView.removeSymbolEffect(ofType: .variableColor)

// Add animation when switching to another symbol. Executed only once.
imageView.setSymbolImage(pauseImage, contentTransition: .replace.offUp)

Looking at the official documentation, it was confirmed that this is possible starting with iOS 17.

In addition to the above 3 functions, many animations are prepared. Details are covered in Animate symbols in your app.

Empty states

At first, I wondered if there was talk of a state-based architecture, but it was really about a screen that is displayed when there is nothing to output on the screen.

This screen represents a kind of limited situation instead, and in the presentation, it was called ‘Internet connection status’ as an example.

Placeholder content (text, image, description) can be displayed through UIContentUnavailableConfiguration.

You are assigning this object to your viewController.

Where can I do this setting? viewDidLoad?? A new method appears.

updateContentUnavailableConfiguration(using:)to configure and assign a UIContentUnavailableConfiguration. This time, the 'no data' state is displayed. If the searchResults property is empty, the Empty state screen is displayed.

As you can see, after reflecting the query to searchResults, setNeedsUpdateContentUnavailableConfiguration()you can set the screen differently according to the result value by calling .

Note that this feature is available starting with iOS 17.

Internationalization

First of all, before talking about this, let’s start with the terminology about Font.

  • x-height = any line above lowercase letters
  • baseline = the line all characters sit on in common
  • line-height = height between baseline and baseline
  • Ascenders = parts that protrude above the x-height line
  • Descenders = the part that protrudes below the basline line

If there is only this distinction, there is no problem rendering text on the screen. The example above is English, but Arabic, Hindi, etc., unlike English, have a lot of Ascender / Descender.

If Ascender / Descender is highly prominent, the text may overlap.

Therefore, text elements such as UILabel recognize language and adjust to have various structures. This will happen automatically according to the user.

I don’t know because I didn’t mention it, but it seems to depend on the user’s regional settings. The reason for this thought was inferred from the part where some text elements are set below.

If you need to display Thai language between Korean contents, you can set the trait like this. You can use this new typesettingLanguage(iOS 17) property.

A function to show multiple versions of images through SF symbols has also been added. This is a code example that controls SF symbols using Locale.

Details are covered in What’s new with text and text interactions.

Improvements for iPad

Talk about Stage Manager. It is to display only one app on the screen, but personally, I often use it when I need to hold and read a long blog post.

Stage Manager is also available on the iPad. My iPad is not the Apple silicon version, so it is not possible, but the iPad Air, Pro, etc. with Apple silicon will be possible.

The window opened using this Stage Manager can be moved and resized by dragging.

There are two ways to apply this feature.

  • When using UINavigationBar, apply PanGesture to UINavigationBar.
  • If there is no UINavigationBar, use UIWindowSceneDragInteraction.

The presentation recommended a column-style UISplitViewController. If the size of the window is reduced, the SideBar disappears and can be called up temporarily whenever needed.

You can arbitrarily adjust SideBar behavior by overriding UISplitViewController’s preferredDisplayMode and preferredSplitBehavior.

The new UIDocumentViewController in iOS 17 automatically sets the title or supports sharing, drag and drop, and key commands on a system-based basis. Since UIDocument objects implement UINavigationItemRenameDelegate, rename UI/UX is also improved.

Details are covered in Build better document-centric apps.

The new iPad Pro and iOS 16.4 (why iOS?) introduced the Apple Pencil hover gesture (I didn’t know…). This is thanks to the UIHoverGestureRecognizer.

The screen-to-pencil distance is normalized to 0–1 via the zOffset property, and the altitudeAngle and azimuthAngle properties preview which view will be drawn.

Along with this, PencilKit’s ink has also been added.

These inks contain PKDrawing data, but cannot be loaded in previous versions of iOS.

It is necessary to match the iOS version through the version of various data models such as PKDrawing and PKStroke. Note that version 1 is version 14 and version 2 is version 17.

Starting from iOS 17, UIScrollView’s scroll functions such as Page Down, Page Up, Home, and End can be used on the keyboard. Let’s use UIScrollView’s allowsKeyboardScrollingAPI.

General enhancements

Collection view improvements

I did something and it worked really well.

Originally, there were many blog posts discussing the performance degradation of UITableView, UICollectionView, etc. In the process of reusing internal cells, the cost of running a new auto layout engine is incurred and the cost goes up to the ceiling. To solve this problem, libraries such as FlexLayout were used.

From this iOS 17, it is said that a performance improvement of more than 50% has been confirmed as a bar tested through a huge amount of data.

Of course you have to do this to know.

UICompositionalLayout, which easily arranges cells in a Grid Layout format using CollectionView, also has improvements.

The NSCollectionLayoutDimension.estimated property is used, but the heights of the two cells do not match.

Added NSCollectionLayoutDimension.uniformAcrossSiblings. Set the layout size based on the largest cell. It is not suitable for all situations, so the developer’s choice is required.

Spring animation parameters

You can create Spring animation. Spring animation has two parameters.

  • duration: time until spring animation starts
  • Bounce: Time for spring animation to run

In other words, duration is not directly related to spring animation.

// Using the new UIView spring animation API
UIView.animate (springDuration: 0.5, bounce: 0.0) {
circle.center.x += 100
}

// parameters are optional
UIView.animate {
circle.center.x += 100
}

For more details, you can refer to Animate with Springs.

Text interactions

There have been improvements to the cursor, text selection, and selection loupe (the ability to zoom in on a specific part of a text view when you hold your finger over it).

Word processing developers can take advantage of system-based views. You don’t need to create your own UITextInteraction here.

UITextView has been improved to make it more customizable. UITextViewDelegate has also been used to improve user response and text menus (links or text attachments, etc.).

For details, please check What’s new with text and text interaction.

Default status bar Sytle

Improvements have been made to the part that informs the time or Wi-Fi status of the iPhone notch.

The color changes depending on the contents overlapping the status bar.

Drag and drop enhancements

You can drag and drop a downloadable file or image onto the home screen and use it to open another file.

You can set the file type by finding the value of CFBundleDocumentTypes in the Info.plist file. When the app opens, use the UISceneDelegate method.

ISO HDR image support

It is said that UIKit supports a kind of image called ISO HDR.

This is covered in detail in Support HDR images in your app.

Page Control

A function to show a slide show for a set duration has been added to UIPageControl.

Using UIPageControlProgress and UIPageControlTimerProgress, not only photos but also videos can be displayed in the form of a slide show.

// Setting up a UIPageControlTimerProgress
let timerProgress = UIPageControlTimerProgress (preferredDuration: 10)
pageControl.progress = timerProgress

timerProgress.resumeTimer()

Palette menus

In addition to iOS 17, a new Palette Menu has been added to macOS Sonoma.

Impressive…

If you want to add such a menu, you can add displayAsPalette as shown below.

UIMenu(options: [.displayInline, .displayAsPalette], children: [...])

SwiftUI

SwiftUI in more places

It refers to visionOS where ARKit and RealityKit are used.

The screen displayed by visionOS has three components.

  • window: 2D screen seen in visionOS
  • volume: puts the same volume as an object on the screen so that it can be touched and moved
  • space : the entire screen the user experiences using the above two

To create a window, do the following:

You can put multiple container views in the WindowGroup as shown below.

If you want to add volume here, you can apply viewModifier to WindowGroup.

For details, see Meet SwiftUI for spatial computing.

There were also significant improvements in WatchOS 10, which further improved the user experience by providing different views for each container view overall.

A lot of improvements have been made to the background. You can make the background that goes in and out depending on the content into a containerBackground.

CityDetails(city: city)
.containerBackgroiund(for: .navigation) {...}

Toolbar items have also been added as shown below.

Following this, contents about DataPicker, List, Widget, MapKit, Swift Charts, and In-app purchasing appear. Most of them were Less code more outcomes, so I won’t mention them separately.

Simplified data flow

The @Observable macro was introduced.

@Observable
class Dog: Identifiable {
var id = UUID()
var name = ""
var age = 1
var breed = DogBreed.mutt
var owner: Person?
}

If we just apply the above Dog object to the view, the view will react to changes in that object and update the view. Compared to using @ObservableObject and @ObservedObject before, it is much simpler.

Now, it is possible to display state values ​​using only @State and @Environment in the view.

You can use @State to make an object Read-Write an @Observable.

In addition, objects passed to Environment can be received as Environment dynamic properties.

@main
struct WhatsNew2023: App {
@State private var currentUser: User?

var body: some Scene {
WindowGroup {
ContentView()
.environment (currentUser)
}
}
}

@Observable final class User { ... }


struct ProfileView: View {
// Environment dynamic property. custom key also possible
@Environment (User.self) private var currentUser: User?

var body: some View {
if let currentUser {
UserDetails (user: currentUser)
} else {
LoginScreen ()
}
}

More details will be covered in Discover Observation with SwiftUI.

SwiftData

SwiftData is a new data storage framework. Objects can easily be made into data models.

// SwiftData model
import Foundation
import SwiftData

@Model
class Dog {
var name = ""
var age = 1
var breed = DogBreed.mutt
var owner: Person?
}

In the @Observable example above, only the @Model part has been changed. This does not lose the functionality of @Observable .

Now let’s look at how to save and load data.

import SwiftUI
import SwiftData

@main
struct WhatsNew2023: App {
var body: some Scene {
WindowGroup {
ContentView()
}
.modelContainer(for: Dog.self)
}
}

First of all, model container and model type are defined using modelContainer.

import SwiftUI
import SwiftData

struct RecentDogs: View {
@Query(sort: \.dateSpotted) private var dogs: [Dog]

var body: some View {
ScrollView {
LazyVStack {
ForEach (dogs) { dog in
DogCard (dog: dog)
}
}
}
}
}

Load model data using @Query . You can do sort as above, and if you don’t pass those parameters, all of them will be called.

See Meet SwiftData for more information.

In addition to this, explanations about Inspector, Dialog, Table, and List appear frequently. I think you can find it and deal with it whenever you need it, so I’ll keep it short here.

Extraordinary animations

Through KeyframeAnimation, various properties can be reflected in the view at once to execute animation.

After passing an object with animatable properties and a state value, define a closure that creates a view and defines how the previously passed property will be changed in the next closure.

KeyframeAnimator(
initialValue: LogoAnimationValues (), trigger: runPlan
) { values in
LogoField(color: color, isFocused: isFocused)
.scaleEffect(values.scale)
.rotationEffect(values.rotation, anchor: bottom)
.offset(y: values.verticalTranslation)
} keyframes: { _ in
KeyframeTrack(\.verticalTranslation) {
SpringKeyframe(30, duration: 0.25, spring: smooth)
CubicKeyframe(-120, duration: 0.3)
CubicKeyframe(-120, duration: 0.5)
CubicKeyframe(10, duration: 0.3)
SpringKeyframe(0, spring: bouncy)
}

KeyframeTrack(\.scale) { ... }
KeyframeTrack(\.rotation) { ... }
}

Wind your way through advanced animations in SwiftUI. You can find out more details at

Depending on the state value, different animations can be executed.

// Phase animator
HappyDog ()
.phaseAnimator (
SightingPhases. allCases, trigger: sightingCount
) { content, phase in
content
.rotationEffect (phase.rotation)
.scaleEffect(phase.scale)
} animation: { phase in
switch phase {
case .shrink: snappy (duration: 0.1)
case .spin: .bouncy
case .grow: spring(duration: 0.2, bounce: 0.1)
case .reset: .linear(duration: 0.0)
}
}

There was also talk of haptic feedback. It is provided in the form of viewModifier and can be used as follows.

.sensoryFeedback(.increase, trigger: sightingCount)

In addition, there was talk about visualEffect, foregroundStyle, and symbolEffect, but it was not a part to be applied right away, so I decided to reduce it here.

Enhanced interactions

To improve the user experience of the app, scrollTransition, containerRelativeFrame, scrollTargetLayout, and scrollTargetBehavior of ScrollView are introduced.

The part that I thought was meaningful is scrollPosition. If you pass a specific data ID of the scroll content to the binding object, the scroll is adjusted so that the corresponding data is displayed.

Accessibility issues were also addressed. It can be found in ‘Build accessible apps with SwiftUI and UIKit’.

In addition, there were several improvements, but they were covered very briefly, so I decided to shorten them.

References

By Ganesh | LinkedIn | Medium | GitHub

--

--