WWDC Swift Slackers

Hello Swift fam I’m Bardi (aka @mtrostyle) — a first time WWDC participant.
As an Android dev turned Swift convert (as of late) I must say it was nice to experience the value of the community in such a condensed timeframe. To pay back for the value I’ve gained from this awesome community so far, I decided to painstakingly (I know I should’ve scripted it) copy/paste the entire conversation. For myself, and for all of you.
As a developer, I know it’s a pity for this much good shit to go undocumented (:
So without further ado.... here's the 2022 WWDC slack archive.

Every question and answer from WWDC 22’s SwiftUI digital lounge!

<aside> 👋🏼 Hey

I’m Bardi – **@mtrostyle.**  Previously, I’ve built award-winning Android apps. These days, I’m re-defining people’s relationship with time in SwiftUI at timing.is (okay, a calendar, but not just another calendar app, promise).

Not a day goes by when I don’t benefit from the SwiftUI community’s incredibly giving spirit. It was time I gave a little back. So on a Saturday night, I began archiving all questions/answers from its WWDC22 Slack channel. Several hours later, and it was done.

It’s a treasure chest of insight. If there were no copies made before the channel shut, it would have been a huge loss. Thank you to the SwiftUI team for their brilliance, assistance and time <3

Enjoy!

</aside>


Animations

I saw that VStack and HStack conform to Layout. Does that mean using an if-else to switch between the two with the same content will now animate the change?

Yes!

To animate between layouts you'll need to switch between the layouts using AnyLayout  for example:

let layout = isVertical ? AnyLayout(VStack()) : AnyLayout(HStack())
layout {
    Text("Hi")
    Text("World")
}

Check out the Compose custom layouts with SwiftUI talk tomorrow for more details!

When animating the Font on a Text, when can we expect the font to smoothly interpolate instead of crossfade?

Generally changing weights and sizes of the same font will interpolate, but not changing fonts

I'm amazed by the new text animations, can we animate text with any font? Does the font need to respect some criteria?

Yes, you can use any font.

However, you can't go from one font to another or animate from one font family to another. For example, italic to non-italic will not animate


How about variable fonts that can change weight? I mean if I use static fonts (that have one file for bold, one for medium etc…) I suppose I cannot either change weight because it would be another font family, right?

I wouldn't expect that to work animate.

Can text animate fluidly when using matchedGeometryEffect and one is set to a fixedSize(horizontal: true) and the other is not?

I'd expect that to work, especially because text transitions work well when the text is changing layouts (multiple lines/alignments). We realize that it can be a little tricky to know how far exactly you can push those beautiful text transitions.

I’m just wondering whether matchedGeometryEffect can work when navigating between views using the NavigationStack? So, for example, imagine tapping on a card on a ScrollView to open a fullscreen view of the card (i.e. like the App Store) using NavigationStack/matchedGeometryEffect?

NavigationStack uses the system-standard push-pop animations. You might try creating a custom overlay for this use case, so the card would not be part of the path.

What are good tells that I should use implicit vs explicit animations in SwiftUI?

I usually default to withAnimation to set up animations based on when a change occurs. That way, whatever UI changes as a result will implicitly be animated. In some cases, View.animation is useful when you have a certain view or view hierarchy you always want to change with an animation, regardless of what triggered it. A good example is the knob of a Switch: it should just always animate when it changes. (And make sure to pass an appropriate value, like .animation(myAnimation, value: mySwitchValue), so that you only animate when the property you care about changes, and don’t accidentally animate too often.)

Architecture

I’m wanting to get your take on how SwiftUI’s data flow can change how we architect our apps? It seems as if, with EnvironmentObjects, ObservableObjects and possibly more, they change where you get your data from, which could cause variations in, let’s say MVVM. What do you guys think is a good way to make use of these property wrappers and could it change how we architect things?

The data flow primitives we provide in SwiftUI were designed to be agnostic to the way you design your model. Think of them less as parts of a specific design pattern and more as tools to allow you to hook your model (however you think it would be best designed) into SwiftUI.If you want more information on this, I recommend you check out the fantastic talk by my colleagues, Raj, and Luca:

Data Essentials in SwiftUI

Curious if there are any changes to Core Data/SwiftUI integration this year. Using ManagedObjects with SwiftUI seems to results in View that know a lot about Models or Models that have a mix of business logic and view logic which can be confusing.  Any suggested best practices for using Managed Objects with SwiftUI?I tried writing value type wrappers to do MVVM but that breaks down with relationships.

Great question. There were no additions to SwiftUI in regards to Core Data. However, we do have our CoreData Earthquakes sample app and CloudKit sample apps all showing best practices with SwiftUI and background contexts.

The former performs batch inserts and merges changes on a background thread, then publishes the changes to SwiftUI on the main thread.

This notion of edit propagation is described in the Landmarks app in the SwiftUI Tutorials.


I'm not sure we can compare the Landmark app based on Struct with an app using Core Data with objects in contexts. How can we use child contexts with SwiftUI? What would be the best approach to edit entities in a child context?We don't have a sample today detailing this exact scenario, so you'll have to apply the same concepts from the Landmarks app to the merge flow shown in Earthquakes. I'd suggest requesting more samples via Feedback Assistant, though, so we can consider more opportunities to improve our learning resources. To clarify, the Earthquakes sample uses private contexts to perform its batch inserts and merges the changes into the main context. So, that sample is a great place to start.

In a WWDC20 session "Data Essentials in SwiftUI" there's a point in the video where the presenter touches on using a single data model that can have multiple ObservableObject projections to target SwiftUI updates to specific views. How can I achieve this?

The exact solution really depend on your data model but its can simply be as having a model that contains a bunch of properties where each of these type is an ObservableObject; or you could have a function that given an identifier return you the ObservableObject that corresponds to that id.What we wanted to get across was that you want and you can scope your ObservableObject to specific screen of functionality of your app.

I wouldn't consider it a bad practice. Be mindful when using plain @Environment, that if you're passing a struct, any change in value will invalidate any views reading that value from the environment. But if you're using @EnvironmentObject with a class that's effectively immutable that shouldn't be a problem

What is the best way to pass down data managers, specifically a media player to subviews?

You can pass them just as argument to your subview initializer. If you have multiple subviews or the subview that needs to use that data manager is further down the hierarchy you could use the Environment to pass is down

The documentation for EnvironmentKey has code example for it https://developer.apple.com/documentation/swiftui/environmentkey

When it comes to concurrency and SwiftUI, how are you managing creation/injections of your actor objects/business layer so that your views have access to them or do you have any specific recommendations based on the newer Swift concurrency model. I've been reviewing through some of the 2021 videos in conjunction with the new discussions this year and I tend to see .shared in the sample code, which would mean a singleton which I'd frankly rather avoid. We been injecting interactors through the @Environment or @Environment object but this has issues because using @StateObjects we don't necessarily have access to the @Environment object during init when we've been trying to binding subscriptions to our @Published vars. If we use .task {} would we have access to @Enviroment at the time the task closure is run? In this way we could probably set access to our common actors through the @Environment or @EnvironmentObject and then set up flows that just bind to @State via an async Sequence. Is there a way to know when @Environment is actual set for a view so we can respond to in within a @StateObject to set up subscription bindings either through publishers or async sequences?

For pretty much any property wrapper in SwiftUI its value become available just before the body of the view is called. If you have ever implemented a custom DynamicProperty that is exactly when update() is called.

Yes, by the time the .task closure run your environment is available and you can capture its value.

I just want to remind you that you should not conform an actor to ObservableObject because the expectation is that all the ObservableObject instance are isolated to the main thread.

It’s only safe to access any of the property wrapper from within body

Best practices

Is there any specific style guide for SwiftUI ? There are some cases in SwiftUI that I'm not sure what's the best.f.e.

var body: some View { myAmazingView }

(More readable)

or

var body: some View { my AmazingView }

(A one-liner!)

We don’t have any specific style guide! Use whatever you and your team think feels best. Personally, I’m never opposed to writing one liners on one line in Swift though The language is so beautifully concise, so I like to embrace that.

`List(items) { item
     switch item.type {
     case ...:
            SomeView(item)
     case : ...
     }
}`

When you use a switch within a @ViewBuilder closure, you are in fact using the power of generics :wink:, but in most common cases you hopefully don’t have to think about that overtly. In general, using switch in view builders is a great tool! The best approach really case-by-case though, just as when deciding to use a switch versus other control flow in regular imperative code.

What’s the naming convention you’d recommend using for a SwiftUI view - with or without View suffix? I think I’ve seen both in Apple examples.

A good rule of thumb is that if the name we are picking has a clear visual representation, say Text, Image, Toggle, we omit the view suffix. In cases like ProgressView where Progress really would feel more like the data itself than its visual representation we add the View suffix. Specifically in the case of Progress we would clash with Foundation.Progress which will require developer to always fully qualify the type name which is not ideal.

I was wondering if we can use the SwiftUI View protocol with the new 'any' keyword? And if it'll be helpful or a good solution in some example use-case?

any View does not itself conform to View, so is not a replacement for AnyView today. Also any View is only defining an existential container that you can use in a type signature but you can’t instantiate that type.There might be use cases for using any View to store that into collection, for example: [any View].  But most of the time, if you’re in the situation where you think you need [AnyView] or [any View], what you should likely do is invert the view dependency flow and have [AnyDataModel] or [any DataModel]  instead, then create your views based on the type of data provided at runtime.

In general, I would suggest to factor out the logic that fetches the data into its own type. You always want to execute this kind of side effect not on the main thread and the hop back onto the main thread to set the data on the model.

Swift’s actors are a great tool to encapsulate this kind of logic. So for example you could the model that is offered to the view be an ObservableObject that is bound to the main actor, and have a separate actor (hence running on a separate thread) that takes care of the fetching and report back new data to your observable object.

Assume that I keep the whole app state in the state object in my app struct? This way I can make sure that all the views are in a consistent state and have a single source of truth. How can I tune performance because in this case, SwiftUI starts diffing the whole app view hierarchy on every single change of the app state?

You’re completely right that with a single observable object, you’ll end up invalidating large parts of your view hierarchy whenever a change occurs. Invalidating even large amounts of the SwiftUI view hierarchy should be an inexpensive operation, as view descriptions are rather lightweight, but if you are running into performance issues here, there are a few things you can do to help. The first recommendation I have is to split out some of the values which are only relevant to a certain subset of views into their own observable object. This is likely going to get you the most performance win of any of these suggestions, but if you don’t want to make that architectural change, there are still some things you can do:

  • Avoid marking non-published values of your ObservableObject published
  • (Assuming you’re using EnvironmentObject to make sure your single StateObject can be accessed throughout your view hierarchy) ensuring you only declare dependencies on the EnvironmentObject in places it’s needed
  • And if you still need to optimize further, writing a custom objectWillChange implementation for your StateObjects which only does invalidation when changes that should actually affect the UI occur (in cases, for example, where published values have multiple different representations that should display in the same manner).

Do ids in a ForEach just need to be unique within that ForEach or globally? For instance using the new Charts, all my data is keyed by date and there are several places where I have adjacent ForEaches that include mostly the same dates.

The IDs must be unique within the container, so for example if you have a List with two ForEach's inside it, they must generate unique IDs within that List.

For complex views, I often define subviews inside computed vars to keep my body block more readable.  Especially for components that don't need to be reused elsewhere in the app, so they don't seem to warrant a reusable struct. I've heard that this can be bad for performance - is that true? And does using @ViewBuilder on some computed vars have any impact?

struct MyView: View {
    var body: some View {
        someText
        someButton
    }
    private var someText: some View {
        Text("Hello")
    }
    private var someButton: some View {
        Button("Press") {}
    }
}

SwiftUI’s traversal of your view tree isn’t impacted at all by whether you chose to use new structs, or computed properties, for small pieces of views, etc. So this is totally reasonable. Using @ViewBuilder here also shouldn’t have a performance impact. I would highly recommend doing so! The only thing that you should pay attention to is your mechanisms for invalidating your views will be a bit less fine-grained, as you’re making a larger part of your view hierarchy dependent on the sources of truth specified by MyView . Make sure you’re paying attention to what pieces of your view depend on which pieces of data, and when you see computed properties that have completely disparate dependencies from the rest of the view, you consider breaking those out.

Charts

Talking about Charts, will it be possible to add a gradient color filling the area underneath the line in a line chart?

It is! I made one like this while putting the talk together, I can't remember exactly how I did it. I may have used an AreaMark that fills the area under the line, and they also stack to make some really cool area charts

When you're making those kinds of charts, using Color.clear as a part of your gradient makes the Chart look a lot neater in light and dark appearances IMO

I have to say, it's extremely fun to see how quickly you can make custom-rolled charts from various apps in Swift Charts. Like a speed run, only with accessibility, dynamic type, and localization built in

Does Swift Charts have a way to highlight values on a line chart  for a specific X position?

You can always try drawing an additional mark for the highlight.

Its possible to modify the .foregroundStyle to have a different color per X position, it depends on what kind of highlight you want to call out. It might be possible to do an annotation as well but the charts team will be the experts!

You can use PointMark (possibly with annotations) to highlight values on a line, such as:

Chart {
    // Create the line.
    ForEach(data) {
        LineMark(
            x: .value("X", $0.x),
            y: .value("Y", $0.y)
        )
    }
    // Highlight a point.
    PointMark(
        x: .value("Highlight X", 10),
        y: .value("Highlight Y", 50)
    )
    .foregroundStyle(highlightColor)
    // You can also add textual annotations to the point:
    .annotation(position: .top) {
        Text("Highlight")
    }
}

I am sorry for not being clear. What I want is having a vertical line when I tap on a specific X position so that all datapoints on that X position are highlighted.

You would decompose the problem into 1) using a chart proxy to get the x position for a tap and 2) highlighting the data points at that x. The lollipop tooltip we have in the Swift Charts sample app may be a starting point to look at.

I’m curious if i could build candlestick charts with it?

Candlestick charts are definitely supported with a little customization. You can compose Mark types, so a candlestick mark is a combination of two different marks.

Does the API provide anything for adding additional types of charts? For instance, if I wanted to implement a pie chart could I leverage this.

That's an interesting question about Pie charts specifically. The data visualization academic community right now has mixed feelings generally about pie charts. They aren't supported in Swift Charts. I'm not data-vis expert though, definitely bring this up in the Charts sessions Curt mentioned.

Can it be used to show realtime (e.g. sensor) data?

Yes, you can use it with realtime data.

Considering long running sensor data being visualized, what would be a good approach to scroll through it it horizontally? Embed multiple Chart

into a scrollview, LazyHGrid? memory pressure and speed is currently killing us in UIKit… any advise here?

The weather app has multiple charts embedded in some scrollview so I suppose that could be a good approach. This could be a good topic for a lab session with the team later this week.

Any support for rendering this to a scalable PDF beyond embedding as an image?

Swift Charts does not support radial layouts so no pie charts or donut charts. However, you can usually show the same data as a bar chart, which may actually be easier to read and is more accessible to e.g. Voice Over users (linear layout is closer to the navigation order in other interface elements).

Any hierarchy tree charts available?

There is no native support for hierarchical layouts in Swift Charts. you could use it to render the output of a tree layout algorithm (e.g. Treemap) with the rectangle mark but I don’t think you get that much benefit from Swift Charts over SwiftUI in that case.

Any support for rendering this to a scalable PDF beyond embedding as an image?

To create a PDF, you can use the ChartRenderer API to render a chart into a CGPDFContext.

Do we get the Audio Charts for free when using native charts or do we still have to provide a chart descriptor?

Yes, you get Audio Graph support automatically. However, the framework can only infer so much automatically so you may still want to override the default to get the best experience for your VoiceOver users.

Are doughnut and pie charts also supported?

No. But you can use a bar chart instead. See my the discussion above.

To create a chart-like layout like this, do you recommend using the new Chart library or building it custom with Grids? Are there any performance benefits for one or the other approach?

Untitled

You can use Swift Charts. You will get the axes and color scale for free and also better performance (I think but would need to try).

Concerning interactions: is there any onTap handler (available/planned) where we can react to a users tap and show (more) info of the mark below? (in particular not overlaying a GeometryReady and find out the position/mark on our own)

We can’t talk about plans for the future.There is a chart reader that you can use for interactions. Check out the “Raise the Bar” talk.

Is it possible to change the axis appearance? Like, changing the color of the lines or using a custom font in the legend?

Yes. Take a look at the raising the bar talk and the docs.

Can the new Charts API allow for scrolling? similar to the health app's charts

Yes, charts should behave just like any other view in this regard. though you may have to set explicit frames on the chart to specify how big (wide? tall?) you want it to be. I just realized the health app chart does scrolling that keeps the y-axis stationary, that specifically isn't supported, but we've received a few requests about this, but few feedbacks. So if you file a feedback for the Charts team, we'd appreciate it.

Forgive me if this question has the same answer as the scrolling chart question, but could we utilize a scrollview and a chart to display a live chart? So new data added is always visible to the user, instead of having to manually scroll it into view.

Yes, this should work, but will extra work. You may have to observe the data and manually keep the scroll view positioned at the very end It sounds like you want to use to be able to scroll backwards through an otherwise-live feed, but if that isn't the case, the data plotted in your chart could always be just the last 7 elements of an array or something conceptually similar

How would one go about creating a Bubble Chart with Swift Charts?

You can use the symbolSize(by:) modifier (https://developer.apple.com/documentation/charts/chartcontent/symbolsize(by:)) to size the points by data.To make the points look like bubbles, you can use .symbol(Circle().strokeBorder(lineWidth: 1)) so the symbols are drawn as stroked circles.Here is an example:

Chart(data) {
    PointMark(
        x: .value("Wing Length", $0.wingLength),
        y: .value("Wing Width", $0.wingWidth)
    )
    .symbolSize(by: .value("Weight", $0.weight))
    .symbol(Circle().strokeBorder(lineWidth: 1))
}

Is there a preferred method to allow user interaction with data points in a chart imbedded in a scrollview?

This talk https://developer.apple.com/wwdc22/10137 has some examples of adding interaction

I think that would be orthogonal to the question of embedding the chart in a scroll view, but it may complicate hit detection depending on how big the chart is

How can I change the (text) color of the scales at the sides in a Swift Charts?

You can change the color of the axis labels with the .chart{X/Y}Axis modifier, where you can configure the foregroundStyle of AxisValueLabel . Here is an example changing the label color for the Y axis:

.chartYAxis {
    AxisMarks { _ in
        AxisGridLine()
        AxisTick()
        AxisValueLabel().foregroundStyle(Color.red)
    }
}

You can change the color of the grid line and tick in a similar way too.


Could it be that this currently doesn't work in the developer beta?

Because I just tried the following code and it applied the colors on the grid line and tick, but not on the label next to the tick.

.chartYAxis {
                AxisMarks { _ in
                    AxisGridLine()
                    .foregroundStyle(.yellow)
                    AxisTick()
                    .foregroundStyle(.blue)
                    AxisValueLabel()
                    .foregroundStyle(.red)
                }
            }

Yes, looks like this is a bug in the beta.

When using Charts to draw a line graph, is there a way to get the last point to be at the trailing edge of the chart view? I’m finding that it always has the trailing edge as a multiple of values used on the x axis.

You can use the .chartXAxis(content:) modifier passing an AxisContentBuilder that either completely customizes the x-axis, or you could first try out this initializer of AxisMarks  passing true for those roundLowerBound and roundUpperBound

/// Automatically determines the values for the markers,
/// approximating the target number of values.
public static func automatic(
    desiredCount: Int? = nil,
    roundLowerBound: Bool? = nil,
    roundUpperBound: Bool? = nil
) -> Values

Using SwiftUI, I’m trying to use SwiftChart to add color underneath my line graph. I was wondering if there's a good resource on how I can do that?

Untitled

Check out AreaMark!

I forget the exact modifier to specify the color underneath the area mark, it may be foregroundStyle

passing a gradient in this case probably from orange to clear

And is there a way to add the line color? On the top of the area

Ah this is one of my favorite parts of Charts

So you can have multiple marks in one chart

There may be a modifier specifically for the line color of an AreaMark so, I'll check with some Swift Charts engineers, but in the meantime, it's still instructive to add a LineMark plotting the same data after the AreaMark

The line mark will be superimposed on top of the area mark

So literally you have two charts on top of each other, but conceptually, it looks like a single styled chart

How do i get points on my lineMark in swift charts?

Untitled

You can either add a PointMark on top of the LineMark or by adding a symbol to the linemark

LineMark(x: .value("xvalue", point.x),
         y: .value("yvalue", point.y))
    .symbol(Circle())

My “Use SwiftUI in UIKit” sample project actually has an example of this https://developer.apple.com/documentation/uikit/views_and_controls/using_swiftui_with_uikitas does I believe some of the Swift Charts talks sample code too!


what if i want to add the numerical values (eg: 15) above that PointMark? TextMark?

It should be an annotation modifer on the mark!

 .annotation(position: .top, alignment: .leading)

https://developer.apple.com/documentation/charts/visualizing_your_app_s_data

the swift charts example project has an example of this!

How can I adjust the width or thickness of a linemark in swift charts?

you can use a LineStyle! https://developer.apple.com/documentation/charts/chartcontent/linestyle(_:).lineStyle(StrokeStyle(lineWidth: 3))

We recommend simplifying the data before rendering it. For your example, you could simplify the line or summarize the data points in small intervals (let’s say you have data for a year, you summarize the data for a day). The added advantage is that you can summarize using mean, min and max and show the full range within the small interval.


An Apple resource I found helpful with this kind of thing is using antialiasing filters to resample the data. https://developer.apple.com/documentation/accelerate/resampling_a_signal_with_decimation

Another useful resource are the number and date bins we released this year: https://developer.apple.com/documentation/charts/datebins and https://developer.apple.com/documentation/charts/numberbins.

Is there a way to get AreaMark to work with .chartYScale(domain: .automatic(includesZero: false))? As soon as I add an AreaMark it seems to always include 0 in the scale.

You could try setting yStart and yEnd for the area, here is an example:

Chart(data) {
    AreaMark(
        x: .value("Date", $0.date),
        yStart: .value("Start Price", 100),
        yEnd: .value("Price", $0.price)
    )
}
.chartYScale(domain: .automatic(includesZero: false))

The automatic option will use nicely rounded numbers. If that's not working for you, you can also set the domain directly like domain: 100 ... 1000


first suggestion doesn’t quit work because there is some padding added to the y range. I’ll give a specific range a try next.

Untitled

Just setting a range doesn’t quit work either… I guess I would need to do both?

Untitled

Umm, could you try turning off roundLowerBound in axis marks? Full code would be like this:

Chart(data) {
    AreaMark(
        x: .value("Date", $0.date),
        yStart: .value("Start Price", 100),
        yEnd: .value("Price", $0.price)
    )
}
.chartYScale(domain: .automatic(includesZero: false))
.chartXAxis {
    AxisMarks(values: .automatic(roundLowerBound: false))
}

roundLowerBound tries to add a round number below the data range, that might be why we are seeing a 40,000 value below the area like in your first screenshot.

That works

Can Swift Charts be adapted for non-discrete data, like curves, etc today?

You can render curves by sampling data points along the function and then rendering that. You can add interpolation to make the line look smooth. Swift Charts cannot directly render functions.


I was wondering if there were some kind of closure-based API to encapsulate the function, with parameters like range and increment

Untitled
Untitled

There is not but you could sample a few points and then render the line.

Is there any sample code or documentation on how to display vector fields with Swift Charts?

Like this?

Untitled

This screenshot is from the Hello Swift Charts talk. Let me find the code for it.

You can use a custom symbol (Arrow ).

        Chart(data, id: \\.x) {
            PointMark(x: .value("x", $0.x), y: .value("y", $0.y))
                .symbol(Arrow(angle: CGFloat(angle))
                .foregroundStyle(by: .value("angle", angle))
                .opacity(0.7)
        }

...

    struct Arrow: ChartSymbolShape {
        let angle: CGFloat
        let size: CGFloat

        func path(in rect: CGRect) -> Path {
            let w = rect.width * size * 0.05 + 0.6
            var path = Path()
            path.move(to: CGPoint(x: 0, y: 1))
            path.addLine(to: CGPoint(x: -0.2, y: -0.5))
            path.addLine(to: CGPoint(x: 0.2, y: -0.5))
            path.closeSubpath()
            return path.applying(.init(rotationAngle: angle))
                .applying(.init(scaleX: w, y: w))
                .applying(.init(translationX: rect.midX, y: rect.midY))
        }

        var perceptualUnitRect: CGRect {
            return CGRect(x: 0, y: 0, width: 1, height: 1)
        }
    }

This is not the complete code but should give you enough to make the example.

There is no automatic sampling in Swift Charts. I would expect the "preferred" sampling method to vary on a case-by-case basis. I think the best approach is to see what works for you and then sample in a manner that is honest to your data as you run into performance issues. We're always looking to improve the performance of the framework! File feedback if you run into issues.

As a general design principle, I would recommend simplifying / aggregating data  as it becomes large. It's rarely useful to look at large amounts of raw data on the screen, as you run into the limits of 2d rendering wrt to occlusion, fidelity, and noise resolution.

One point per screen point is probably excessive too (from a legibility perspective, if not a performance one)... it would help to get an idea of what you are trying to achieve & what your data looks like

It depends on the machine performance and complexity of the chart. It's usually a good idea to test with your actual data and chart to figure out how many points can be drawn with acceptable user experience.

Based on my experience it's about 1000 to 2000 for smooth animations.

You may be interested in the date and number bin apis we added this year: https://developer.apple.com/documentation/charts/numberbins https://developer.apple.com/documentation/charts/datebins. You ca use them to group your data and then summarizing the data in each group/bin.

How easy is it to support interactions like pan-to-move and pinch-to-zoom?

For pan-to-move, you can use a SwiftUI gesture in conjunction with ChartProxy. From the gesture, you get the the pan distance, and then you can use ChartProxy to figure out the pan distance in the data domain. Then, you can set the domain for the X scale with .chartXScale(domain: start + offset...end + offset) , where you can adjust the offset to pan the chart.

you can use a pinch to zoom gesture (or any other gesture) and hook up the events in a similar way.


Without location information (like the new SpatialTapGesture) it would be a bit unnatural as we wouldn't know where to center the zoom, right? MagnificationGesture doesn't provide location information, unless I've missed something

For now I think you can try implement a UIView with UIPinchGestureRecognizer and then wrap the view with UIViewRepresentable so it can be used in SwiftUI.

Can we highlight specific data points and dim the rest; similar to what Health.app does when selecting “min/max”, “latest”, etc in Heart Rate and other charts?

absolutely! An easy way to do this is to store the desired highlighted data's ids in a @State and check against that in your ForEach of Marks. Something along the lines of

ForEach(data) { value in
  BarMark(x: ..., y: ...)
    .foregroundStyle(value.id == state.highlighted ? Color.red : Color.gray)
}

Is it possible to use a Chart to display a large amount of data? For example, display a waveform.

Yes!

You can render curves by sampling data points along the function and then rendering that. You can add interpolation to make the line look smooth. Swift Charts cannot directly render functions

We generally recommend aggregating very large datasets since there are only so many marks that can be rendered and reasonably read by a user. Swift Charts can process and render a reasonable number of data points.

Is there multiple axis support? Logarithmic axis support?

A Swift Charts chart can only have one axis per x and y. Swift Charts supports logarithmic scales

For example, you can specify a log scale on x with.chartXScale(type: .log)

You can however, have multiple sets of labels / ticks / grid lines by adding multiple AxisMarks

they will share the same scale, but might be useful for things like displaying both C and F on the same chart

In https://wwdc22.slack.com/archives/C03HX19UNCQ/p1654799167892029 I talked about ways to show multiple metrics as separate charts.

I have one question about the axis labels on charts. When I use the chartXAxis modifier to show custom AxisMarks with an array of values (dates in my case), the chart doesn't show the last value on that axis (the last date). Is it possible to turn that on?

//  Simple Chart
.chartXAxis {
  // data contains two data points with a date. The entire chart only has these two data points
  AxisMarks(preset: .extended, values: data.map(\\.date))
}

I think I can guess what is going on here. If a label is placed beyond the edge of the axis, (as can be the case with the last value of a list of dates, as it would define the end of your date range) it won't be rendered, as it would run off the edge of the chart.

Off the top of my head, solutions may include: adding a bit of "padding" in your date range or switching the axis style.

Is there a way to have multiple scales per chart? Let's say I'm doing weather and I want one line with cloud cover (a 0-100% scale) and rainfall per hour (in, say, mm). The x axis on both of those would be time, but the y axes are different.

An axis always has one scale. So x and y have one scale. You can have multiple axes to display e.g. temperature in C and F. If you want to show multiple measures, I would recommend multiple charts with aligned x-axes. You can even hide the axis of the upper chart to create a more compact view.

I noticed some layout issues with the Legend, when there are a lot of items to display, or when the names are long. Do you plan to make the legend Layout automatically wrap/use multiple rows when there is not enough space? I noticed the iCloud design on iOS switches from a HStack to a VStack when the device accessibility is set to true. My feedback with more infos: FB10125848

Thank you for your feedback!

Adding data to charts and the modifiers always requires this .value(_:) function that requires a label key. What exactly is the purpose of that label key? Is it some kind of identifier? Does the label key in a foregroundStyle have to match one in a LineMark, for example (if referencing the same data)?

The label key is used for generating a good default description for the chart for VoiceOver users and the audio graph. For example, if you have x: .value("time", ...), y: .value("sales", ...) , VoiceOver users will hear something like "x axis shows time, y axis shows sales".The label key in foregroundStyle doesn't necessarily need to match LineMark, but it's a good practice to use the same label if the data is the same.

Are there any limitations to the result builder syntax used to add marks? How many entries can we put in there? View builders are typically limited to 10. Would grouping help if there is an arbitrary limit based on the builder?

Right now it's 10. Grouping into ForEach's etc would help! If you have a use case that requires more, please file feedback~

What were the inspirations for its API design? It feels very similar in many aspects to ggplot2 which itself is apparently based on "The Grammar of Graphics" book. Was that an inspiration?

Swift Charts is a grammar based visualization language, which means charts are composed of building blocks (marks and mark properties) instead of picked from a list of chart types (vertical bar chart, bubble chart, waterfall chart etc). The Grammar of Graphics was hugely influential for many visualization APIs like ggplot, D3, Vega and also Swift Charts.

How can we remove or configure the space between the bars (BarMark) ?

Untitled

BarMark has a width parameter that takes a MarkDimension! It can be a fixed value or a ratio (of the space the bar is allocated).

this is a pixel boundary rendering artifact. One solution is to make the width just a tadddd over 1 so they overlap just a bit

It's a rendering artifact that happens when the bars doesn't align with pixel boundaries. There are a couple of ways to address it:

  • As Halden mentioned, you can make the bars slightly wider (with something like .inset(-1) or .ratio(1.01))
  • You can also tweak the width of the plot area (with .chartPlotStyle { $0.frame(width: plotAreaWidth) }) based on the number of bars, so that the bars are aligned exactly with pixel boundaries. This is more complex to do, but will give the best result.

Do you have any suggestions for displaying "goal progress" data? Saw in earlier Q&A that radial/rings charts are not supported, but other types could be used.  Looking for visualization similar to Health activity rings.  Thinking about 3 bars normalized to % of progress toward goal.

You could make a chart with three bars one for each category. If you set the scale to have a domain from e.g. 0 to 100, then the length of a bar indicates the progress towards a goal. A horizontal bar chart could work well.


that's exactly what I was thinking, too.  But unsure on upper bound of chart when goal is exceeded.  For rings, if my steps goal is 5000 and I actually take 12000, then it would show 240% for that bar.

That’s an interesting consideration. You could have a chart that extends beyond 5000 but adds a vertical RuleMark  to annotate the goal.

Since you may show different metrics (e.g. steps and distance), you may want to normalize them to % of goal so they have the same scale/axis.

Is there a suggested "update rate" that you'd recommend for real-time charts? When trying this out on a simulated iPhone, I quickly approach 90%+ CPU usage if I try to update a line graph more than 40 times/second (For example, when trying to visualize a simulated accelerometer).

We recommend benchmarking your app to find the right balance between the update rate and the amount of data on your line chart.  We'd also appreciate feedback through Feedback Assistant for your use case!

We have data that doesn't necessarily progress linearly from one point to the next, for example the x and y values could either increase or decrease from one point to the next. Would those points be linked as if they were points on a path or would it upset the system?

I’m not sure I fully got the question but you can either draw points as separate with PointMark or linked with a LineMark. Adding linked points is well supported by Swift Charts.


Sounds like "can I do XY scatter with joined lines”.

The answer is yes. Use a LineMark.

I have a horizontal bar chart with two Text overlay annotations on each bar, one aligned leading and one aligned trailing. When the bars are short the annotations overlap and eventually truncate. Is there an easy way to hide overlayed annotations when the bars are too short to accommodate their intrinsic widths or should I explore other layout configurations (e.g. one annotation with an HStack containing two Text views spanning the context target region width)?

There isn't a way to hide overlayed annotations right now, but feel free to file a feedback

In this situation, you can explore other layout options as you mentioned. For example, a single annotation with

HStack { Text(...); Spacer(); Text(...) }

Is there a way for external developers to extend Swift Charts and add new chart types that aren't supported out of the box, for example pie charts, or charts with 3D styling?

You can create custom marks but they need to be cartesian. So you can make e.g. a candlestick or boxplot. Swift Charts does not support pie charts or 3D charts. See https://wwdc22.slack.com/archives/C03HX19UNCQ/p1654618060787259 for a discussion of alternatives.


So I would assume a 2D bar graph with a fake 3D effect for the bar marks should be easily doable. But no circular graphs?

Yes, I would agree with that.

Is there a method to modify or specify the label style of a chart? For instance, my chart includes price averages for home heating oil. I want to clearly display on the label that the Double is in dollar format on the Y axis.At this time, when I attempted a brief demo app it simply made the Y axis label as an Int.

Yes, there are a few options here. You can use AxisMarks(format: FormatStyle) or AxisValueLabel(format: FormatStyle) or AxisValueLabel { Text(\\(..., format: ...)) }

If your units are more verbose, a design alternative is to clarify them in the title or headline of your chart, to save horizontal space on the y axis.

Does Charts support polar coordinates?

It does not, but feedback is appreciated!!

How can I add a text or SF Symbol at the top of a vertical BarMark ?

You can use the annotation modifier to add an annotation on top of the bar, where the content of the annotation is a SF Symbol image. Here's an example:

BarMark(...)
.annotation(position: .top) {
    Image(systemName: "sfsymbol_name")
}

Note that you can also use Text or other views as the content of the annotation.

I saw the example for the Interval Bar Chart in the docs and it got me thinking I could represent a simple weekly view of a student's course schedule if I flipped the axis. I made a proof of concept and it worked really well! I calculate the duration of a meeting in minutes to create the size of the BarMark using yStart and yEnd. Is this a good way to do this or can it be achieved with just the start date time and end date time? I also had to reverse the chartYScale to get the AM meetings to apear first, not sure if that is expected or not.

struct Series: Identifiable {
    let courseName: String
    let meetings: [Meeting]
    var id: String { courseName }
}
struct Meeting {
    let startDate: Date
    let endDate: Date
    let startMinute: Double //Minutes since 7am
    let endMinute: Double
}
 Chart(data) { series in
	ForEach(series.meetings, id: \\.startDate) { element in
		BarMark(
			x: .value("Course", element.startDate, unit: .day),
			yStart: .value("Start Time", element.startMinute),
			yEnd: .value("End Time", element.endMinute)
		).annotation(position: .overlay, alignment: .top) {
			VStack {
				Text(series.courseName).font(.caption)
				Text(element.startDate.stringValue(dateFormat: .time)).font(.caption)
			}
		}
	}
	.cornerRadius(8.0)
	.foregroundStyle(by: .value("Course", series.courseName))
} .chartYAxis {
	AxisMarks(position: .leading, values: .stride(by: 60)) { axis in
		AxisTick()
		AxisGridLine()
		AxisValueLabel(centered: false) {
			if axis.index+7 < 13 {
				Text("\\(axis.index+7) AM")
			} else {
				Text("\\((axis.index+7)-12) PM")
			}
		}
	}
}.chartXAxis {
	AxisMarks(position: .top, values: daysOfTheWeek) { _ in
		AxisGridLine()
		AxisTick()
		AxisValueLabel(centered: true)
	}
}.chartYScale(domain: .automatic(reversed: true))
Untitled

Beautiful!! You can use Date here instead of converting to integer minutes and it should go top to bottom by default.

Int and Double will go bottom up (low to high) while dates will go top down (early to late)

I think you're approach is good! (turning it into a number and then applying a reverse and customizing the axis labels). This is a clever solution, I dig it. The problem with the startDate and endDate approach is that its interpreting the dates including the date, so your Y axis became a mirror the X axis.

Is it possible to get a reference to the colors automatically assigned to the series by the foregroundStyle? I may want to create my own legend in a vertical format. Unless legends can be formatted vertically?

You can try positioning the legend on the trailing edge of the chart using the chartLegend modifier

The default color scale is currently as follows: all system colors.systemBlue, .green, .orange, .purple, .red, .teal, .yellow

Can we transform a mark when the user presses and releases it, like we could do with a ButtonStyle. If not, we can probably use an overlay, but can we change the size of marks without changing their values (for example with a scale effect)?

Currently we don't have a scaleEffect modifier. You can use something like width: .fixed(hovering ? 100 : 80) in BarMark constructor. This will make the bar wider when hovering is true.

I'm curious on how Charts handles time based data e.g. temperature over a day when data can be received at any point of the day, not a set interval apart? Some chart libraries that have previously existed did not handle this and just spaced out data incorrectly.

Charts handles Date as a continuous variable, so this should be fine. If you do want to treat the data as spaced out evenly (e.g., exactly one measurement per day) you can tell the framework to do so by using the unit parameter in a value

I've got a set of data I wish to chart that is discrete states over time, for example on/off states of a light, or an enumeration a door lock's state. (example: https://twitter.com/aaron_pearce/status/1527452719027728384?s=21&t=ux-SjhyOSmO89k0u4Lf_jA)..)

Yes. A Rectangle or Bar Mark. I suppose you have some kind of start/end time already, no? You can pass those to xStart and xEnd.

What's the best way to use ChartRenderer to draw to a CGContext with slightly different styles (e.g. draw shapes as hollow, or dashed lines, etc)?

Currently there's no API to draw marks with styles other than what's supported in ShapeStyle. Feel free to file a feature request via Feedback Assistant.

No, currently there isn't a way to configure styling of the renderer itself. You could try an approach like exporting the rendered content as PDF or SVG and apply the styling by transforming the resulting vector graphics.

Is it possible to assign a gradient between specific LineMarks? E.g. to show a change in value in temperature from cold to hot?

You can draw an AreaMark with .foregroundStyle(gradient) below the two lines. It will add an area under them, the lines will be intact.

You can use .foregroundStyle(gradient) on the LineMark as well. with a LinearGradient that goes from left to right.

What's the best way to that we can use Swift Charts in a predominately UIKit app?

Yes the new UIHostingConfiguration lets you use SwiftUI in cells and UIHostingController has some new ways to track size changes that make it easier to use it in stack views or in embedded view controller! Definitely check out the talk, anywhere I talk about using a SwiftUI view you can use a Chart as well!

Is it possible to share one of the axis between 2 charts or have 2 subcharts on the same axis, eg share x-axis have have 2 different y-axies on either side with their own independent domain range.Or have a plot when another plot to its right that shares the y-axis but has its own x-axis (commonly used when drawing a heatmap to show a histogram attached on the side)

Hope I'm understanding your question correctly. You can set specify two charts to have the same chartScale and chartAxis using the appropriate modifiers, but we don't support dual scales on the same chart

Compatibility

Are any of these changes back-deployable to previous OSes (e.g., like the new Section initialisers were last year)

Not this year! Last year we had some nice syntactic refinements that we were able to back deploy, but many of the features this year require fundamental new support in the OS.

Are there any plans for backward compatibility for the new navigation APIs e.g. for iOS 15?

I’m afraid it isn’t technically possible to back port these APIs.

Are all the new layout features available on non-iOS platforms? watchOS, macOS, tvOS…

Yes, there are. And just for reference, you can always check the availability of a bit of API right at the top of the page.

How can I make sure I support older iOS versions, for example iOS 15 in my SwiftUI app, while still using the new features for iOS 16 users? Are there any macros for that?

You can conditionalize your code based on whether iOS 16 APIs are available like this:

if #available(iOS 16, *) {
    // iOS 16 code
} else {
    // iOS 15 and earlier code
}

@available is used to annotate your declarations to mark them as requiring a newer iOS version. For example, if you have a method that takes in an object/struct only available on iOS 16, then you need to annotate the method as @available(iOS 16, *)

#available is a runtime check to be used in a condition. @available is an annotation for a method that makes that method unavailable. If your iOS 16 only code is run in a method that is only available in iOS 16 then the compiler won’t complain. So you can use a mixture of both.

Right, the compiler will then complain if you try to call that method on an older iOS version. Frameworks like UIKit and SwiftUI use this to prevent new API introduced in iOS 16 from being called on iOS 15, for example.

We recommend factoring out the common parts and then using if #available checks to use the relevant modifier. Something like this:

let common = commonViewParts
if #available(iOS 16.0, macOS 13.0, *) {
    return common.newModifier()
} else {
    return common.oldModifier()
}

You are correct that you can’t apply availability to stored properties in Swift.There are a few techniques you can use to work around this. Most commonly, you can factor out the portion of your UI that uses this property into it’s own View, and apply availability to that entire view. However, the best way to structure the code really depends on your specific use case, and we agree that this can be tricky to handle in some situations.

Controls

Is there any new control in SwiftUI like the NSSegmentedControl used under tables to add / delete a row? This is a common pattern in macOS applications and the current SwiftUI segmented control does not fit to this use case.

Good news: There’s not a new control, but an old one

Last year we introduced ControlGroup that enables building these kinds of controls (which you might have used  NSSegmentedControl for with AppKit).

You can create one with Buttons, Toggles, and more!

Is it possible to present a popover as popover on iPhone, like it's the case with iOS?

On iPhone, the .popover(…) modifier always presents as a sheet. There isn’t currently a way to customize that behavior.

Talking about the Date Picker with multiple dates, can they allow to choose date ranges (like when you book a flight), so with just two dates possible and the highlight spanning over all of the days in between?

Currently, MultiDatePicker only supports non-contiguous date selection. So range selection is not supported at the moment.

Is it possible in general to use TimelineView as a "global clock" that can be synced by all the devices (that use the app) in order to display/show something at the same exact time? (if so, what precision should be expect?)

While TimelineView can be used to update views at a specific point in time, it isn’t designed specifically for cross-device synchronization. You may be able to use it for that kind of use case, but it wouldn’t provide any better precision than using a Timer or other scheduling mechanism

Can we use SwiftUI to create a numeric text field? I was looking for something that allows typing Int numbers.In my case, I had to work to with 4 digit numbers, and a stepper wasn't the best choice. Instead, I went for a TextField that checks if it can convert the input string to an Int when a button is clicked. Is there a better way to achieve this?

Check out the TextField initializers that take a formatter. If this is for iOS see also the keyboardType(_:) modifier.

Is there a way to use a capacity Gauge outside of the lock screen?

Yes! Gauge is usable outside of the Lock Screen, and also has a whole host of new styles! I would take a look at the linearCapacity, accessoryLinearCapacity, and accessoryCircularCapacity styles. Please note though that gauge styles prefixed with “accessory” are really intended to appear in contexts like the Lock Screen / widgets, or some similar design context within your app proper, so please give careful consideration to where you use them.

I am using three pickers in a row to allow me to enter hours/minutes/seconds. However, the tap targets for the pickers are all off by some factor, such that if I try to scroll to the right of the middle of a picker, it actually scrolls the picker to the right instead. Is this a known issue? Is there a workaround?

Could you please file a radar fro this issue?

Would it be possible to create an “infinite” paged collection view in SwiftUI? Similar to the week view in the calendar app where you can swipe through weeks endlessly. Thanks!

On way to achieve that would be to have onAppear on a the individual views that the List is scrolling over and use that load in more data.


What if you want the @State data to not grow as the user continues to page? Removing items from the array would offset the data and causes a jarring affect.One way you can solve the problem is by keeping only identifiers in the @State so that the storage doesn’t grow too much, and load on the demand the actual data as view are coming on screen.

Hope non-standard behavior out of SwiftUI is your cup of tea, because I have a really “interesting” question. This happens using SwiftUI in Xcode 13.4 on an iMac running macOS 12.4. When using .datePickerStyle(.compact), and I touch the date to bring up the calendar, the final displayed date changes format depending on the chosen date. “June 19, 2022” looks ok, but then I get “6/20/22” when I move to the next day. It gets better: after going left to right in the month, and seeing “6/22/22”, when I start moving right to left from June 24, 2022, the output for the 22nd comes out as “June 22, 2022”. Any ideas would be welcome! Apologies for the weird problem!

Thanks for the feedback. This is a known issue :) and we are fixing it!

I noticed a month ago on one of my Views that any TextField I add to my Form (within a VStack) extends the space below the Form. I only noticed as the view contains the Form in question and then an HStack with buttons. The space between the Form and HStack increases with each TextField I add to the Form. I created a stackoverflow question (linked at end) but couldn't figure it out. I got around this by surrounding it in a ScrollView (realized my other forms were fine and that's why) so I continued on. Figured I'd ask here though. :) https://stackoverflow.com/questions/72293879/the-textfields-on-my-swiftui-macos-project-are-making-my-window-height-too-tall

this does look unexpected. could you file a feedback with a sample project that reproduces it attached?

Is it possible to have a self-sizing list in SwiftUI similar to how LazyVStack works? List has support for drag and drop through onMove while LazyVStack does not.

List doesn't size itself based on the height of the content like LazyVStack. You'll need to give it a fixed height using the .frame(height: ...) modifier. List has support for reordering, swipe actions, and other features that LazyVStack does not.

Data

When using SwiftUI with Core Data, should we setup the predicate and sort descriptors for a FetchRequest in the View init or in the onAppear of the View, when they’re based on object passed from the containing View? I noticed some issues when using the onAppear because items are displayed then removed (with animation).

If you want to be sure that the FetchRequest is setup before the view does any work you might want to set that up in the initializer.I think it would be worth to file a feedback regarding the issue that you are seeing with onAppear.

DynamicProperty

What is the correct way to implement invalidation when conforming some type to DynamicProperty? Should hosting another builtin DynamicProperty enough? Are these wrapped properties like @State or @ObservedObject guaranteed to work as expected in DynamicProperty?

Dynamic properties are fully composable, so any other dynamic properties you use inside of their declarations will be picked up on and invalidated properly. That means supporting invalidation as you would expect is often just a matter of utilizing the support already built into other dynamic properties, like @State

Is there a better way to prevent DynamicProperty from invalidating a view’s body based on different criteria? I am currently doing this with a private ObservableObject backing that manages its objectWillSend calls, which seems to works well but also feels like I am doing some backflips (the context is being able to scope in on specific changes on an ObservableObject model for performance reasons).

There is no direct way to prevent DynamicProperty from updating. What you are doing is a way to do it. If the purpose is to manage ObservableObject invalidation I would suggest consider refactoring your model into multiple model. Keep in mind that you can also implement your own objectWillChange Publisher.

What's the intended use for DynamicProperty's update() method? It seems most of the time the DynamicProperty's members are @Stateful objects managing their own state and using update() with them requires a dispatch async (to the next runloop cycle).

You’re definitely correct that the state management dynamic properties do is usually handled using their own sub-dynamic properties, and custom logic! The update method is called directly before the corresponding view’s body is called, and is more a place for any logic that needs to happen before body runs to occur.


So, for things that I assume are not stateful in nature, just derivates of the state?

That tends to be the case. That said, there may be some examples of property wrappers that use information about when the view is rendered to drive stateful systems. When debugging, I’ll sometimes use a DynamicProperty with an Int wrappedValue that increments whenever the surrounding view’s body is drawn, for example

Event handling

What is the difference between .onChange and .onReceive modifier.? ".onReceive is like a combination of .onAppear and .onChange", is this the complete and accurate picture?

onReceive is specifically to subscribe to Combine’s Publisher types and produce a side effect.onChange is used to produce a side effect when a property of your view changes. For example you can use that to produce a side effect when the scene phase in the environment changes.

It really depends on your use case: Is the value equatable? Is it a lightweight event? Does your view have constraints to adhere to, such as de-duping, debouncing, exponential backoff, etc.

When is onAppear/onDisappear called? How do they compare to the UIKit equivalents of did/willAppear?

The framework makes no guarantees on the specific timeframes on when these methods are called, but you can be sure that onAppear will always be called before the view is visible to the user and onDisappear will never be called while the view is on screen. We have recently updated the documentation for these methods online to clarify these details; see https://developer.apple.com/documentation/SwiftUI/AnyView/onAppear(perform:) and https://developer.apple.com/documentation/SwiftUI/AnyView/onDisappear(perform:)in terms of a comparison to UIKit, there is not a direct parallel. The UIKit methods are invoked specifically around when views become visible/not visible to the user, whereas the SwiftUI calls are tied more to when the views are constructed/torn down, rather than visually presented.

Is there a way to have an onChange(of:perform:) Modifier but only call the closure, when the state was changed by the user and not programmatically?

onChange executes its closure whenever the value change (that’s why we require the value to be Equatable). So onChange only know about comparing the value that your are providing.If you want to make that distinction you probably should model that difference in your state.

What is the difference between SpatialTapGesture and TapGesture?

For SpatialTapGesture the event in onEnded now provides the tap location.

How to identify the visibility (in index or id) inside a TableColumn View for paginate remote content.

Similar to techniques of paginating content in Lists, you can also use onAppear for TableColumn views in Table as well using the same technique. You’d want to compare the id of the column element to what you consider the “last” element’s id. We even using that technique in Photos in macOS Ventura.

Focus

Is it possible to set default focus on TextField when it appeared first time? Without workarounds with delay?

Yeah, checkout the new defaultFocus modifier! https://developer.apple.com/documentation/swiftui/view/defaultfocus(_:_:priority:)

What is the best way to resign (text field) focus from some distant view in the view hierarchy. scrollDismissesKeyboard is a great step in the direction I need, but I'd like to programmatically trigger that same behavior, for example, on some button tap.

For example, looking at ways to replace this code:

UIApplication.shared
       .sendAction(#selector(UIResponder.resignFirstResponder),
                        to: nil, from: nil, for: nil)

// as an action to perform on a view:

extension View {
    func resignFocus() {
        UIApplication.shared.sendAction(...)
    }
}

You can do this with the Focus State API: https://developer.apple.com/documentation/swiftui/focusstateYou want to bind a focus state property to your text field using View.focused(_:equals:), and then set the binding's value to nil/false from your button action as a way to programmatically resign focus and dismiss the keyboard when the bound text field has focus.Making the action available to distant views is a matter of arranging your app's data flow appropriately. There's no single answer, but for example, you could declare your focus state property on your scene's root view and pass a reset action down to any descendant views that need it. Or if the action is created by a leaf view, you can use the preferences system to make the action available to ancestors.

Gestures

Is there a way to access DragSession from DropDelegate (like UIKit)?

This API is not available. However, we'd be interested in learning more about your use case here.


One primary use is to determine if the drag started from the same app (either same view or from another scene)The other reason is to use that to pass data (where NSItemProvider works but is async and may be out of order)

My doubt is regarding drag and drop on SwiftUI

I think there are 2 approaches but I am stuck with both the approaches

WWDC22

  • When using the new draggable, dropDestination, Transferable API, I am only able to drag single items. I am unable to drag multiple items in a list. I have filed a feedback FB10128110

WWDC21

  • I have faced a couple of issues for drag and drop introduced in WWDC21 (onDrag, onDrop, itemIdentifier), the Feedback ids are FB9854301, FB9854569, FB9855245, FB9855532, FB9855567, FB9855575.

For now, I have one pointer that could be useful: for Lists and ForEach, we expect you to use the onInsert modifier. onDrag is designed for other types of views.


So draggable is the new approach however does it only support simple cases now (like single item drag for non-list and non-ForEach views)?

Yes.

Also using draggable I noticed there was no way to generate preview, or specify the item is to be moved (no green + circle) instead of copied

This is correct as well

So would slowly draggable grow powerful that would one day support all cases instead of ondrag?

Can’t comment on that.

Is there a way to coordinate between SwiftUI DragGesture with their UIKit counterparts in the UIGestureRecognizerDelegate like shouldBegin or shouldRequireFailure?

Sorry, no, there's no interop between SwiftUI gestures and UIKit gestures.


How about multiple SwiftUI DragGestures?

You can ensure exclusivity with this:

https://developer.apple.com/documentation/swiftui/gesture/exclusively(before:)


Does it work if there are two DragGestures applying to different views?

No, the exclusivity is only for a single gesture application.


Then my question would be how to coordinate them

They seem to conflict each other, and optionally I want to disable one over another

It's not supported. Please file a feedback request for this.

Can onTapGesture be used more than once on a single view? Like single-click to select, double-click to open in a window?

ItemView()
  .onTapGesture(perform: selectItem)
  .onTapGesture(count: 2, perform: openItemInWindow)

onTapGesture can indeed be used more than once but you need to get them in the right order, so that the double-tap fails before the single-tap succeeds.Something like this:

ItemView()
    .onTapGesture(count: 2) {
        ...
    }
    .onTapGesture {
        ...
    }

I'm trying to have .onDelete for delete and .swipeActions for other actions. It is not working this way. Any idea?

The moment you add .swipeActions it up to you to define the delete action (SwiftUI will stop synthesize that for you in the swipe action drawer).You want to create a button with a destructive role to achieve the same result:

Button(role: .destructive) {
    delete()
} label: {
    Label("Delete", systemImage: "trash")
}

Is there a way to know when a drop has been cancelled with .onDrag and the DropDelegate? While dragging I want to change the opacity of the view for the duration of the drag. I tried providing a preview view and using onDisappear but it isn't called either. There is dropExited but the user can still be dragging.

There is no API for this, and as you noted, the drop session state in DropDelegate is different than the drag session state.

Graphics

When implementing path(in: CGRect) of a Shape, are dynamic Property Wrappers  assumed offer the correct values, or is this only valid for bodies?

Shapes don’t have the same data flow primitives as views do, so things like state, environment, etc. won’t work, but don’t despair! You can still get the results that I think you might want. Since you’ll eventually be showing your shapes somewhere in a SwiftUI View, you can hoist your data flow up to the SwiftUI View level, then pass down that information about state, environment, etc. down to the shapes.

I'm working with CoreImage filters, and currently using the CIContext to create a CGImage, which is turned into a UIImage, which initializes a SwiftUI Image. Is there a better or more efficient way?

You should be able to avoid the intermediate UIImage and initialize a SwiftUI Image directly with a CGImage

How can I add use an SVG in my SwiftUI app?

You can add an SVG in the asset catalog and it can be rendered via a named Image.Checking “preserve vector content” (or similar) in the asset item preferences will render it from vectors instead of raster.

Grid

Is it possible to drag and drop grid items within the grid to reposition them in the grid?

Dragging and dropping between cells of a Grid would be a higher level component you'd want to build on top of the Grid layout

Are there any special considerations needed when putting a Grid inside a ScrollView?

Grid is eager, so putting it in a ScrollView can create performance issues, unless you’re certain the number of items is small.

Does Grid replace VGrid?

LazyVGrid and LazyHGrid arrange their children lazily and so are great fits for large amounts of content within a scroll view

Grid requires all of its children be loaded up front and because of that has some powerful features that the lazy grids do not

So basically, use Grid / GridStacks > VStack / HStack combination’s for more complex UI’s?

Each layout container SwiftUI vends had unique affordances that make it appropriate for different use cases.

Can Grid cells span rows and columns?

They can span columns. See https://developer.apple.com/documentation/swiftui/view/gridcellcolumns(_:)

Is Grid only for static grids? What if we have 1000 elements with images, etc.

For large grids consider LazyVGrid and LazyHGrid.

Is it possible to implement stack with wrapped items like this using Layout?

Untitled

Yes, it is definitely possible. The Food Truck sample code includes a simple "flow" layout: https://github.com/apple/sample-food-truck/blob/main/App/General/FlowLayout.swift

Can a column span partial columns in Grid? i.e. If I have 8 items in a three column Grid, I want the last row to have two cells that are 1½ columns each.

The column spanning uses an integer, but you could try doubling the number of columns you're using.

How would I go about making a Grid where all the cells are the same size based on the cell that needs the largest size to appropriately display its content?

To do this today you would need to do something more custom like creating a custom Layout. Though you might be able to to implement the custom Layout so that it calls into Grid itself, reusing its internal logic.

Layout

AnyLayout

How many layouts can you have in AnyLayout?

AnyLayout erases just one layout, but you can dynamically switch between them while preserving animations and State. You can switch between any number of layouts.

AnyLayout could be user selectable (if selection changed @State)?

Yes! As Paul showed in the video any State or property can drive conditional logic to choose between different Layouts using AnyLayout

Do all system stacks implement the Layout protocol for use in AnyLayout? Is this documented anywhere?

The goal is for as many system provided layouts to conform to the Layout protocol as possible, including the stacks. You can find what protocols a type conforms to in the developer documentation Yup, scroll down on this page: https://developer.apple.com/documentation/swiftui/hstack


AnyLayout does not require making copies of the same view, rather it is a concrete view that dispatches the layout behavior to a type-erased layout.

How can i get something similar to autolayout priorities, of being able to have 2 views in a stack equal but only up to a certain width?

You can pass any kind of information you like to an adopter of Layout.  So that "certain width" could be passed to the instance of the Layout itself. And the layout priority can be provided via the subviews proxy of Layout.

/// Views have layout values that you set with view modifiers.
/// Layout containers can choose to condition their behavior accordingly.
/// For example, a built-in ``HStack`` allocates space to its subviews based
/// in part on the priorities that you set with the ``View/layoutPriority(_:)``
/// view modifier. Your layout container accesses this value for a subview by
/// reading the proxy's ``LayoutSubview/priority`` property.

You can see the rendered version of that text in the docs under the heading “Access Layout Values”: https://developer.apple.com/documentation/swiftui/layout

Thinking about this more....Reasoning about this in terms of autolayout might make things tricker than they need to be, especially for 2 views.  For instance you could instead use a custom LayoutValueKey to say that View A should take 70% of the proposed size, and View B should take 30%.

Rough sample code:

MyCustomLayout(widthThreshold: 300.0) {
    viewA.oversizedWidthPercentage(0.7)
    viewB.oversizedWidthPercentage(0.3)
}

When using the Layout protocol, is it possible to resolve an alignment guide for the layout container, not a subview, to align the subviews relative to the container correctly? For instance, a Layout that proposes size (100, 50) would resolve HorizontalAlignment.center to 50 (if unmodified). If not, what is the correct way to do this?

You may be able to use the alignmentGuide modifier to define how an alignment guide for a view will resolve


My goal is to get the CGFloat value from the container view for its own alignment guides in the placeSubviews function. (Specifically, to do a layout similar to VStack where the children align in the left middle or right)

Well, you get the bounds of the region that you are laying out inside of, so you can know the midpoint in each dimension, for example

You can also set explicit alignment guides for the layout container by implementing either or both of the explicit alignment methods:

What happens to a subview if you don't call .place() on it in placeSubviews in a Layout? What happens if you call it twice?

If you call the method more than once for a subview, the last call takes precedence. If you don’t call this method for a subview, the subview appears at the center of its layout container and uses the layout container’s size proposal.

You interact with the subviews from within the layout protocol via the subview proxies that you get as input. This lets you do things like propose a size or place the view, but not perform arbitrary operations on the view, or apply arbitrary modifiers. If there’s something specific that you’d like to do but can’t, please do file a feedback with your use case.

When Layout will be calculated? From UIKit experience,  sizeThatFits fail to calculate size on viewDidLoad.

Layout participates in SwiftUI’s general update system. It will be computed when any state affecting the layout changes.

Does Layout support lazy-loading its subviews? Would it be a good replacement for UICollectionView with a custom layout?

Layout is eager. Eager means computed in advance. Lazy means computed only when needed.

Why are the subviews being placed with a y position of the layout’s midY rather than minY?

Because they were anchored by their center point.

Yes, you’d likely run into performance issues.

Can I use custom layout to create a hierarchical tree map/view of rectangular boxes of data items connected with lines?

Untitled

Layout could readily handle positioning the boxes. The lines would be the interesting part.

You might experiment with using the layout values to route information.

You could also experiment with using Canvas to do the drawing, though that’s a low-level approach that wouldn’t give you accessibility out of the box. Check out the accessibilityRepresentation modifier for that.

Ultimately, that’s “just” math. There are a few open source frameworks for diagram drawing. You might be able to see what algorithms they are using.

Do LayoutValueKey values travel up through nested Layouts? Also, how are they different from PreferenceKey?

LayoutValueKeys only travel up to the nearest Layout container. One reason for this is for Layout to facilitate building of encapsulations that can be composed without having unanticipated effects on the other views that surround it.

What examples of custom layouts do you think a new layout protocol is a best choice for?

Whatever you can imagine :upside_down_face: In the State of the Union we mentioned Flow and Radial layouts as good examples A custom layout can be a good fit if there's something super custom in your app It's an even better fit for building a generic layout container that you can reuse across your app (like Flow referenced above) Even really subtle, nuanced layouts can bring a little extra level of polish — plus be composed together! For higher level features like the new form style on macOS we’re using several small custom layouts to get it to perfectly match what the design specs described

I am thinking of a dynamic layout case for seating order around tables. User could create a new Table, specify if the table is rectangular, oval or circular, and specify the number of guests at each side. We could then get a layout for the table as specified, and the user can fill in the guests. In code terms, this could mean that the specific layout should be created dynamically. Would something like this be possible?

That sort of thing is definitely possible! In fact, in the what's new in SwiftUI talk, they show an example of a layout which is very similar to what you’re describing to make a seating chart for SwiftUI’s birthday party!

Is there a way to build a Layout that would effect each child view with ViewModifiers? Let's say I always want to style the first view one way and the second another.

LayoutValueKey allows you to pass information from your view hierarchy along to layout, but please note that layout can't use this information to make style changes to the view, only to determine its layout.The information is passed through to layout through layout proxies, so the original view isn't accessible from the layout protocol.

How does Layout interact with other view modifiers or constructs that can provide layout data, like offset, geometry reader, anchor preferences, etc? (For context I've got a card game-type view that currently lays out cards in columns all powered by GeometryReader and anchor preferences, because I need specific frame data when a user performs a drag gesture to drag a card over a region of the screen to perform logic. I'm wondering if it's possible to re-implement it in Layout, but I'm unclear about if it's possible to get at the anchor preference frame data.)

A layout is only able to position its direct subviews.It can  be superior to GeometryReader because it's able to do that while also computing a sizeThatFits.If you're trying to arrange things that are crossing parent-child boundaries, though, anchor preferences will likely still be necessary.

I am trying to create a new custom Layout. I would like to know how to access LayoutValueKeys from within a Layout.

The documentation for the new layout API is fantastically written and should have all of the information you need to get up and running! It explains it far better than I could in a short question answer. You can check out the docs for LayoutValueKey here. It even has a walkthrough that shows you how to create, set, and retrieve keys! https://developer.apple.com/documentation/swiftui/layoutvaluekey/

Should Layout work fine with UIKit-representable views?

Yes! To get more control over how UIViewControllerRepresentables size themselves in SwiftUI layout you may want to implement their new sizeThatFits method: https://developer.apple.com/documentation/swiftui/uiviewcontrollerrepresentable/sizethatfits(_:uiviewcontroller:context:)-35p75.

Is it possible to use @State, et. al from within a custom Layout? Or is there a different way we should parameterize our layouts? I noticed that the protocol doesn't inherit from View, so I wasn't sure if using the property wrappers would work.

You can add input parameters to your layout, and you can attach values to particular views using the LayoutValueKey protocol. To store data between calls into your layout, you can use the cache, but that’s only to avoid repeated calculations, and you should be prepared for the cache to go away at any time.


Okay, so anything stateful should live in the parent view (and be passed as init args) or in a child view (and be read through a LayoutValueKey) ?

Yes

As we get more and more familiar with SwiftUI we use GeometryReader less and less, but what are some tells that there's no way around it?

If you want a visual effect like corner radius, opacity, or color to depend on your geometry, GeometryReader is the way to bridge between these two worlds.

Layout gives you a superior tool for encapsulating layout logic for re-use. And while using GeometryReader you can position children, the GeometryReader can't reflect back any custom sizing behavior. This is one of the reasons it can become unwieldy when used in complex layouts—because the GeometryReader becomes fully flexible.

About SwiftUI’s Layout:When creating a custom Layout, is it OK to use another Layout within the func like sizeThatFits or placeSubviews, including the built-in Layout (like HStack)?More specifically, is it possible to compose some HStack and VStack within my custom Layout? In that case I have to create a LayoutSubview by myself, is it possible?

Yes this is an explicit use case the Layout protocol was designed to support

Yes, that should be fine, although you'll need to manage the cache(s) of any intermediate layouts you use. (E.g. store them in your own layout's cache storage, and invalidate them as needed.)

You can also create subsets of the subviews collection, to pass to the inner layouts.

… use the LayoutSubviews subscript(bounds:) operator for that.

SwiftUI Layout isn't possible for dynamic content, right? Since each subview need to be there at calculation time.

It could depend what you mean by dynamic content

The SwiftUI layouts you write yourself, like the system provided HStack and VStack, require all children up front

However, often we use "dynamic" within the team to refer to content driven by a ForEach

And that is absolutely supported with custom SwiftUI Layouts

The main thing that SwiftUI Layout doesn't support today is the lazy/incremental layouts that don't need to load all views up front

There is not a way to build your own LazyHStack and LazyVStack on top of SwiftUI Layout... or at least not one that is as efficient in lazy loading content

the SwiftUI framework automatically manages dependencies between views and will recall your layout's sizeThatFits or placeSubviews whenever anything needs to be recomputed (including child size changes)


So, if the Layouts could’ve been lazy, that means that the views in the Layout would’ve been loaded only when needed (when they appeared on screen)? I’m asking this to make sure I understood the concept of lazy grids.

That's correct. A lazy Layout theoretically wouldn't have access to all of its children up front from sizeThatFits or placeSubviews, and so that limits some of the things it can calculate up front. Paul covers this well at the beginning of the "Compose custom layouts with SwiftUI" talk from yesterday: https://developer.apple.com/videos/play/wwdc2022/10056/


So many detailed and nuanced OS features were made possible thank to the new Layout protocol!
I can say this, since I didn’t work on it: The documentation for the new Layout protocol is some of the best technical writing I’ve seen.
The GeometryReader + preference keys pattern frequently led to issues like layout cycles and too-frequent updates. I am also very glad to see that Layout obviates the need for many GeometryReaders.

macOS

Are there any types of macos apps or interfaces where you would still recommend using appkit rather than swiftui?I'm yet to invest the considerable amount of time learning swiftui and I keep reading mentions of people saying it's still a mixed bag for macos development, so I don't want to potentially waste time.  Thanks!

Good question! Across all platforms, we’d recommend comparing your needs to what SwiftUI provides (so no hard rules/recommendations) — and keeping in mind that you can adopt SwiftUI incrementally.Within Apple’s own apps on macOS, we’re ourselves using the full spectrum of approaches. From just a specific view/views in an app, e.g. in Mail, iWork, Keychain Access; to an entire portion of the UI or a new feature, e.g. in Notes, Photos, Xcode; and all the way to the majority of an application, e.g. Control Center, Font Book, System Settings.But in the end, I’d recommend starting with a part you’re comfortable with and building up from there! You should look at SwiftUI as another tool in your toolset in enabling you to build the best apps you can.

When opening the Control Center via the Menu Bar Extra, the button remains highlighted while the Control Center is visible. Is there a way to replicate this using the new MenuBarExtra API?

I think this is likely just a bug with the framework at the moment, and that it should behave similar to Control Center by default. If you could please file a feedback for this, I'd appreciate it.

When using the new MenuBarExtra in window style is it possible to control the width and maximum height of the content window?

The window size should be derived from the content provided to it, though we do impose a minimum and maximum on the resulting size. If you are seeing unexpected behaviour in this area, please do file a feedback with a sample to reproduce it, and we can take a look.

When creating a MenuBarExtra, is it possible to create something that runs on its own, separate from the parent app? I have an app that users can save data to by means of various app extensions. If the app is closed, however, those changes don't get synced to CloudKit. I was thinking of having a menu bar app that would essentially be my workaround: always listening, always active. Can a MenuBarExtra do that for me?

You can certainly define a SwiftUI App with only a MenuBarExtra Scene. If your app should not show a Dock icon, that will require some changes to the Info.plist file, which should be noted in the documentation for MenuBarExtra

See https://developer.apple.com/documentation/swiftui/menubarextra

Posting that bit of documentation here as well:

For apps that only show in the menu bar, a common behavior is for the app to not display its icon in either the Dock or the application switcher. To enable this behavior, set the LSUIElement flag in your app’s Info.plist file to true.

I have a macOS app where I am attempting to 'tear off' certain SwiftUI views as floating free form windows. I've looked into some of the WindowGroup API, but it doesn't seem like it supports what I'm looking for. Essentially, I have N views of various sizes that can either be docked into a main window, or float above it. I'm running in to issues like sharing state between the docked version and the windowed one, as there seems to be a difference in the relationship between how a standard SwiftUI update bindings works for windows or views. Given that, what would be some ways that I could go about this method of 'docking / undocking' SwiftUI views, and keeping their state in tact?

This is really interesting! I'm not really sure we have any API that entirely fits your concept here, but I'd love to learn more. Can you speak to how you are accomplishing this at the moment? Also a feedback for this with any details you provide would be great!

With the new MenuBarExtra. Is it possible to get a callback when the content window appears or disappears. I’ve tried onAppear but it’s only called on first appearance. OnDisappear is never called.

This sounds like it is probably a bug. Could you please file a feedback for this?

SwiftUI Mac specific question: When using .contextMenu on a List , how can I find out what was actually selected?When looking at Finder, the selected (=item on which the action should be performed on) is either the selection (1 or more) OR it is the item that has been right clicked on directly.How can I replicate this behavior using SwiftUI?

Check out the new context menu API that accepts a forSelectionType parameter. This passes the value of the selection into the modifier for you to act on.

List(selection: $selection) {
 ...
}
.contextMenu(forSelectionType: MySelection.self) { selection in
 // check selection
}

Be sure to match the type of your lists selection to the type you provide to the context menu modifier.

https://developer.apple.com/documentation/swiftui/view/contextaction(forselectiontype:action:)

SwiftUI on macOS question: Is there a way to position the windows when they are opened? In my app, the position of the next window always depend on the last, offset a bit to the right and down. So they are slowly crawling down the screen, which is not nice.

The cascading of windows is the default behavior for WindowGroup. We've also added a new Scene modifier - defaultPosition, which allows you to specify an initial position to use absent any previous state for the window. It takes a UnitPoint, so for example, it would be something like defaultPosition(.topTrailing). Did you have some other behavior in mind? It'd be great to get more info, if so.


It would be nice if I could position a new window just beside the already open window, e.g. to the right or left, depending on the available space.The second window is a “compagnon” to the document, used for editing.

Ah, I see. That makes sense given your use case there. Would you mind filing a feedback for an enhancement?

SwiftUI Mac specific question:When using NavigationView, is there a way to start the app with a the sidebar already collapsed (or do it programmatically)? I saw this in on of the videos. Bonus question: Can this also be done on macOS Monterey?

The new NavigationSplitView API provides an initializer which takes a binding indicating the visibility of the columns. This can be used on macOS to indicate that the sidebar should be initially collapsed.

There is an example in the documentation here:

https://developer.apple.com/documentation/swiftui/navigationsplitview/

I have a UIKit app on iOS. I am at the point of needing to decide—do I ship it for macOS with Catalyst, or given I’m doing a major redesign anyway, do I migrate it to be a SwiftUI app.

I am wondering—are any of the features/capabilities that I would have in a Catalyst app to make the app more "Mac like" that are not available on macOS using a native SwiftUI app? e.g., the "Bring your iOS app to the Mac" session showed the ability in Catalyst to enable/disable the traffic light buttons when they were not appropriate for that window. Is this kind of control also available in SwiftUI on macOS?

With regards to your last part around the window controls (traffic lights) - SwiftUI will enable/disable these depending on the content of the scene. So, for example, a content view with a fixed size, will have the zoom and fullscreen button disabled. I'd also like to point out that on macOS Ventura, SwiftUI App lifecycle windows will be fully flexible by default (they can be resized to the maximum allowed by the screen). This can be opted out with a new Scene modifier - windowResizability. ie:

WindowGroup {
}
.windowResizability(.contentSize)

Enabling/disabling of full screen behavior is also related to the maximum size of the window's contents and how that relates to the screen size of the device. If there are other aspects that you would like to customize here, a feedback would be appreciated as well.

SwiftUI macOS: How can I control how the focus moves around the controls of my view when I press "tab"? Currently it jumps from top left to right, then down. But I have two columns in my window and would prefer it go down first on the left side and then again up to the right.Is there some functionality to pre-define the order of the controls?

You can use View.focusSection() for this, which is newly available on macOS 13.0. Marking a view as a focus section causes the Tab loop to cycle through all of the section's focusable content as a group before moving on to the next thing in layout order. So, something like this should get you the sort of column-wise navigation you're after:

struct ContentView: View {
    var body: some View {
        HStack {
            VStack {
                FocusableView()
                FocusableView()
            }
            .focusSection()

            VStack {
                FocusableView()
                FocusableView()
            }
            .focusSection()
        }
    }
}

Also, a plug for my colleague Tanu's WWDC21 talk: Direct and reflect focus in SwiftUI https://developer.apple.com/videos/play/wwdc2021/10023/ It goes over some tvOS use cases for View.focusSection(), and also describes how to work with focus programmatically using focus state bindings.

With the new MenuBarExtra API on the Mac, if I want the menu item to be persistent after my app quits, do I need to do any extra work (e.g. adding a login item) or does the system automagically make sure it appears after reboot/logout?

You can certainly use MenuBarExtra to create a standalone menu bar app, though you may want to look into the Info.plist changes noted in the documentation:

For apps that only show in the menu bar, a common behavior is for the app to not display its icon in either the Dock or the application switcher.To enable this behavior, set the set the LSUIElement flag in your app’s Info.plist file to true.

If the menu bar app is used in conjunction with a main app, then you'll need to package it together (ie, the "helper app" model). Adding a login item sounds like the way to go if you want it to show at login regardless of the user's preference for restoring state.

I'm trying to mimic the 3-view layout in Xcode, Pages, Numbers, etc.  using SwiftUI.Sidebar | Document | InspectorI can use the NavigationSplitView for the Sidebar and Document, but I can't find a way to animate the Inspector in a right sidebar. The SwiftUI animation usually animates all the child views in the Inspector's view. Is there a way to do this in SwiftUI on the Mac?

One thought we had here is potentially using an HSplitView as the view for your detail, and having one of its children be the inspector. The animation not working is likely a bug, and we'd definitely appreciate a feedback about it.

With MenuBarExtra, is it possible to have a primary action that's triggered when the menu bar item is clicked and then a separate menu that's shown when the item is option clicked?

This isn't something we have support for at the moment, but a feedback with any details you can provide would certainly be helpful.

As of Monterey, List supports drag-and-drop reordering of items on macOS and iOS/iPadOS, but it seems that other types (e.g., HStack, VStack, etc.) support drag-and-drop reordering of items on macOS only in Catalyst apps. In any other kind of macOS app, the same SwiftUI code that works as expected in iOS/iPadOS and Catalyst doesn't work (i.e., a drag cannot be started at all). The code compiles just fine, but it doesn't actually work.

How can I support drag-and-drop reordering of items (or sub-Views) in SwiftUI code in HStacks, VStacks, etc. in non-Catalyst macOS apps? Here's some code that allows a drag to be started on macOS in Catalyst but not on macOS outside Catalyst: https://pastebin.com/VvJgDq0x

Hm, have you tried to provide the contents to the NSItemProvider instead of nil ? It is possible that empty NSItemProviders are treated slightly differently on different platforms.

Changing that line to this worked. Thanks!**return** NSItemProvider(item: item **as** NSSecureCoding, typeIdentifier: "public.text")

To enable macOS-native UI in your Catalyst app, go to your target's settings: General → Deployment Info → Mac Catalyst Interface, and switch from "Scaled to Match iPad" to "Optimize for Mac".

Controls in SwiftUI will automatically adapt to be more Mac-like in that mode. Also check out the new Form styles, to have the controls arranged in a traditional Mac columnar layout.

This year, there is the new FormStyle support, with FormStyle.columns available on all platforms, including Catalyst. That creates a Form layout like the default on native macOS with trailing aligned labels next to the leading aligned controls https://developer.apple.com/documentation/swiftui/formstyle/columns

Form {
    Picker("Notify Me About:", selection: $notifyMeAbout) {
        Text("Direct Messages").tag(NotifyMeAboutType.directMessages)
        Text("Mentions").tag(NotifyMeAboutType.mentions)
        Text("Anything").tag(NotifyMeAboutType.anything)
    }
    Toggle("Play notification sounds", isOn: $playNotificationSounds)
    Toggle("Send read receipts", isOn: $sendReadReceipts)

    Picker("Profile Image Size:", selection: $profileImageSize) {
        Text("Large").tag(ProfileImageSize.large)
        Text("Medium").tag(ProfileImageSize.medium)
        Text("Small").tag(ProfileImageSize.small)
    }
    .pickerStyle(.inline)
}
.formStyle(.columns)

Is it possible in SwiftUI on Mac to use a modifier with a mouse click like ⌘-leftClick? I like to select non-adjacent items like in Photos and Finder.

Gestures have  .modifiers(_:) modifier, which allows restricting that gesture to only respond when the modifier is active. So in this case you could use a Tap gesture with .modifiers(.command)

Split

Will NavigationSplitView allow sidebar on the right?

Right-hand sidebars are not supported by NavigationSplitView.

Can split views have priorities set for each panel? For example in a 3 panel configuration, I want the middle. view to expand when you resize a window.

Check out the .navigationSplitViewColumnWidth modifier https://developer.apple.com/documentation/swiftui/view/navigationsplitviewcolumnwidth(_:)

Does the new NavigationSplitView preserve state when we switch to a new navigation destination like tab bar in UIKit, or do we need to roll our state restoration, like what we had to deal with using the old TabView?

If you want to switch to a TabView in narrow size classes, you’ll want to design a navigation model type that provides selection information for the NavigationSplitView in regular size classes and a different projection of the same information to a TabView that’s shown in narrow size classes.

Windowing

Can Window be used for splash screen finally (such as What’s New? or News startup) . I’ve had a lot of issues making Scenes work for Document-based (and opted out on iOS) because it starts an app with a Nondescript Files.

Window is likely not the best expression for these types of onboarding experiences. A feedback for this type of functionality would definitely be appreciated though! For iOS support of Window, please check release notes for future changes.

Would it be possible to have / pass separate NSManagedObjectContext for each window?Reason: Like for example if I have multiple windows on a Mac app and I want to create something temporary on to a specific window till the user decides to save it and make it available on all windows.

You could take a look at the new WindowGroup initializer which takes a binding to a value presented for the window. You could potentially use this value to determine your managed object context.

How do you pass data to a new window? openWindow

looked in the session like it only takes an id parameter to help determine which window type should open, but suppose you want to inject a model object into that window?

There is a version of openWindow which takes a value as well: openWindow(value:).


Is NavigationView deprecated?

Soft-deprecated. We recommend against it in new code, but it would not be a compile time warning. All the community feedback really helped us understand the use cases and tough spots.

I have an issue in which I am passing @Binding to the child navigation view from root view, when update the @Binding variable from child view, the view pops back to root view. Will the new NavigationStack fixed this issue?

Danny, the most common cause of that is that you’re accidentally invalidating the view surrounding the NavigationView, causing it to be replaced.

Am I understanding right that the navigation destination data cannot be a class object (such as an NSManagedObject) and I would need to use something like a string to represent the object?

Object instances should work fine.

Check out the SwiftUI Navigation Cookbook talk, there is a lot of flexibility that you can get from having full control cover the path. The path of a NavigationStack doesn't necessarily have to live in the same View as the stack — it can be higher up in your app's architecture. One approach is to bind a path to the surrounding NavigationStack. Then use an onChange modifier to observe the path.


My concern was to work in a leaf view without any path knowledge, while still being able to locally perform logic when some NavigationLink is activated. The objective is to avoid leaking the parent model into the child, but still have some logic around navigation being performed by the child. The idea was to perform the check locally, without any access to the stack or its path.

Alternatively, you could have a button that appends to the path. To get the data separation you’re looking for, you might need to pass an action in the environment or as a parameter that would do the appending. But if a Button is equivalent in terms of rendering/behavior, that's indeed a possible workaround. My concern with NavigationLink with value is that the values are eagerly evaluated.

Only for links that are on-screen or in an eager container.

If Button is equivalent to NavigationLink in terms of UI or behavior, then I have no concern with eager evaluation. Ideally, the value would only be created when the link is activated. But maybe there are some internal constraints forcing an eager evaluation.An autoclosure might be reasonable here. NavigationLink gets the chevron in some contexts, but is otherwise a button.

Is it possible enumerate a NavigationPath or replace certain elements?

It’s not currently possible to enumerate a NavigationPath. Because it’s type-erased, the elements could only be exposed as any Hashable so  aren’t directly useful.

Generally, if the set of things that can be added to a path form a closed set, which would be the case if you can usefully enumerate it, I’d recommend wrapping your presented values in an enum with associated types.


I’m wondering if having a mutable collection of enum values might be generally more useful than using a NavigationPath.

Then use an array of that enum instead of NavigationPath.

The disclosure indicator isn’t currently customizable.

With the new NavigationStack and path binding, you can use a regular Button and append your value directly to the path.

Is there anything different visually, to the user, between a NavigationView and a NavigationStack?

They’re both structural components, but they do behave a bit differently.

NavigationView renders differently depending on how many views you pass to it and what navigationViewStyle you set on it.

NavigationStack takes a single root view and always renders as a stack.

NavigationView is only soft-deprecated and so will continue to work fine in all its existing use cases with no compiler warnings. If writing new code, however, we recommend you start using NavigationStack.

On iPadOS in a NavigationView, Is it possible to switch between two column and three column layout depending on what is selected in my sidebar?

It isn’t possible to do that directly.

Often those style of UIs can be built by swapping the view in the detail area between a single root view and an HStack with two-elements.

That is, instead of conceiving of it as a two or three column NavigationSplitView, think of it as a two-column one, where the detail column itself has one or two columns.

Previously in NavigationView on iPad, the detail view would be displayed with the ForEach list being collapsed in a sidebar. With the new NavigationSplitView, can I use a modifier to not collapse the ForEach list?

Thanks for the question. NavigationSplitView takes a columnVisibility binding. You can set it to .all to reveal all the columns programmatically!

Is it possible to use SwiftUI Navigation for iOS 15? How can we transition to it on the existing project?

To learn how to transition your existing projects to the new navigation types, see this handy migration guide: https://developer.apple.com/documentation/swiftui/migrating-to-new-navigation-types

Can we set the NavigationPath from onContinueUserActivity and onOpenURL?

This is certainly something you can do, and is a good example of how you can support something like deep linking, for example, by parsing the URL provided to onOpenURL and using it to construct your navigation path.

NavigationLink( ... )
    .contextMenu {
        ViewIWantToPreview() // is not previewed
        Button { ... } // other options show correctly
    }

Yes, use the new contextMenu overload that accepts a preview view.

NavigationLink( ... )
    .contextMenu {
        Button { ... }
    } preview: {
        ViewIWantToPreview()
    }

Here’s some more detail on that new modifier: https://developer.apple.com/documentation/swiftui/view/contextmenu(menuitems:preview:)

Can I have the user tap the preview to open another view (the “full” view) as well? I'm playing around with it in Xcode previews and it seems like tapping the preview just closes the context menu.

No, it's not currently supported— please file a feedback request.

I am curious is it possible to navigate from SwiftUI view to UIViewController.Is it possible to pop out from the SwiftUI view  back to UIViewController?

You can push a UIViewRepresentable onto a NavigationStack, and use that to wrap a UIView.

That works with the view-destination NavigationLinks inside a NavigationView as well for previous releases.

Check out the SwiftUI Cookbook for Navigation session and the What's New in SwiftUI session for 2 examples of deep links

They are indeed possible, and we think they work pretty well ;) Of course, there's a lot of routing to consider with any app — for instance if your deep link is behind some authentication token, you'll need to do the extra work there.

The general idea is that a deep link is certain destinations presented — in order — on a navigation stack, and with this years' new APIs you can have full control over what is on the navigation stack.

I remember before from the NavigationView API, that when SwiftUI automatically switches from a split navigation style to the stack navigation style, for example when switching from portrait to landscape on iPhone 12 Pro Max, the selection state wasn’t preserved and some UI glitches happen. Was that all solved with the new APIs?

It should be easier with the new API, but it’s also possible that the selection issues were caused by how the app modeled the data.I guess I’m saying it’s still possible to write bugs.

In general we discourage to do any expensive work in the init of a view. SwiftUI expects the creation of views to be cheap.We recommend doing any side effect or data loading with either .task or .onAppear.

Check out the new NavigationStack. Inside that NavigationLinks can present values instead of views. The resulting view can then do work in onAppear or using task.

In our app, we can push a view containing a custom view above the navigation bar. We achieved it by using a NavigationView inside a NavigationView (displaying a custom view with the back button hidden).Is it possible to have a custom view above the navigation bar with NavigationStack? Is it possible to use a similar workaround?

Nested navigation stacks don’t compose the same way. An inner navigation stack is effectively a no-op; it doesn’t add anything and any path bound to it should be ignored.

With NavigationPath, I've already felt the need to pass it down to child views as a @Binding or @EnvironmentObject so that they can influence the stack programatically. Is that a reasonable approach or am I overlooking something?

Passing the binding or passing a navigation model as an environment object are both reasonable approaches with the API we have available today.I hope we can make this more ergonomic. I’d love a Feedback with your use case! I personally like the navigation model approach, since I can easily do other work when the navigation state changes without putting that code in my Views. But either approach works fine.


So, a ViewModel (probably observableobject) that dictates navigation?Yeah. That works for the way I think about navigation.

In SwiftUI, is there a way to listen for navigation events or would that have to be custom from UIKit delegates?

With the new iOS 16 NavigationStack, you can bind a path to the stack. Then you can use the .onChange() modifier to watch for changes to the path.

What about non navigation events like dismissal of sheets or full screen modals? Is there a stateful way to be informed of when these events are done so we can say present a follow up confirmation or pop the navigation stack back?

Those dismiss events will reset the binding that caused the modal presentation to appear. So the same recommendation works there. You can use onChange() to observe that binding too.


What if you’re programmatically changing those bindings? If I set an isPresented var to false to dismiss a modal, how would I be able to know when the modal is actually gone? If I change the navigation backing state right away to pop a view or try and set a sheet as not to display , I’m usually presented with inconsistent UI behavior or a message saying that I’m trying to present / dismiss in an invalid state.

I’m usually stuck doing something like asyncAwait after and then playing with the timeframe and that’s, well, gross.

The delay hack is one approach.

Another approach people seem to have some success with is using a common sheet modifier for a variety of presentations.

Then you can drive the sheet with an optional enum state.

Set it to nil to dismiss, or switch between different non-nil values to present different sheets.

We’re also made some improvements in iOS 16 to make the invalid state issue much less common. For example, we try to delay the presentation of the next sheet until the previous one is gone. So you might find that things just work now. :)

I am new to SwiftUI, what is the best way to Switch between Views? For example, depending on the condition of a @State variable how can I switch between a HomeView, SignInView and SignUpView?

You can actually use switch statements directly in SwiftUI! e.g.

enum Screen {
    case home
    case signIn
    case signUp
}

...

@State private var selectedScreen: Screen

...

var body: some View {
    switch selectedScreen {
    case .home:
        HomeView()
    case .signIn:
        SignInView()
    case .signUp:
        SignUpView()
    }
}

Depending on your needs, NavigationStack is also a great tool to use for this, directly manipulating the current path :+1: But if you just need to swap views in and out, a switch works just fine. For example, it’s common to use a switch to choose the detail view of a NavigationSplitView based on the current selection.

SwiftUI and EnvironmentObject: do we have to pass the object every time we use a NavigationLink?My app crashes when ViewA adds an EnvironmentObject Post when displaying ViewB, and ViewB navigates to ViewC where ViewC accesses the Post object. Cf: https://developer.apple.com/forums/thread/707659

I think the answer on the Dev Forums is the correct one, does it solve this problem?

Your TagView requires BOTH a post and a tag but you are only passing a tag environment object...

Navigation destinations inherit their environment from the stack in which they appear, not from the context in which they are presented.

So the navigation environment of a previous view on the stack doesn’t affect the subsequent view.

I think you could move your .navigationDestination(for: Tag.self) into PostView, then propagate both the tag and the post into the TagView from there.

The parent environment is the one for the whole stack.

By which I mean the surrounding NavigationStack, not the views on the stack.

A view can’t have two parent environments. Consider the two ways we could propagate the environment:

┌────────────────────────┐                             ┌────────────────────────┐              
│    NavigationStack     │                             │    NavigationStack     │              
└────────────────────────┘                             └────────────────────────┘              
             │                                                      │                          
             │  ┌──────────────────────┐                            │  ┌──────────────────────┐
             ├─▶│      Root View       │                            └─▶│      Root View       │
             │  └──────────────────────┘                               └──────────────────────┘
             │                                                                     │           
             │                                                                     ▼           
             │  ┌──────────────────────┐                               ┌──────────────────────┐
             ├─▶│     Pushed View      │                               │     Pushed View      │
             │  └──────────────────────┘                               └──────────────────────┘
             │                                                                     │           
             │                                                                     ▼           
             │  ┌──────────────────────┐                               ┌──────────────────────┐
             └─▶│     Pushed View      │                               │     Pushed View      │
                └──────────────────────┘                               └──────────────────────┘

We chose the one on the left and leave it to developers to propagate any additional information as needed. This reduces the number of dependencies.

Is it possible with SwiftUIs new NavigationStack to hide the tabbar of a TabView when the destionation view appears. With the existing NavigationView it was possible but not so easy to handle the navigation title and buttons.

Take a look at the new toolbar visibility accepting modifier. This is new in SwiftUI and allows configuring the hiding or showing of different bars like the navigation bar, or the tab bar.

ContentView()
 .toolbar(.hidden, in: .tabBar)

See https://developer.apple.com/documentation/swiftui/presentedwindowcontent/toolbar(_:in:)

I wrote small test NavigationStack. But when I click on 'Click Me' button the back button automatically appear in the toolbar. How I can hide or customize this back button? PS: It's on macOS

struct ContentView: View {
    var body: some View {
        NavigationStack {
            VStack {
                NavigationLink(value: 123) {
                    Text("Click Me")
                }
            }
            .toolbar {
                ToolbarItem {
                    Button {
                    } label: {
                        Text("Done")
                    }
                }
            }
            .navigationTitle("Title")
            .navigationDestination(for: Int.self) { value in
                DetailView()
            }
        }
//        .toolbar(.hidden, in: .windowToolbar)
    }
}
struct DetailView: View {
    var body: some View {
        Text("Detail View")
            .navigationTitle("Title")
            .toolbar {
                ToolbarItem {
                    Button {
                    } label: {
                        Text("New Button")
                    }
                }
            }
    }
}

It isn't possible to hide the back button, but a feedback asking for this could help us gauge additional interest for it. Especially whether you'd like to hide or customize.

In SwiftUI when you had a List view with items that were continuously synced with a server and you displayed the details view of a selected item then the app jumps back to the main list. Are NavigationStacks solving this problem?

Generally the popping back problem is because there is a state change that’s invalidating the view that contains the NavigationView. This causes SwiftUI to discard the NavigationView and create a new one, popping you back to the root.

Check out Demystify SwiftUI from #wwdc21https://developer.apple.com/wwdc21/10022 for more details on view invalidation and identity.

With NavigationStack, you can bind a path, so the popping back shouldn’t happen.

But you should still investigate why the identity is changing. That’s likely a source of performance problems, since lots of extra work will happen. In the new navigation API, that new work will be to replace the entire navigation hierarchy.


Isn’t it better to stop syncing List with a server in time if you are in the detail view?

That’s really up to the specific app design. Many times that would be right, but some apps might want the root view to be always correct immediately when the user pops the stack. Or maybe the backend doesn’t vend the details separately.


Stopping the sync is in our case not possible. As Curt C mentioned, it can also be a state change that causes the back popping. It is really the NavigationLink as he said. I tried to set identifiers for the link itself or the destination view but the effect is still there. But I will test it with the new NavigationStack. Maybe this solves the problem.

Explicitly setting an identifier isn’t a solution if the structural identity of the view containing the NavigationStack is also changing

Explicit identifiers can be used to force an identity change, but not to prevent one.

In practice the identity of a view is a combination of its structural and explicit identity.

Previews

We’ve been getting some questions regarding the new previews experience where each preview is given its own tab, and folks are wondering if there is a way to instead have multiple previews in the same tab.

Each view in the PreviewProvider now shows in its own tab. If the individual views are differently configured rows for a list or can be combined in a VStack then a single preview could be used for seeing the different configurations. We'd love feedback if you have a unique case that you don't think is covered by the current solutions!

We’ve been seeing some confusion regarding the behavior of the  .previewLayout modifier in the new previews experience which we wanted to address.

the .previewLayout modifier does indeed still work, but like previous releases it does not affect the live preview which means you'd need to switch to the new Selectable mode to see its effect.

Untitled

What is the best way to debug issues with the Live Preview when an error isn't thrown / the build doesn't actually fail and the "Diagnostic" button isn't available? In some instances when I resume the Preview, a "Build for Previews" is launched and then stops shortly after, pausing the preview again

In the new Xcode the diagnostic button is now always available in Xcode's menu Editor > Canvas > Diagnostics, so you can access them even when the canvas doesn't show an error banner. Hard to say without the diagnostics (and potentially your project) what the root cause is, but from the symptoms it sounds like maybe your project has a script phase that modifies some of the source as part of the build? If you file a feedback with the diagnostic we might be able to help narrow down where things are going wrong.

Is there a newer way to debug a view while it's in preview?

Best way to debug a preview now would be to use Xcode's menu item Debug > Attach to Process (or the Process by Pid or Name) and select/use the name of your app. Then update a string literal in that view and it should cause the View's body to get called and hit any breakpoints you've got in that code.

Is there a way to enable interaction with the new device variants in previews?

No, unfortunately not. The preview is only interactive when viewing it in the Live mode, and all the other modes are static previews

Is there a way to make the Live mode preview landscape?

yes, use the Device Settings button to change the orientation to be landscape

We can now use preview to instantly see different dynamic type sizes and schemes all at once when using SwiftUI in XCode. Can we also see different devices at the same time? e.g. all iPhones that support iOS16

We do not currently have variations on devices/device types available. We are actively monitoring for what set of variations the community would find the most useful, so please do file enhancement feedback reports with examples of where and how you think a new set of variations would be useful.

Can charts be used in the new Preview option to see a live chart in the preview without needing to go to that screen? Such as current screen allows new data entry and the preview shows the updated chart?

Swift Charts behaves like other Views and updates the same way.

Is there a way to export/save a screenshot directly from Previews?

There's no way to do this now, unfortunately -- but that's a good idea!

Not directly related to previews, but you might be able to automate some of your snapshots using the new ImageRenderer view announced this year: https://developer.apple.com/documentation/swiftui/imagerenderer(Doesn't include the device chrome, of course.) it would just be the contents of the View, not include status bar

Is there a way to add a "Custom variants" to Xcode Previews?f.e. I think it'd be a good idea to add RTL/LTR variants

There is not currently a way to add custom variants, but that's a great idea!

My Previews take generally a long time to render, often failing (timeout) and sometimes it's quicker to just launch a run on the simulator. Also, it takes some huge place on disk (40GB+). Any hint to optimise all this and make the Previews quick, light and reactive?

If you're experiencing long times to render there might be something specific about your setup. Filing a feedback with a sysdiagnose taken while the preview is taking the long time to render would be very helpful for us to diagnose this.

As far as general tips to keep things fast, it helps to break up you views into smaller components where possible. And if your app project itself takes a long time to build, then it could be very helpful to split your Swift UI views out into a separate framework target so they could be built without the burden of the rest of the project.

I think the general theme is trying to focus on building as little as possible. If you can build out those new SwiftUI views in a framework / package, you can opt to build just that package rather than all of the app.

Yup, packages would be fine, too. It's even easier to use them in Xcode now. The larger point is to break out the parts that need Swift UI into their own targets that can be built independently. It might even help to have a separate "previewing" app target that you link your Swift UI views into instead of your main app. It all depends on your setup, of course. The tl;dr is that Previews needs to build some target to get its work done. If your whole app target is large and slow to build then it will be the bottleneck for previews that you can investigate.

As of Xcode 13, there are some gotchas with SwiftUI Previews and custom build configurations not named Debug or Release.

• SwiftUI Previews are not compiled-out unless the active build configuration is exactly named Release.

• Source files under the Preview Content directory are compiled-out for non-debug builds (whether this is looking for the active build configuration to not-be-named “Debug” or whether it’s based on code optimization levels, I do not know)

So, what this means is…

• If you have a custom build configuration, say a “Staging” or “Beta” or whatever, which is essentially a variant of “Release”….

• And if you have SwiftUI Previews in your app…• And if those previews are not wrapped in #if DEBUG directives…

• And if you have source code to support SwiftUI Previews stashed under the “Preview Content” directory…

Then your project will likely fail to build, as the previews will not be compiled out, but they will depend upon development asset code in “Preview Content” that is compiled out.Do you know if this is resolved in Xcode 14?

Right now the recommendation is to limit the Preview Content folder (which is really just a convenience for the DEVELOPMENT_ASSET_PATHS build setting) to assets like asset catalogs, preview data, etc.

For code, we recommend you continue to keep it in your normal source paths, but to wrap with #if . Note: the compiler will normally remove any preview providers from the final binary without needing the #if, but the #if is a guarantee it won’t be included.

If you don’t put any code in Preview Content, then the compiler will usually be able to correctly remove any branches of code used only for previews.

The compiler optimizes by removing non-public symbols that aren’t referenced from any top level code. This will remove most preview code that is not referenced by other public or used types.


Just to clarify my understanding, you are saying that it’s not supported use case to have code inside the Preview Contents folder that will be stripped out in Release builds?

It’s not unsupported ( :slightly_smiling_face: ) to put code in Preview Content, but we’ve found it to work best when Preview Content is limited to assets.

Are there any new SwiftUI Preview tools for previewing views on devices of varying os versions? For example viewing how a view would look on an iOS 16 device vs iOS 15 that uses the compiler checks.

There’s not currently a variant mode in the canvas for different iOS versions. However, there is a neat solution! If you have a physical iPhone that is running iOS 15, you can use on-device previews to see your simulator preview in the canvas (running iOS 16) and the preview running on device (running iOS 15). And any changes you make will automatically be updated in both places at the same time!

What's the best practice for working with Core Data and SwiftUI previews, such that we don't end up interacting with the actual store data?

Core Data supports pointing to in-memory storage which won't need the file system and would work great in any situation where you don't want to persist the changes permanently, even in Previews.https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/CoreData/PersistentStoreFeatures.html

As preview utilizes some generated code (for dynamically updating values etc), I have faced naming clashes a few times in a rather crowded file. And it wasn't obvious at first, I had to dig through logs to figure out some helper types I had were clashing. What would be suggestions to avoid such cases? Is there a guideline that we can refer to?

That's interesting. In order to be able to help we'd have to take a look at a concrete example. If you're able to repro the issue in a sample project, could you file a feedback request for us?

Sometimes the Xcode previews stop working for no apparent reason. The last example of this was it said "connection interrupted" or something like that. So, I question is what are some tips for fixing broken previews? BTW: The new previews are great! Love not having to create multiple previews for landscape and portrait.

We know there are cases where previews don’t work and we’re actively working on addressing them. The best way to help us is to file a Feedback Request and attach the previews diagnostics. Look for an upcoming message about great tips for filing previews bugs to make it easy for us to investigate! Thanks!

Views within an extension aren't always exposed to Previews. This will create a compile issue. Is this a known issue?

enum MyNameSpace { }
extension MyNameSpace {
    struct MyContainerView: View {
        var body: some View { MyChildView() }
    }
    struct MyChildView: View {
        var body: some View {Text("MyView") }
    }
}
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        MyNameSpace.MyContainerView()
    }
}

Ha, yes, definitely not expected :slightly_smiling_face: This is a known issue that we are actively looking at. In the meantime, a workaround is to add a typealias inside of the struct that references the other view. For example in your example I added typealias MyChildView = MyNameSpace.MyChildView inside of MyContainerView and the preview renders.

Question re the layout inspector inspecting swiftui - curious if there are public/sanctioned ways to introspect a swiftui view for details, similar to what is presented in the details panel (on the right when selecting a view).

The current recommendation is to attach to the process and use the view debugger. The runtime view debugger does not provide the same level of detail that you get when using the inspector in Previews – are there specific details that you are looking for in the view debugger?

In particular, what level of detail are you looking for with the font? i.e. Is it a custom font that you’re trying to validate or are you trying to make sure something is actually using a system font like .heading I don’t believe that level of introspection is available but we’re interested in hearing more about what you’re looking for.

Is there a way currently to automatically add borders to all the views in the screen with the press of a button/setting?

If you'd like to see the borders of each view in the preview you can use the non-interactive mode then in the menu bar go to Editor > Canvas > Show View Bounds. Additionally, you can toggle "Show Clipped Views" in the same menu to show or hide views that extend beyond the edges of the preview.

Is there a way to have the preview window size to be automatically  the same as the device used for the preview ? It usually opens wider than necessary on my small screen ;-)

There is not currently a way to have the preview canvas match the size of the device being previewed, though it is a known request. Feel free to file a Feedback request to help us track interest in that feature, thanks!

How do I see multiple previews at the same time with Xcode 14?

Each view in the PreviewProvider now shows in its own tab, and there are two ways to see multiple configurations in one tab.First, you can see multiple previews in the same tab for variations in device settings by using the new variants mode, accessible from the bottom bar of the canvas.Second, for multiple previews of the same view but with different inputs, you can make a single preview of a List or VStack that contains those different configurations. This is particularly helpful with rows of a List as the List will also show those views with the correct list styling and metrics.We’d love feedback if you have a unique case that you don’t think is covered by the current solutions!

Is it possible to print to the console while in SwiftUI previews?

This is a known issue we're actively investigating.

(Also not necessarily the best solution, but sometimes I end up just adding a debug label attached to state and use that as a print…)

FWIW, os_log and Logger do work fine in previews and then you can look for those with the Console app like any other syslog output.

It seems that the selectable mode no longer works the way I would expect. Is there an explanation somewhere of what I can do in that mode?

Hmm, that does look like a bug. It should be selecting the text / button.

Performance

I'm noticing a huge hit to scrolling performance when I add a contextMenu to cells in my lazyvstack. When I profiled the app, it showed that buttons in the contextMenu was what was taking so long to render. Does a context menu have to render on creation of a view? Is there any way to create a lazy context menu?

We believe that this issue was fixed in a recent software update. If you are still seeing this, could you please file a feedback?

With the new any keyword, will we still need AnyView to type erase views, or can we declare a collection with any View now? will this also have the same performance implications of using type erased views?

Ideally you should not use  AnyView and over the year ViewBuilder has improved enough that you should be able to eliminate most, if not all, its usage. That said, yes you will still need to use AnyView because you need to actually instantiate that type, and not just use View as a type. any View is just defining an (existential container) box.


is it possible to use view builders as function params or property types without Generics?we are using AnyView to present content. there are different types of content each represented by an enum with associated value. This forced us to use AnyView to have concrete types. What would be your suggestion to move away from AnyView in this use case?

If you have finite number of views you are displaying described by an enum could you switch over that enum in body of a view? ViewBuilder does support switch statements It really depends on your use case. But most of the time, if you're in the situation where you think you need [AnyView] or [any View], what you should likely do is invert the view dependency flow and have [AnyDataModel or [any DataModel]  instead, then create your views based on the type of data provided at runtime.


I have similar use case. Sometimes I would like to not couple the view which other views it present, but instead use other Flow/Factory logic that shows whats needed depending on the business logic. It forces me to use AnyView . E.g.

struct MainView: View {
    @ObservedObject var viewModel: MainViewModel
    var channelsViewFactory: (Int?) -> AnyView

    var body: some View {
        Text("ABC")
        channelsViewFactory(viewModel.selectedId)
    }
}
...
extension AppDependencies: MainViewFactory {
    func makeMainView() -> MainView {
        return MainView(
            channelsViewFactory: { id in
              if loggedIn {
                self.makeChannelsView(for: id)
              } else {
                self.makeSignInView()
              }
         }
     }
}

You could introduce generics into  MainView (e.g., MainView<ChannelsView: View>: View) and then create a container view above MainView to encapsulate the generic constraint(s).

I’m seeing much choppier performance in SwiftUI with iOS 16 Beta 1 vs iOS 15—should I troubleshoot my specific view hierarchy, or do you anticipate the framework becoming more optimized in later betas?

We plan to improve things over the betas, but letting us know about problems you’re seeing (performance or behaviors) helps us know about and resolve them sooner, so please file feedbacks for any regressions you are seeing! Specific, reproducible performance regressions make especially good feedback reports :)

Sharing

Can we create our own custom payload for internal app drag and drop?

Yes! you can!

If you create a custom payload type that multiple apps support, you can send it across them as well! As long as they have the same codable representation, you should be all set!

PhotosPicker and ShareLink are available on watchOS. It's the first time we've had this functionality available on the platform!

You can't, but please file a feedback with your use case!

Does Transferable also support asynchronous behaviour like NSFilePromiseProvider, e.g. if you do not have an file URL yet (e.g. cause a file first needs to be downloaded from a web server, but only when the drag operation ends)

Definitely, the FileRepresentation transfer representation does what you’re describing.

There is a difference: ShareLink is used for sharing here and now, not for persistent storage. Core Data is a database–and its intended use is for storing items on the disk.

It depends on which transport APIs we are using. For example, Drag and Drop allows sharing items within a single process or between different processes. Copy/paste works similarly.If we are using FileRepresentation, we can specify the allowAccessingOriginalFile parameter for SentTransferredFiles and tell the system if should make the copy, or not.Transferable doesn’t provide any synchronization, just passes around data.


So in a use case where we are sharing persistent data between users of the same app (for example, a recipe created by the user in a recipe app), is using ShareLink discouraged in favour of sharing using Core Data + CloudKit?

I wouldn’t say discouraged, it just has different purpose. ShareLink allows to present the share sheet or another system sharing interface, so users could send over the recipes to their friends in Messages, or pasted into Notes, etc. Does this make sense?

Sheets

Is it possible to have a presented view that switches between the popover/sheet presentation styles depending on the size class (i.e., sheet in compact, popover in regular)?

Yes! You can do this by creating a custom view modifier that uses looks at the UserInterfaceSizeClass. Custom modifiers are great for conditional combinations of other modifiers, views, etc. and this is a perfect use case We have an example of this use case in the BookClub sample app, in ProgressEditor.swift.

State

I was wondering if there are any updates, or opinionated best practices when it comes to large scaled applications using SwiftUI in terms of state management and dependency management/injection.

SwiftUI is not opinionated on a specific architecture for state management. We offer the building blocks to build whatever best fit your use case. It might be good to sign up for a lab so that we can discuss the specific of your use case and give you targeted advices

FWIK it's a good practice to have state changes the deeper in the view hierarchy as you can get, in order to avoid redundant redraws. Are there any best practices to achieve that besides breaking views down to tiny elements and composing them together?

The right way to structure your state varies by app.

For State, I would generally recommend defining it at the level where you are going to use it.For your ViewModel it could be useful to break your model into multiple ObservableObject that are specific to a specific functionality (like a cell, or a single screen).But I would avoid prematurely breaking you model into very small pieces.SwiftUI does diff your view and will only re-render if it detects that something has changed.

  • Everything suggested in the Demystify SwiftUI Session from a year or two back is definitely useful
  • Keeping Identifiers separate from values is recommended generally (but not a hard and fast rule), especially in Navigation APIs.

Why would anyone use observable object instead of state object?

You might want to use @ObservedObject if the lifecycle of your model is not owned by your view.An example is if you are using UIHostingConfiguration and you have your model owned by UIKit in a UIViewController and just passed to a SwiftUI cell. Also, in general you want to use @StateObject in a parent view, and if you pass the same ObservableObject instance to child views you can use just @ObservedObject.

I’m a teacher but also write iOS/iPadOS apps. I watched Curt’s Cooking/Recipe section and am trying to understand state restoration. I thought Curt said adding SceneStorage and the Task to check if navigationDetail was nil would do it but it doesn’t seem to work. Do you still need to use the onContinueUserActivity and then have each view in the stack hierarchy have a .userActivity to create/describe a NSUserActivity for that view?

What I shared in the talk and in the Copy Code associated with it should work. Or check out the sample project here: https://developer.apple.com/documentation/swiftui/bringing_robust_navigation_structure_to_your_swiftui_appYou shouldn’t need to use user activity directly at all for this.


Hmm. I tried running it in simulator. I select Apple Pie, select Fruit Pie Filling, press Shift-Cmd-H. Press the stop button in Xcode, and then relaunch the app and it starts at the initial Categories screen. Am I not testing it correctly?Ah! Yeah, Xcode kills background storage unless you hold it “just right”. The pattern when working with Xcode, is to (1) background the app in the simulator or on device, (2) wait 10 seconds for the system to do its backgrounding work, (3) kill the app using the Stop button in Xcode. Then when you run the app again, it should use the saved value.

Just starting out with SwiftUI. One of the things that is hard to get my head around is the following. In UIKit, I have a label that pulses (grows and shrinks) based on certain events, so I'd typically have an outlet to the label and a method 'pulse'.  In SwiftUI, I accomplished the same by having a binding labelState which I change in the containing View. So while UIKit would have an outlet for multiple labels, in SwiftUI I'd have a binding state for each label. Is that typically the correct pattern?

That seems like a totally reasonable approach! Generally, when you have some value that you want to change in SwiftUI, you want to make sure that there’s a clear source of truth for that value. That source of truth can either be @State, or a property within an ObservableObject.When you have a fixed number of controls, having a separate piece of state backing each of those controls is completely reasonable.That said, the sources of truth you provide for your state should mirror your UI, so if you dynamically generate your labels from an array of data, you might then want to have an array of data as the source of truth state for your ui components. If you see that your sources of truth for your data mirror the structure of your UI, you’re probably on the right track :)

My question is about some code in the SwiftUI Cookbook for Navigation session. Around 23 minutes in, Curt uses the task modifier to run an async for loop over the model's objectWillChange publisher. In the loop, he then accesses an @Published property of the model. But a @Published property fires the objectWillChange property before it updates its wrappedValue. Doesn't that mean that when the code accesses navModel.jsonData, it will get the out-of-date model values? Or is there some async magic that guarantees the loop body will not run until later after the objectWillChange publisher has finished publishing and the @Published property has updated its wrappedValue?

Task schedules its body on the main actor, which is also where the view update happens. So objectWillChange enqueues the body of the for loop, but it’s enqueued behind the update of the data model.

Is there any way to get my offscreen nested StateObjects to not be deallocated when scrolled offscreen within a LazyStack? The only solution I've found is to "hoist" them to the top level of the LazyStack, e.g. within the Content of a ForEach, but that feels kinda clunky to have to do in every scenario—wondering if there's another option.

I think "hoisting" your state into an ancestor is your best bet here

As an aside, StateObject is more commonly used with model objects and you generally don't want to tie your model object's lifecycle to the view

In the case of a model object it might make sense for an ancestor model object to be maintaining references to these children model objects


Yes in this scenario it's effectively a State , just incidentally modeled as a StateObject for other reasons — however we were finding that a State was getting reset as well back to the initial value as well in that same scenario. I assume that's expected as well?ya State would be expected to behave the same as StateObject here since the motivation is to limit memory growth by avoiding preserving state for an unbounded number of (offscreen) views

There has been a lot of controversy regarding the ObservedObject(wrappedValue: ) initializer. Is it safe (and encouraged) to use it, or do we have an alternative for it this year?

This initializer is fine to use! In fact, the ObservedObject(wrappedValue:) initializer is invoked every time you construct an ObservedObject , even if you don’t explicitly write it yourself. When you write: @ObservedObject var myObservedObject = myModel, The Swift compiler converts that standard property wrapper syntax to a call that looks something like: var _myObservedObject = ObservedObject(wrappedValue: myModel).

The controversy I think you’re referring to is using that initializer explicitly in the initializer for one of your views. Typically, we see people doing this to allow observed objects to be instantiated with specific information. That is also something which we think is fine to do. We recognize that the ergonomics of that case is not ideal (since you have to access the de-sugared property wrapped (in the example I gave, _myObservedObject), but it’s not at all harmful.


What about the State initializer?

The state initializer worries me a bit more. Not because it’s dangerous — it’s totally fine to use it yourself (as I mentioned, the normal syntax is just sugar for the fully spelled out case) — but because I can’t think of as many cases where you need that syntax for @State that aren’t dangerous. Remember that @State is initialized once per lifetime of the whole view, not once per time a view’s initializer is called The views representation will be recreated on demand. That means that if you’re re-initializing the state every time the views init is called, you’re going to be clobbering your own state. So that’s fine to do, but make sure that you’re only using it to set the initial value of a state, and that you’re not resetting your state depending on some initializer value.


I believe same applies for @Binding and co. too?

Yup!

But for @Binding is it still harmful? Because source of truth is already on a parent view or somewhere up there?

Yeah, binding is also one of the cases that would sound alarm bells for me As a final note: regarding the “don’t call this initializer directly,” that’s mostly because as I mentioned, the cases where you “need” the underlying initializer (for @State and @Binding especially) are few and far between. Most of the time, you’d want to be using the standard property wrapper syntax, so we want to make sure people reading the docs look there first.

My intuition is that for a primary-detail setup, you would want the detail using @ObservedObject (or even @Binding) instead of @StateObject.

@State and @StateObject are defining a source of truth and lifetime for the state/model.You want the lifetime of the state/model to live on beyond changing the selection in the primary.@ObservedObject will listen to changed in the model object and update the view without establishing a new source of truth.

Would you recommend to use @State/@ObservedObject for any cases where where we don't expect the object to mutate?

If the values you’re represented are never going to change, there’s no need to use @State or @ObservedObject. I highly recommend just making and using a standard struct.


What about reference types in views? Would let suffice?

Let would not suffice for reference types! A let binding for a reference type just says: “This will always point to the same instance of the object”. It doesn’t guarantee that that instance is immutable. If you can guarantee that your reference type is completely immutable, then you should be fine, but that can be a hard thing to ensure, so be cautious (and I would highly recommend using structs where you can)

Should I ever be concerned that as the view gets thrown away and recreated my UISelectionFeedbackGenerator  instance (for example) will be continuously re-created as well?

I wouldn’t ever be concerned that your view gets thrown away and recreated. That’s by design. SwiftUI views aren’t linked to their actual UI representation, but rather are lightweight descriptions of views that can be recomputed quickly and easily. You should expect your views to be thrown away and recreated very frequently.

Does branching in a views body (via if-else or switch) cause the creation of each branch's views?

It only creates the views for the branch of the if/switch that’s actually taken.

I noticed that when a subview uses a binding to published variable from an ObservableObject, the subview's body will re-execute any time any of the other published variables in the ObservableObject are modified. Even if this modified variable isn't used by the subview at all. Is this a bug or a performance concern?

The subview updates based on the objectWillChange publisher, which is a composite of all the published properties. This is by design, but can require fine tuning of models.

Different apps can handle this different ways, so this might be an excellent question for a lab.

I’m still having an issue with generic view models in SwiftUI. I’m having trouble to understand what should I choose between @ObservableObject or @StateObject when injecting a generic view model into a SwiftUI view.I’m commonly doing this, in this case, the viewModel property should be @StateObject or @ObservableObject ?

protocol ViewModelProtocol { }
struct MyView<ViewModel: ViewModelProtocol>: View {
    @ObservedObject var viewModel: ViewModel
}
let myViewModel = MyViewModel()
let myView = MyView(viewModel: myViewModel)

This particular example should be @ObservedObject https://developer.apple.com/wwdc22/10072. There are a few nuances that are explained in this year's Use SwiftUI with UIKit and last year's Data Essentials sessions. With @StateObject , MyView would own the model, and is at liberty to make a copy of it when initialized. That means that the myViewModel variable would become "disconnected" from the @StateObjecthttps://developer.apple.com/videos/play/wwdc2020/10040.

If your view wants to own an ObservableObject view model, and the lifetime of that object should match the lifetime of the identity of the view, you should use StateObject.You can initialize a StateObject with an external value using this code in your initializer:

_viewModel = StateObject(wrappedValue: existingModel)

Note that the value passed to that initializer is accessed once and can't change over time.

Styling

Is it possible to provide custom form styles?

There is a new FormStyle protocol you can conform to to create your own styles. Please file feedbacks if you find anything you’d like to do with it, but can’t.

Would love to see a Label() with an Icon, Title and a Subtitle.

Try out

Label {
    Text("Title")
    Text("Subtitle")
} icon: {
    Image(systemName: "star")
}

There may be a few contexts that this doesn’t work quite right in, so if you find any, feedbacks are always appreciated

Does the grouped formStyle work in Mac Catalyst SwiftUI?

That style is available in Catalyst, like iOS — but the design hasn’t changed in Catalyst and looks the same as it does previously / on iOS.

Is there any difference in terms of performance about using Table instead of List on iOS?

There shouldn’t be. Tables default to plain lists on iPhone.

Can I ask if we can have separate customisable toolbars for different views, or is it only one per WindowGroup like on macOS?

You can have different toolbars for different views on iOS and iPadOS.

With graphics and custom layouts being added, when should we use native elements vs custom styling? How far should custom designs go?

It entirely depends on your use case! We ultimately trust your sense of design on this one since only you know what’s right for your app. To give some general guidance though: Take native elements as far as you can, and if you find you need further customization beyond that to finely polish the experience, then don’t be afraid to use it!

One quick disclaimer: It can be easy to drop to custom layouts prematurely. Stacks and Grids are incredibly powerful already, so be sure you can’t get what you need with them before you use the new layout protocol.

We don’t currently support extending our property wrapper APIs like @State and @Environment outside of how they are used in SwiftUI.


To the original poster: I’m not an Apple engineer, but I’ve build something similar in the past by making the struct conform to DynamicProperty . SwiftUI will pass through all DynamicProperty members recursively and inject dependencies (i.e. @Environment  and @State ) before calling body .

Note that custom types conforming to DynamicProperty will only work if values of those types are stored within views or other SwiftUI types that generally support dynamic properties like @State and @Environment.

**I've done something similar for other closed source things. The technique I am using revolves around creating a protocol/configuration (similar to what you'd find in ButtonStyle definition) and then injecting it into the EnvironmentValues via a custom value type conforming to EnvironmentKey. Then the component (e.g. Button for the purposes of this description) would internally grab the environment set (via @Environment(\\.buttonStyle) private var buttonStyle)

You'd then just pass the configuration you build into the make* functions you create as needed.

Hope that makes sense. I've really enjoyed this technique in the components I've built.**

And to dive a little more down for the State/Environment part of it, I would just pass those through the configuration struct if a style would need it (do this for passing things like isEnabled down) similar to how ButtonStyleConfiguration has isPressed as a value

Above technique is an effective way to implement a similar pattern

Love the new toolbarBackground(_:in:) and toolbarColorScheme(_:in:) modifiers in iOS 16! Is there any way to have them take effect always? They seem to only make a difference when content scrolls up beneath the navigation toolbar and using something like .toolbar(.visible, in: .navigationBar) doesn't seem to make a difference.(My basic goal here is to control the navigation bar background color and the status bar style, so if there's a better way to do that please let me know!).

.toolbarBackground(.visible) should work for this. If you are not seeing that, please file a feedback

We’d generally recommend resolving it right away and storing the view

Storing the view will have better performance than storing a closure (potentially avoiding allocations).Of course, if you need to dynamically resolve a view from a closure (such as if it takes parameters), then storing the closure is also fine!

You can attach @ViewBuilder to properties! You can actually support it on both view and closure properties, depending on whichever you need:

struct MyView<Content: View>: View {

  @ViewBuilder var content: Content

  // or

  @ViewBuilder var content: (Int) -> Content

}

Creating views in body is fine, we’re specifically talking about stored properties, and storing views versus closures for creating views.

ViewModifier question:What’s the difference between a custom ViewModifier (without DynamicProperty) that uses some built-in modifiers in body(content:), and a custom View extension func that just use those built-in modifiers?Similarly, what’s the difference between a custom ViewModifier with some DynamicProperty and a custom View with some DynamicProperty (also has a @ViewBuilder content property to receive content to modify) ? I think two have the same render result and behavior.

Because of the way a ViewModifier is expressed, the engine knows it's not changing the content passed in and can apply performance optimizations (compared to just an extension on View).

Is it possible to customise the font on pickers and menu this release? I’ve had to create my own menu (quite a workload) to workaround this styling limitation.

The font should be customizable on macOS but is not currently on iOS. We’d love to hear more about your use case and please do file a feedback with more details so that we can take it into consideration for the future.

Check out the .toolbarBackground modifier, new in iOS 16 and aligned releases.

Does .toolbarBackground apply to only that view or any view pushed into navigation stack as well?

I believe it applies to the current view, so you can change the behavior at different levels of the hierarchy. There’s also toolbarColorScheme if you need to control the text appearance. Finally, you can use a toolbar item in the principal placement to replace the default navigation bar title with an arbitrary SwiftUI view.

How do I actually apply Variable Color to an SF Symbol along with the percentage I want highlighted vs dimmed? Is there a SwiftUI modifier for this?

You can make a variable color symbol with:

Image(systemName: "wifi", variableValue: signalStrength)

It’s part of initializing the image, not a separate modifier you apply.

While I was working with Canvas and rendering images, shapes, and text, I was trying to sort out if there was a way to get the offset for the baseline value from a ResolvedText. I wanted to align the text baseline to a visual element that I was drawing in canvas, and the only path I found to getting sizes of discrete elements was to resolve them and measure them - something akin to:

let captionedTextSampleSize: CGSize = context.resolve(Text(label).font(.caption)).measure(in: size)

This hands back CGSize, which mostly worked for what I needed, but I'd really like to align to that baseline - and for that I need to determine an offset. Is there any public API to help me do that, or a technique I could use to get said offset that uses other frameworks or libraries?

The GraphicsContext.ResolvedText type also has firstBaseline (and lastBaseline) methods. So you can do something like:

let baseline = context.resolve(myText).firstBaseline(in: size)

Using .buttonStyle(MyCustonStyle()) instead of MyCustomButton(...) is more SwiftUI-y. But why should I prefer one over the other (considering MyCustomButton uses MyCustonStyle under the hood)?

We strongly recommend separating semantic controls and styles as it provides a lot more flexibility.

For example, using the button style modifier will apply to the whole hierarchy, so if you decide you want specific parts of your app to use a different button style, you can just apply it to that specific hierarchy without changing the control itself.

With this approach you also get multi-platform behaviors for free.

What is the advantage of using custom Symbols rather than SVG with template rendering mode?The ability to programmatically change the colors of several layers? Any other reason?

In addition to the great color support, using a custom symbol also helps it better fit with text by growing with fonts, respecting bold text, and matching baselines.

I have some custom multicolor symbols that I want to inline with Text, e.g.Text(“Look at my pretty symbol \\(Image(“mySymbol).symbolRenderingMode(.multicolor))”But they don’t render as multi color, is this an expected limitation? Can you think of any work arounds that still provide all of the benefits of inlining? It works great for system provided multicolor symbols…

it could be a bug, or it could be some problem with your symbol template. For instance the template must be at least version 2 to support multicolor. Does the SF Symbols app work with it and is it able to display the symbol in multicolor? if the symbol is working correctly in other contexts, that sounds like it could just be a bug on our side let me look into it further

We can now use .foregroundColor(.white.shadow(…)) on SFSymbols. Will this work with custom PNGs/SVGs as well?

foregroundStyles apply only to shapes, image masks, and text. If the Image is configured as a template, then foreground styles should be applied. If the image is non-template, they won't.

Is it possible to have a customizable toolbar with SwiftUI on iPad?

Yes it is possible :tada: Checkout the "What's new in SwiftUI" talk on the Advanced Controls section to have a peak. And make sure to tune in for the "SwiftUI on iPad: Add toolbars, and documents, and more" talk tomorrow to dive deeper. :smiley: Note that the same APIs will work on macOS too.

What is the best way to make a TextField wrap? I noticed some new API regarding lineLimits and axes, and wondering if those provide some functionality in this area.

TextFields can be initialized with a new axis parameter. If you provide a .vertical axis, then platforms like iOS and macOS will wrap the text of the text field in a scrollable container instead of letting the text expand horizontally. See one of its inits here: https://developer.apple.com/documentation/swiftui/textfield/init(_:text:axis:)-7n1bm

These text fields will also respect the line limit modifier. So specifying a lineLimit(3) will let the text field grow vertically up to 3 lines and then it will stop growing and scroll instead.

My app’s design uses kerning on most of its buttons, but I can’t put that inside of my ButtonStyle because kerning is only available on Text, not ButtonStyleConfiguration.Label. I have a feedback open suggesting passing kerning through the environment (FB10020695).In the meantime, do you have any suggestions on how to do this without using .kerning() separately on every button label nor making a custom button View?

The only other thing I can think of is to create a Button wrapper view that requires a Text be passed in as a parameter. Then attach kerning to the Text yourself and pass it to the underlying Button

Is there any possibility of creating my own form style? For example if I wanted to backport the new .columns

style back to macOS Monterey.

FormStyle is only public this year, so not able to be backported. You would have to create your own Form replacement as a whole to do something like that

Is there a way to recreate the appearance of the widgets on the Lock Screen using UIVisualEffectView in an app using either SwiftUI or UIKit? I'm specifically interested in recreating the appearance of the circular widget.

A variety of the gauge styles used in circular complications on the Lock Screen are available in app as well! You can access them using any of the SwiftUI gauge styles with an “accessory” prefix. Please be aware though that those styles are really only intended for Lock Screen / widgets and contexts in your app that should have a similar look and feel, so please be thoughtful about where you use them.


I realise that my question was poorly phrased. I’m looking for a way to recreate the vibrancy that the Lock Screen widgets use. Would that be done using a UIVisualEffectView?

with UIVisualEffectView you can try the UIVibrancyEffects created with a UIBlurEffectStyleSystem*Material, but I’m not sure that will necessarily match what the lock screen is doing


Something we couldn't talk about in the talk (for brevity) was how complex these new shadows are. Not only do they composite on top of each other as you'd expect, but if you apply a shadow on a translucent shape, the shadow will not show through the translucency
Avoid using tap gestures for button-like things. Custom button styles will provide a better user experience, both in interaction handling and accessibility.

Same goes for toggles! If you’re using a tap gesture to mutate some boolean state back and forth, consider a toggle style!

Accessibility Quick Actions on watchOS is super cool. Instead of having AssistiveTouch on all the time, you can have it on just to do quick things in your app with a gesture.For example, you can enable QuickActions to answer a phone call with just one hand -- clench your fist, and it performs the action.Using .accessibilityQuickAction is an easy way to add that functionality to your app.
We’ve gotten a few questions about modifying the background of a SwiftUI List.

In general, you should not rely on implementation details of a framework (including SwiftUI) to achieve specific behaviors in your apps. The release notes did call out the change in implementation of List since we were aware of developers using UIKit methods to style their Lists in the past. This is a known limitation, but we realize this is a popular request, so rest assured we have noted the feedback here and in the SwiftUI lounge!

Support

What is the best venue to ask SwiftUI questions during the year? Swift Forums is amazingly useful for Swift language and library questions, with many of the implementers frequenting it, but it is focussed solely on the Swift language itself. Is there any comparable place where y'all converse during the year?

The developer forums are a great place to ask questions! We monitor them throughout the year and reply when we can, and so do other members of the community!

There's also full-year lab-style code-level assistance from Developer Technical Support to facilitate your SwiftUI questions.

Testing

Our recommendation is still to thoroughly test your model layer. In my experience, the best SwiftUI apps move their logic into model code, using SwiftUI as a declarative mapping from that model state to views. Then your tests of the model layer are effectively tests of the resulting UI as well

Question regarding the SwiftUI Instrument:Is there a value of avg. duration that no View's body should go above when rendering for avoiding performance issues/hitches?

View’s body properties should be cheap and avoid any potentially expensive work. If there are things you need in your views body, its best to pre-compute that into a piece of state that you can pass your views.

Concretely, each frame has a hard deadline of generally 1/60s or 1/120s (depending on the refresh rate of the display) to render its content. Thats 8ms in the fastest case.

Thats for the entire screen to render its content though, not just your single view . So if any one view is taking more than a few ms to finish calling body, you’ll run into issues.

If you’re using Swift concurrency to move work off the main thread, consider watching this session: https://developer.apple.com/videos/play/wwdc2022/110350/

This is all mostly related to scrolling performance. Other kinds of things like app launch or navigation pushes will typically take longer than multiple frames to render, but those situations have different expectations around frame deadlines.

When using Self._printChanges() in the body of Views, what should we pay close attention to? Is @Self printed often harmful? What are the numbers @44 we see when using FetchRequest in the View.

@Self self is not inherently harmful. The purpose of Self._printChanges() is not to indicate that something is wrong but rather as a tool to match your expectation with what is happening at runtime. What you want to be on the look out for is that you don’t do unnecessary invalidation which might cause performance issue. If you see @ followed by any number it means that we couldn’t find the field (property) name, so printed the byte offset of the swift view struct field instead.

UIKit and AppKit with SwiftUI

As we are incrementally adopting SwiftUI in a UIKit app, are there guidelines for replacing the patterns that we are used to in a UIKit app, like delegate pattern, notifications, target-actions etc? Some of these are obvious but I kind of feel I'm doing something wrong whenever I pass a closure into a view to get a feedback to replicate delegate pattern for example.

Delegates do a lot of different things in UIKit, and so the way that they should be translated into SwiftUI can vary heavily depending on what they’re being used for in UIKit. In some situations they’ll become closures that you pass around, in others, a Binding or State, sometimes a onChange(of:), etc. UIKit and SwiftUI have two very different programming models, so often times, concepts don’t map over in a one-to-one way. I’d highly recommend you book a lab appointment so we can chat more about what specific case you’re trying to translate, and where your pain-points are there

When using UIHostingController, is it better to add it to the view controller hierarchy (with addChildViewController), or could we use its rootView and simply add it as a subView ?

You want to always add a UIHostingController as a childViewController.

// Add the hosting controller as a child view controller
self.addChild(hostingController)
self.view.addSubview(hostingController.view)
hostingController.didMove(toParent: self)

without the view controller relationship things that depend on the UIViewController hierarchy won’t work. Such as UIViewControllerRepresentable

There are a few other types as well that depend on this relationship in their underlying representations so its best practice to add the parent/child relationship.


I am building a design system implementation where I’m providing reusable components that other teams can simply build their features. I usually start with SwiftUI but this view controller relationship makes things very hard at times, especially if the view in question is complex. I believe there is NSHostingView on the Mac, I wish we had the same on iOS. For the time being, given the requirement, is there any recommendation to fulfill this requirement? For example, can we even use window’s rootViewController as a parent or is there a better way?

yes the AppKit underlying infrastructure makes NSHostingView work while UIKit is not able to do so due to the hierarchy requirements.It depends on exactly what you are trying to build, but potentially you could make a reusable view controller that your teams can use instead depending on where the complexity is at. Parenting at the rootViewController  would have issues with any navigation calls you might try to make in SwiftUI.

One of the strengths of SwiftUI as a framework is that it works well with a variety of architectures.

We might be opinionated about API design :slightly_smiling_face:, but we want you to have the flexibility to design the data model that works best for your app.

The particular data model of any individual app depends on the domain of that app. For example, a car rental app might have a very different architecture from a news reader app.

I would like to migrate my (very complex) iMessage app extension to SwiftUI. How do I deal with the MSMessagesAppViewController? Do I need to use some mix of UIHostingController and UIViewRepresentable?

You should use the UIHostingController as a child of the MSMessagesAppViewController

Does SwiftUI support the new toolbar modes for iPad or do you need to use UIKit?

Check out the toolbar role API: https://developer.apple.com/documentation/swiftui/view/toolbarrole(_:)

And the secondary action toolbar item placement: https://developer.apple.com/documentation/swiftui/toolbaritemplacement/secondaryaction

For more information, I go into these APIs in the 2 part of SwiftUI on iPad series:https://developer.apple.com/videos/play/wwdc2022/10058https://developer.apple.com/videos/play/wwdc2022/10058

Should we approach SwiftUI views as data models for real views? Where should we place data formatting logic? If SwiftUI view is a data model we can data formatting logic there? How can we test our data formatting logic in this case?

The most convenient way to unit test your data formatting logic (like a Foundation FormatStyle) will be to factor the formatter out and assert against the String it produces I generally wouldn't consider a SwiftUI view to be a data model

Factoring out the formatter might take the form of lifting into a model or view model

Or it might just take the form of specifying it in a computed property on the View and running the assertion against that


So, we can use property testing to assert data formatting directly inside SwiftUI Views. Is it good practice? How do you deal with this problem at Apple in big projects?

Unit testing is a bit of an art and so I wouldn't say it's a necessarily a good or bad practice to assert directly against the SwiftUI view. I think the concerns are more pragmatic: how easy is it to assert against the SwiftUI view vs against a model. Does one way or the other require extra boilerplate? Does one way or the other lead to fewer false negatives?

Does this new APIs are backward compatible with UIKit project or just only iOS 16?

In general all APIs that are introduced in new versions of our operating systems always require those versions to be used. However you can conditionalize your code to only use those new features when running on that OS and have your app back deploy to old versions without those features.

That, unfortunately, is a technical limitation. These features are implemented in frameworks that are shipping with the OS and that are heavily integrated with the OS, so they require the new OS to work. In a lot of cases you can just add the new features when running on the new OS and just do nothing on older versions, in which case it is enough to just check the current version you are running at run time before calling out to the new APIs.

On iOS 15 and earlier, you request an update to the size of self-sizing cells in UICollectionView and UITableView by:

  • If using diffable data source, re-applying the diffable data source’s current snapshot with animatingDifferences: true
  • If not using diffable data source, performing empty batch updates on the collection or table view directly (that’s the same as the begin/end updates you mentioned)

Are there any major limitations to be aware of with the new UIHostingConfiguration for collection view cells using SwiftUI, that may not be addressed in the session video?

We do try to address the majority of the limitations in the video! Theres a spot at the end where we talk about how UIViewControllerRepresentable will not work there. The video also covers considerations around data flow. https://developer.apple.com/wwdc22/10072

Would you use SwiftUI or UIKit to implement a list that can change layout between a table and grid layouts? I currently have a UICollectionView with different layouts but I can't animate between the layout change.

As always we recommend using the tool that is best for the job. UICollectionView does support animating layout changes via setLayout:animated: so there is no need to rewrite this in SwiftUI. If there are specific things you want to achieve that can only be achieved in SwiftUI, then of course converting it to that is a very valid option.

Is there a way to allow duplicate CommandMenu item .keyboardShortcuts? In AppKit macOS menus, this works, but not in SwiftUI.  The duplicate shortcuts are never active at the same time - they depend on the type of the selection focus.

Assigning the same shortcut to different menu items is not recommended, even for AppKit apps.The user should be able to predict the outcome of each shortcut. If the selection focus changes which menu item is invoked, that would be confusing.

I don't suppose that the two different actions are similar enough that you could combine them into the same menu item, with the same shortcut? The Copy menu item is a good example of something that applies in a variety of different circumstances, and is strongly responder chain / focus driven...

Using SwiftUI cells in UIKit is a fantastic feature in iOS 16, however that will not work if my app is still supporting iOS prior to iOS 13. Right ?

The use of new APIs requires iOS 16, so unfortunately you can not use these in iOS 15 or before. However you can use them in an app that is available on iOS 15 and before conditionally when the user is running iOS 16.

Is there a way of disabling scrolling on a List, or would the best option be to use UIHostingConfiguration inside of a UICollectionView that's wrapped in a UIViewRepresentable so that I can disable scrolling on the collection view itself?

Use the new scrollDisabled modifier. https://developer.apple.com/documentation/swiftui/menu/scrolldisabled(_:)

Is there an analog to AppKit's flangsChanged notification, to change the appearance of SwiftUI controls based on keyboard modifiers? I'm currently polling on a timer to do this, but that is unsatisfying.

You could try using something like this:

import AppKit
import SwiftUI

class KeyboardModifierMonitor: ObservableObject {
    @Published var eventModifiers = EventModifiers()
    var localEventMonitor: Any?
    var globalEventMonitor: Any?

    init() {
        localEventMonitor = NSEvent.addLocalMonitorForEvents(
            matching: [.flagsChanged],
            handler: { [weak self] event in
                self?.eventModifiers = EventModifiers(event.modifierFlags)
                return event
            }
        )
        globalEventMonitor = NSEvent.addGlobalMonitorForEvents(
            matching: [.flagsChanged],
            handler: { [weak self] event in
                self?.eventModifiers = EventModifiers(event.modifierFlags)
            }
        )
    }

    deinit {
        localEventMonitor.map { NSEvent.removeMonitor($0) }
        globalEventMonitor.map { NSEvent.removeMonitor($0) }
    }
}

extension EventModifiers {
    init(_ flags: NSEvent.ModifierFlags) {
        self.init()
        if flags.contains(.capsLock) { insert(.capsLock) }
        if flags.contains(.shift) { insert(.shift) }
        if flags.contains(.control) { insert(.control) }
        if flags.contains(.option) { insert(.option) }
        if flags.contains(.command) { insert(.command) }
        if flags.contains(.numericPad) { insert(.numericPad) }
        if flags.contains(.function) { insert(.function) }
    }
}

which you would then use in your controls like so:

public struct MyAmazingButton: View {
    @StateObject fileprivate var eventMonitor = KeyboardModifierMonitor()

    public var body: some View {
        let modifiers = eventMonitor.eventModifiers
        let isOptionHeld = modifiers.contains(.option)
        let isShiftHeld = modifiers.contains(.shift)
<...>

EventMonitors don't fire during tracking loops, and while a menu is open, AppKit is tracking that via an event tracking loop.

Could you please file a feedback for this?

The documentation for makeCoordinator states: "Creates the custom instance that you use to communicate changes from your view to other parts of your SwiftUI interface." could you explain what that means? It doesn't make sense to me because normally the coordinator is an NSObject that is the delegate to a UIView. I have seen some examples of Coordinator classes that take in an @Binding, that was passed in to the UIViewRepresentable and then into the Coordinator. Is that what this means?

The Coordinator you return can be any type, including an NSObject subclass. That coordinator will then be passed into makeUIView and you can assign it as the delegate of your view.

I explained this in my session "Use SwiftUI with AppKit", starting at around 12:38 into the video.

https://developer.apple.com/videos/play/wwdc2022/10075/

Passing a binding works great as well, but doesn't scale as well if you have multiple pieces of state to pass through. You're welcome to do it either way!

What approaches would you recommend to start integrating SwiftUI into existing codebases that support iOS 14/15?

I'd suggest trying to adopt it in a view controller first, and replace the existing view controller with a UIHostingController and try to recreate the existing layout.

A great place to start is a settings view, where you can use Form to put a list of fields, switches, sliders, and more.

Is there a way to specify the tabbing order of text fields, akin to textView.nextKeyView (FB10020959). My app has a combination of SwiftUI TextField Views and NS/UITextView wrapping in NS/UIViewRepresentable, and I've seen some odd cases where the default tabbing order is quite unintuitive.

By default the key view loop follows the same default order as AppKit — leading to trailing, then top to bottom — do please file a feedback if you find a situation where that’s not the case.There is support for customizing that order by describing the sections that separate your UI using focusSection() (https://developer.apple.com/documentation/swiftui/view/focussection()?changes=_4)

Is there SwiftUI equivalent of new UINavigationItem.backAction?

There is no equivalent in SwiftUI, but a feedback would be appreciated!

We have an app that has a 50+ components built using UIKit. We are trying to use SwiftUI by reusing our existing components but we are facing multiple challenges.

It seems that UIViewRepresentable doesn't work out of the box with views that are built using auto-layout. We have a generic container (IntrinsicContentHeight<View>) that tries to calculate the size of the UIKit view and return it to the intrinsicContentSize. Is there a better solution?

We noticed performance issues using UIViewRepresentable views in SwiftUI Lists. It seems that Lists always re-create the UIViewRepresentable views and never recycle cells. Are we doing anything wrong?

Our design system slightly modifies the line-height of our texts. We have a solution using NSAttributedString that works well for UIKit but haven't found a solution for SwiftUI. Text supports line spacing but it can only increase the default line spacing, it cannot decrease it (passing negative values does nothing). Is there anything we can do to customize the line height of a Text in SwiftUI?

I only have an answer for the first question. We have new API that allows you to more finely control how your UIViewRepresentable interacts with the SwiftUI layout system. Please see: https://developer.apple.com/documentation/swiftui/uiviewrepresentable/sizethatfits(_:uiview:context:)-9ojeu

ViewThatFits

I assume the contents of each Layout in ViewThatFits won’t share the same state and they won’t animate between states as they’re different views with different ids?

Ya the mental model for ViewThatFits is that all the children have different identity.

How does ViewThatFits decide if a view fits? I find it a bit strange that Text with a line limit of 1 still "fits" even if it's truncated for example.

ViewThatFits consults the view's ideal frame size for both dimensions.

The latter behaviour isn't intended. A feedback # and keeping an eye on later seeds is a good strategy here.


Adding a fixedSize(horizontal: true, vertical: false) seems to fix the issue but also seems unnecessary. I’ll file a feedback.

ViewThatFits has some strange effects when the size is animated.  Is it intended to work with animation or should it be avoided?

ViewThatFits should support animations, could you file a feedback for this one and share right here?

ViewThatFits feels very convenient but I'm concerned about making copies of the same content for each layout option. I assume a custom layout would be required to achieve this?

ViewThatFits is a convenience that might not be appropriate if you need something with animated transitions, or in general something with more complex behaviour.

watchOS

Is there a way on watchOS for SwiftUI to present a modal where the stays bar is hidden? For example, how the keyboard menu in the phone app hides the time. The entered phone number is displayed in the status bar area instead. Thank you!

if you present a modal that has a confirmation action, the time will be hidden for you automatically, but otherwise, the time will always be there. Is it possible to do this with watch kit or is the time always shown? I'm just wondering if it's possible for me to recreate the keyboard menu in the phone app. Thank you! I am trying to make a calculator like app, and liked this layout from the phone app. I liked that the input pad keys were large and the entered numbers were in the status bar area

Untitled

if you wanted to do that, you can do it in a modal sheet on watchOS, and you can provide a custom confirmation action as a button in the top right (like the delete button is), and you could provide a navigationTitle for content in the navigation bar, and then provide your own cancellationAction. but the time will only hide if you actually put content in the navigation bar in that spot (via confirmation action placement toolbar) https://developer.apple.com/documentation/swiftui/toolbaritem/init(id:placement:showsbydefault:content:)

On watchOS is it possible to call the keyboard from swiftUI straight from a complication? i think we still have to do a wkinterfacecontrol or go through a textfield.

No, unfortunately not with TextField or TextFieldLink. Could you please file a feedback requeset?

String input on WatchOS is quite limiting, because it happens in a non-customizable modal. Are there any tips or guides on how to achieve autofill of a textField on watchOS?

If you specify .username, .email, or .password, on the appropriate textfields, the system will provide the little keychain icons for autofill appropriately.


In my case it is custom strings. In my app, the user can see a List of mushroom species and search for a specific species using TextField. On iOS, I implemented another List that overlays the screen and shows results satisfying the user-typed value. The user can tap one of the results to complete the string. Not sure how to proceed in watchOS though

that sounds like a great use case. could you file a feedback with this info so we can pass it along?

And until then… Can you create a modal, which has a list, and at the top of the list, you include a TextField, and below the textfield you include list items that are your autocompletions, and if they tap one of those, they get the short cut values, and if they tap the textfield they can enter the raw text?


not quite, since each mushroom species is unique, so the selection depends on the first several characters of a string. For example, typing "ama" will bring up mushrooms from the "Amanita" genus. Also, on watchOS, once the user taps on the textfield, the entire screen is covered by the modal, so there is no space for dynamic suggestions to come up while the user is typing.I wonder if the new quicktype bar in the keyboard in watchOS 9 would be able to autocomplete some of these? have you tried .searchable on watchOS ?

I mean, it might not be exactly the same experience, but it would be very close.

you could have one of the search results always be the literal string that the user provided

So the first result would be the literal, and the rest of the results would be actual search results.

you might want to talk with the design lab folks about differentiating the literal from the actual results, but you should be able to achieve something like that

And the matching results will somehow pop onto the screen as the user is typing?

the user will have to type the first few characters and click the done button in the top right, so not exactly.

if searchable is helpful, great, but if you still feel like there's room for something to be better, please file a feedback request.

Windowing

Can Window be used for splash screen finally (such as What’s New? or News startup) . I’ve had a lot of issues making Scenes work for Document-based (and opted out on iOS) because it starts an app with a Nondescript Files.

Window is likely not the best expression for these types of onboarding experiences. A feedback for this type of functionality would definitely be appreciated though! For iOS support of Window, please check release notes for future changes

Would it be possible to have / pass separate NSManagedObjectContext for each window?Reason: Like for example if I have multiple windows on a Mac app and I want to create something temporary on to a specific window till the user decides to save it and make it available on all windows

Hmm, thats an interesting question. You could take a look at the new WindowGroup initializer which takes a binding to a value presented for the window. You could potentially use this value to determine your managed object context. More info on this will also be in the 'Bring Multiple Windows to your SwiftUI app' session on Friday

How do you pass data to a new window? openWindow looked in the session like it only takes an id parameter to help determine which window type should open, but suppose you want to inject a model object into that window?

There is a version of openWindow which takes a value as well: openWindow(value:).

Is there any way in SwiftUI to create multiple Windows (or Window like things) on Mac (and maybe iPad) or Pages on iOS?

You can certainly compose the different Scene types available in your App to create the functionality you'd like. For instance a WindowGroup and a Window or DocumentGroup and a WindowGroup, etc.

Could a WindowGroup value that has no stored dependencies be recreated along the lifecycle of an app? If some value is stored not in a @State in the WindowGroup, for example, let uuid = UUID(). Will it stay the same in this specific case for the lifetime of the app. This is of course a bad practice, but I've seen it quite some time on the internet, and I would like to know if in this specific case, the value could be recreated or not as the app runs. This is more a theoretical question to try to get a better grasp around this specific value lifecycle. In other words, are WindowGroup susceptible of being recreated even if they have no stored dependencies, no @State, etc.

I see. I think for this, I would likely recommend storing this in an app-level model, and providing that value to the WindowGroup I don't think it's being overzealous, if that is what you are concerned about.


Etc.

Is it possible to reorder items and insert into an outline group?

SwiftUI doesn’t have much in the way of automatic support for that, I’m afraid. I’d love a Feedback with details of your specific use case.

We did expose public API for disclosureGroupStyle this year, which might be worth investigating.


The use case would be a sidebar that the user can organize on their own. I was thinking this could be a normal list, but there a limits with cross-section item moves that I end up tripping over.

Makes sense. With the current API, I’d use a view model that vends the items as if they are a flat array, then style the items based on their apparent depth. That would let you use onMove or the awesome new editing support on List to update your view model.

Pages and Numbers are both document-based apps which have a beautiful onboarding experience. How do I build such an onboarding experience for my document-based app using SwiftUI?

While we do not currently have a high-level concept in SwiftUI for this type of flow, it may be possible to combine the  new Window scene together with the new OpenDocumentAction and NewDocumentAction to create it. You would need to define the Window as the primary (first) scene in your app, however. It's possible there may be some drawbacks to this approach, so I'd love a feedback for an enhancement in this area.

In your talk (Curt) you used objectWillChangeSequence but I can't find it in the new Xcode beta, where is it?

That’s a method that I implemented on my NavigationModel but didn’t fit into the slides. It’s in the Copy Code for the talk accessible in the Developer app though

var objectWillChangeSequence:
        AsyncPublisher<Publishers.Buffer<ObservableObjectPublisher>>
    {
        objectWillChange
            .buffer(size: 1, prefetch: .byRequest, whenFull: .dropOldest)
            .values
    }

There’s also a sample app with similar code: https://developer.apple.com/documentation/swiftui/bringing_robust_navigation_structure_to_your_swiftui_app

The sample app is a little more complex than what I shared in the talk.


Instead of objectWillChangeSequence would it be possible to use onChange(of: perform) to track any selection changes and update @SceneStorage data variable?

Yep. That approach will work too.

I used task in the talk so the restore and save code was in one block, but splitting them into separate onAppear and onChange should also work.

I implemented the new searchable APIS yesterday. One issue I have is that when suggestions are presented, it completely blocks out the entire search view. I'm wanting to implement something similar to the Photos search feature where you can see a small box at the top with search suggestions, while also display existing results. Is there a way to accomplish this with searchable?

If you’d like search suggestions to be rendered inline your results, you should consider them as part of your results and not provide any suggestion views to the searchable modifier.Note though that in iOS 16.0, for a regular width size class, a search bar that is displayed in the trailing navigation bar will display suggestions in a menu rather than over the main content like on macOS. Take a look at the SearchSuggestionsPlacement type and searchSuggestions(_:in:) modifier for customizing your UI around this behavior.

If your app is always behind an authentication session what is a good approach for blocking the app's content when authentication is required? In UIKit apps it was common to display a separate UIWindow atop your app's main window. Is this still a good way of handling it in a SwiftUI app?

Without knowing the details of your app, my inclination would be to try the RedactionReasons API.

You can use the .redacted modifier to set a redaction reason. SwiftUI controls will automatically react to that, hiding sensitive data. You can also read the reason from the environment to redact in custom controls.

You could also use an overlay modifier at the root of your hierarchy to present a view over the whole app, then adjust that view’s opacity based on the log in state.

Is there a way in the SwiftUI document model to access updateChangeCount directly, in order to decouple document saving from the undo stack? (Certain operations don't make sense to undo, but do change the document's file state.)

For now, there is no API available in SwiftUI for updateChangeCount.