Hi, welcome to another SwiftUI group lab, or as we like to call it, SwiftUI After Dark. My name's Kurt, and I'm part of the Worldwide Developer Relations team here at Apple. I'm joined by engineers and leaders from the UI Frameworks team: Anna, Steven, Nick, Russell, and Sam. In addition to those on screen, there's a team behind the scenes helping with the triage of all your inbound questions. We're excited to answer your questions tonight about all things SwiftUI and UI frameworks. If you have a code-specific question or somehow we can't get to your question today, please bring your questions to the developer forum at developer.apple.com slash forums, where we can continue the discussion. If you have a bug or a feature request, go to feedbackassistant.apple.com. We'll focus on questions tonight that will help the broadest audience. So without further ado, let's get to questions. And I'd like to start things off by just hearing from each of you about what parts of Swift UI you work on. Maybe, Sam, you can get us started? Sure. So before this world, I did a lot of work in programming languages. And so as a sort of natural consequence of that, I work on things that are like at the intersection of Swift and Swift UI because that's sort of where my interests lie. So if you've seen some of the type checking performance work that we announced this year, I'm very involved in that and anything else where we're thinking about how do we use Swift in really interesting ways. I actually worked on UIKit for most of my time here. But I worked on animations there and the interop between that and SwiftUI and the bridging parts of SwiftUI a little bit. Nice. Nick? I, too, I did a stint in AppKit. I did a little bit of work in UIKit, and now I'm a manager on SwiftUI. So when I do get to write code, I'm sometimes in presentations with Sheet and some of the containers like Inspector, Navigation, Dabble and Controls. And then this year, I spent a little bit of time in Dataflow. Oh, nice. And Steven? So before SwiftUI, I was an engineer on the Apple Music team doing SwiftUI development on the app side. And now my focus is on SwiftUI performance and also the agentic coding skills. that we introduced this year. Nice. And Anna? Yeah, I work on mostly navigation, bars, tabs. Effectively, if it's touching the way that someone is navigating your app, that's something that I work on. I get to work on it with Nick. Nice. Excellent. And before I became part of the worldwide developer relations team, I also worked on presentations and navigation. In fact, Russell and I shared an office, which was great. So let's go to some questions from the forum. So the first question is, with over a million reorderable items, 4-H doesn't render every view, but still traverses the whole collection on first display and every count or order change, causing slowdowns. UIKit's diffable data source has the same issue. Only a classic data source helps. What can we do about this in SwiftUI? You want to take a stab at it, Stephen? Yeah, so this is actually an issue that we're looking into and that we're aware of. It definitely shouldn't be working in that way. And the best thing to do is to file a feedback in order for us to keep track of it. And it's, I should say, when we're asking for feedback, it's not so much that we need to be aware of the issue. Like, we know there are issues, as Stephen said. But we want to know your particular use case. So why do you need to display that many items in a list? What's the nature of your data that causes that to be sort of the structure that you're building up? So that's the sort of thing we look for in feedback reports is tell us what you're trying to accomplish so we can make sure the APIs support your use cases. And bravo to this developer for downloading the betas and testing them out. We are, every day I get to work right now and I come in and see what feedbacks are coming in from developers. They're very visible to us. We take a look at them. We've already gotten a couple on state macro as well. And so we're fixing the bugs. And when you get them in early, we get to look at them pretty quickly. Yeah. Totally the best time to file feedback that will influence the next release is right now. So our next question, and let's see. And I think I'll let you take a crack at this one first. So in iOS 27, at least beta one, it's not possible to create a custom transition. The protocol navigation transition is publicly empty. What is the purpose of this protocol? And is there anything we can do to make our own? Yeah, so that is effectively a way for SwiftUI to expose things that conform to the protocol so they can be navigation transitioning. this is something that you know in Swift UI sometimes you will see like either like protocols or like also styles that will give you the pieces to be able to do your own like for example like a button style but there are other ones that maybe expose concrete members so like you can make a zoom you know navigation transition but they may not necessarily at least right now expose a way to do it to create your own custom one so kind of unfortunately going back to the last one but if you're able to file a feedback with your use case we'd be really curious about the kinds of things you're trying to build because it helps us know also you know what are the pieces that you might need in order to be able to build your own custom navigation transition right yeah so we've got crossfade transition and zoom transition and automatic as the sort of the trifecta today but one of the ones that i'm actually quite excited about this year which is very sleeper but any navigation transition which means you can switch between the two of them which is something that you weren't able to do before so like having that that dynamism is nice. Cool. And that crossfade one applies to sheets too, so you can do some pretty cool things with it. Zoom as well. Oh, yeah, yeah. Nice. Yeah, so the API is composed, right? So when you say navigation transition, we name that specifically because there was a lot of back and forth on what that should be called. Presentation transition, navigation transition, transition transition. But we named it navigation transition because navigation was kind of the unifying concept, like sheets are navigation. Another fun thing, just when you're making these transitions, there's no SwiftUI first class API for custom transitions in the sense that the UI kit one exists. But it's also quite fun and easy to build custom transitions for your own SwiftUI views if they're not on top of a navigation stack. So you can drive the animation yourself, and SwiftUI gives you all sorts of modifiers to flex the shape, and you can even use shaders. And so if it doesn't strictly have to be pushing onto a navigation stack, it's quite a lot of fun to build your own kind of transitions. Yeah, so if your animations are really powerful, like especially with, you know, animatable and you can have like keyframe-based animations, there's some crazy stuff you can do. Yeah, it's a lot of fun. So, Stephen, I'm going to send this next question your direction. With coding intelligence and eugenic models in Xcode, what are some ways we can implement it in building views with Liquid Glass, for example? So I guess let's talk about that more generally instead of diving into the specifics about it. And then we can maybe double back to the specifics. Yeah, so the new skills that are shipping with Xcode are a really good way to get some additional insight, especially into new APIs and best practices. And we would definitely like to get feedback on the skills as well. The tools that are built into Xcode are really good for rendering previews of Liquid Glass also. So iterating on the various pieces of the design to kind of get things looking the way that you want them to look is a really good way to sort of work your way towards the outcome that you're trying to get. And the skills are usable with the model of your choice as well, which is great. So, you know, if the results vary from model to model, you know, there's an opportunity there to to experiment with kind of trying to iterate with that. Right. As a reminder also about these. All these skills are built into Xcode's agentic workflows, and they work really great there. But if you use something outside of that, like some other agentic system, whatever it is, you can always export all of these skills. There's a command. I forget exactly what it is, but it's listed in what's new and in docs. It's in what's new and in modernizing your UIKit app as well. Yeah, yeah. So you can grab those skills and use them elsewhere. And also, they're fun to read through. There's a lot of really cool tidbits in there for humans too. And obviously targeted at LLMs, but that doesn't mean people can't learn from them. So the second part of this question is about using the glass effect modifier on buttons to apply a glass effect. And I want to take a second talk a little bit about what's in the human interface guidelines and what we've seen in the various workshops we've done around the world about adoption of the new design. When you put buttons in toolbars in the navigation bar, the top toolbar, they'll take on the appropriate glass appearance automatically. And so the glass effect is really for stuff that is not appearing in those locations. And in general, we would encourage people to not use liquid glass inside the content area of the view. Think of the glass control layer sort of hugging the content layer, and the content layer underneath is flat. Because if there's not any content scrolling underneath the glass, the glass effect really isn't providing any benefit. There's nothing for it to refract. It's just static. And so think about whether you actually need glass effect in some of these cases. Often the simpler design is actually better in the content area. I'm gonna take a dangerous venture down trying to describe controls. I don't work too frequently in controls, so Frank, please correct me if you're watching. But if you're trying to put glass on a button specifically, there is API for that, I'm pretty sure. There's a glass button style. Yeah, you want glass button style or glass prominent. I think FaceTime uses glass prominent where they've got that green button in there. It's like, this is the button. This is the magic one. So yeah, you can use it to good effect there and one error I see people making because it's very natural to do is to reach for a glass effect You're like oh button glass effect and that Alluding to the question that that will get you a button on glass, but it won't look exactly right So you probably want button glass effect And then on top of that you want button border shape a lot of times you want button border shape to like make it a circle or a Triangle triangle. Yeah, and the other thing I will say We're gonna hear about this one On top of like one to use liquid glass is reminder that if you put like a button into toolbar item like that will already have a glass background So you don't need to add one on top of that. And if you want it to take on a color like a prominent glass button might, you can just use a tint. Can you put content not on glass in the toolbar? Yes, you can. So you use, I believe it's the, oh goodness. It's shared background, hidden, true. Shared background, hidden, true. A lot of debate went into that one as well. Yes. We think a lot about names of things. And the main case for hiding the glass background, for example, you can see this in the Books app. It shows a profile photo of the current person who's logged in. And putting glass around and behind a photo of a person actually doesn't look great. And so this causes that to be flat and not have the glass treatment over the top. But we have something for that now, don't we? Yeah, we do have something that makes it a little bit easier to make kind of like the padding and other things good in that case. So because one thing that can look kind of cool is if you have like a little glass refraction around the edge. Like you don't have a huge piece of glass, but you have like just enough to kind of reflect. But it's mostly the profile photo. And we've added API this year so that you can remove that content margin that normally toolbar buttons will add around. So the refraction is right at the edge. Yeah. Yeah. Super cool. Because removing the background used to be the only way to remove that padding. It removed both. And then your view could take up the whole space. And so it would look the same size as the other buttons. But now you can remove just the padding and leave the background and keep your image inside. And even if it filled, then it can fill it. And then you get the rim and it's still made of glass, which then also means it mitoses better when you push and pop. Because the mitosis looks more natural if everything is glass. So it all looks much better now. I want all of the avatars to have like glass. Mitosis, for those who haven't had a biology class recently, is when the shapes sort of blob together or blob apart. It's like they have this sort of liquid really cool effect. Yes. Also called schlurp. Schlurp, yes, also called schlurp. I believe schlurp is the technical term, which is why we tend to stick with mitosis, which is a lot easier to experiment. Yes, it's so easy. So the next question, I think I'll start with you, Russell, and then you might be interested in jumping in also, or Nick. There's lots of us who have interests here. But we'll start with Russell. So what's the best way to manage screen sizes now in our apps with vertical and resizable and split views and all the different sizes that screens can take now, the resizable simulator? Like what API should we think about using as Windows, handle Windows resizing? definitely so one if you're hard coding for specific window sizes don't do that that that's been a losing battle for a long time um really just if you can lay out at any size you should be able to do that and then look at size classes um i think we're leaning like even more into them than we were before to and i think of them as kind of defining different experiences So at regular size classes, you get kind of your full like iPad or Mac-like multi-column experience. And in compact sizes, either vertically compact or horizontally compact, then you get a more like you're constrained in that environment. So you just want to display less. And sometimes that means just changing your number of columns. And sometimes it's much more dramatically changing your app. But if you lean into size classes, you should be okay. - But remember that just supporting size classes isn't fully sufficient, right? Like, you know, Windows can be many different sizes that like go in between where you'd want those size class transitions. So make sure that you're dealing with true flexibility, right? In addition to doing like different UI looks and feels per size class. - Yeah, I mean, I will also say like using system containers if that's like an option for your app can be really nice because then we're the ones doing the work for you to have to support that. But the other thing I will plug is something that, I don't know. I feel like it's just layouts in SwiftUI are also really cool and really powerful. There's a good WWDC talk from 22. Yeah, from 22 on that. Using custom layouts. Yeah. We're all thinking, oh, yeah, that's Paul's talk. Internally, we all think of who gave the talk because we know these people. And it turns out the stuff very helpful to those of you who are trying to find them. That was the final Paul's talk. Yeah. But it is the session on building custom layouts in SwiftUI. - Yeah, 'cause one thing that people, I think, is something that people will reach for is doing an if statement off of size class. And the thing that can be not great about doing that is when it changes, it'll tear down the view on the other side, so you lose all your state. Or you have to do a ton of work to make it so that the state is synced on either side. And that can just be hard to manage. So the nice thing about a layout is if you're genuinely changing the position of the views and they're flexibly resizing, then you don't have to throw away that state. Also a plug for what we're here, custom containers. Like the combination of custom layouts and custom containers is a really great way to make super flexible reusable controls that can like have all of these adaptations to different size classes, different layouts, like all sorts of different things. And demystify SwiftUI containers from WW24. Fantastic. Matt's talk is a good one to go to for that. I think we're all talking about like different ways to maintain structural view identity. And the one that we almost hit was like the Any Layout as well. So if you're really doing something custom but you want a custom layout in compact and then you want a different layout in regular, you can use Any Layout. And all of those views will maintain their structural identity. And Any Layout wraps each of those other – it's Any Layout, right? Is it called Any Layout? I think it is. It wraps – it can switch between those two layouts. It can animate between them too. It's very, very cool. That's all the structure is. And you can use the system ones too. Yeah. Another couple of things to think about in this space, view that fits is handy. You want to not use view that fits in a whole bunch of views at once because it has to measure successive views to find the one that fits. It literally tries the ball and says, which view fits in this container? But it can be at a higher level. It can be super handy for that. The other thing that I would plug is I think tab views are great. for this. Two releases ago, it would be iOS 18 and aligned releases. We, Anna really, built tab views that are, along with others, tab views that are adaptive and can have a sidebar at regular size classes, and that's optionally collapsible, and they have all kinds of configuration options. And that's a really nice container that adapts nicely to narrow, Compact size classes like on the phone with just the tabs or two larger ones And so I think that's a great container view that's maybe less appreciated than than it should be on larger devices One question though. I like a lot of people will you know you think okay? I need to respond to sizes. I want to use a geometry reader. I was wondering like Steven Can you talk a little bit more about like? When to think about using a geometry reader or like what the performance implications are and like how you know if an app is thinking I need to do something a little more precise like what they might want to think about when they're doing that Yeah, so I'm actually a big fan of on geometry change specifically because I feel like most of the use cases where people are trying to You know react to size changes for things like resizing grid items for instance What they really want is like break points for their various sizes You know like if the if the view is like wider than 320 Then I want to have like this particular layout for my cell And if it's like in this range, then I want to have another kind of layout. And the nice thing about on geometry change is that it actually has two closures. The first one is the one that actually gets the real-time geometry information that fires on every frame. But then whatever you return from that is the thing that actually determines whether the action gets called. So basically, like if you had a range, you know, where you're saying like 320 to 480, like I want to use this size, then you can specify that logic and then like only need to relay out or, you know, change things when you actually cross over those various thresholds. So you take something that's running at frame rate and suddenly it just fires twice as you cross the thresholds. Right. Like typically if I if I were, you know, on an older release using a geometry reader, I would really only do it in a background view for the most part, because putting things inside of a geometry reader, it ends up being really expensive for the views that are like sub views of the closure for for that geometry reader. In general, on geometry change is going to be a better tool to reach for. Basically, you don't want your views to be invalidating on every single frame. Right, and for things where you're trying to do more complex stuff, where you have the bounds and then want to do very specific placements, and I mentioned custom layouts, that's the tool it would go to there. So the combination of on geometry change and custom layouts is going to get you so far. And there's a super cool thing in the talk on advanced graphics in SwiftUI this year, Hauchian's talk. He has such a good explanation of alignment guides and has this really neat example where he uses alignment guides to do something that I would have thought you could only do with a custom layout, but his explanation of it is just so neat, what you can achieve with that. And it's super efficient. It's like layout once and it's done. Alignment guides are so powerful and so underused. Yeah. It's like that layout once thing that just kind of made me think of something that with on geometry change, it's still, even like the couple times that it fires, like even if your condition mostly means it doesn't fire very much, but the second closure, the only thing you can really do in there is still set some state or something. So this whole system will take at a minimum of like two passes to layout. It's like one initial one and then one additional one. Once you change that state, it needs to like run again. Whereas with like a custom layout, you can really lay everything out in one pass. So the next question, I think we'll start with you on this one, Sam. The developer asks, any tips on how to properly learn data management and passing data between views in SwiftUI? Are there good projects that would help us strengthen our skills in that, or how should we increase our knowledge there? That's a really good question. - At its core, at least in my mind, data management in SwiftUI is really making pieces of information and then trying to make your views as lightweight as possible such that they map that information to view data. So honestly, my biggest recommendations in terms of getting good at structuring that is even just building self-contained state machines and logical components that you can use all throughout your app to drive things. And then anytime you see that your view code is getting messy, trying to sort of bridge things back and forth, try to see if that means you can pare down that model or logic layer data so that it only has the things that it needs. I harp a lot on the fact that SiftUI is very architecture agnostic. And the reason for that isn't like there's no-- we don't want to make a choice. It's that we think there isn't one correct choice. And it really depends on the shape of the data for your specific app. So as far as learning goes, I'd say just build a lot of things that are trying to model very different kinds of data. And you'll quickly find you'll need very different patterns for each one of those cases to map them nicely onto these. Yeah. The thing I think about there is it's helpful to build sample apps in a domain that you're familiar with. So build an app for something that you care about. Maybe it's keeping track of your watercolor paints or how often you have to feed your fish, or whatever it is that you really care about. Because then you're solving a problem that you have, so you're motivated to work on it, and you understand the data. And so you're not spending brain cycles trying to figure out what the data is about. You're just spending it on trying to solve the problem. I think one of the challenges of going through a canned tutorial that is about something someone else is excited about is you have to learn what they're excited about and what you're doing in your tutorial. The problem I run into all the time. It turns out people don't want to look at my apps about floor tiles. It's just not good sample code to look through different terrazzo patterns. People aren't into that. You just need to find someone who has your same interest in floor tiles. Still looking. I'm also a big fan of using instruments for this. You know, not necessarily, like, people typically use instruments for debugging performance, but the SwiftUI instrument is actually really powerful because it shows you a timeline of all of the things that are being updated so you can actually understand how the places that you're updating your data are affecting, you know, which view bodies are running, and sort of, it can kind of show you how the data is flowing through your app in that way as well. And you can also see the work that SwiftUI is doing as a result of the changes that you're making to your data, And that can kind of help you understand how things work and how stuff flows. I've also been peddling dynamic property to all who will listen this year. I finally learned the power of dynamic property. And it's hard to explain on a panel, but a lot of the times on change is very helpful in a pinch. But as your views grow and you have lots and lots of on changes, a good rule of thumb that I like any on change can probably be replaced by a good usage of dynamic property. and then going back to Russell's point that also saves you an extra render cycle because on chain or dynamic properties their update method is called right before body and so you take what was an update of the on change updating state and then re-rendering the view and you move that into the dynamic property updates and the view renders and you're done yeah yeah anytime you have like any kind of on change or like action-based closure in some extra state you're like incurring I mean, both like extra memory to store that state, but then like extra time to process that. Yeah, that's a great point. Like we had a question in the previous SwiftUI lab, which is was about sort of anti patterns. And on change isn't always the wrong move. But sometimes I'll be like looking at code in a workshop or something. and a developer will be using onChange in order to do a bunch of calculations and then update some piece of state. And it's sort of like trying to get back to imperative code and do the work there. And ideally, you'd have a data model that's doing that work, and it's just vending the new value as the other values of that data model change. And you make it observable, it updates efficiently. So there are cases where onChange makes sense because you have to broadcast to some external system or whatever. But if you're using on change to mutate the state of the view, that's almost always not the right move. Yeah, I see a lot of people in various forums saying like, oh, you know, XAPI is bad or whatever it is. Like you shouldn't use it. Generally, if we ship an API, it's because we think like it is useful. It's a stinky one. Yeah, like, you know, on change, any viewer things that I hear a lot of people saying like, oh, they're, you know, spooky. You don't touch them. But I wouldn't so much put it that way. I would say when you see uses of APIs like that, it's a sign that you should look critically and make sure that the usage is justified. For any view, are you actually erasing the type of the view? Are you using a heterogeneous collection? Or are you just wanting to make it easy instead of thinking through the generics? And for onChange, are you actually doing something reactive and that needs to be an imperative breakout point? Or are you just using this to plumb things through that you otherwise could use the environment or a dynamic property or something else to better work? We haven't mentioned onAppear, And I feel like that's even more common than on change, actually. And this is my favorite use case for dynamic property, which is that, you know, commonly, if you're loading something like an image, there's the possibility that you'll already have it in your cache. And in that case, you don't want to wait until on a peer to load your image because you're basically going to be guaranteed to have a full re-render of your view, even if the image was already available. And so because the update method of a dynamic property fires before the body renders, you can actually turn a dynamic property into a property wrapper and vend the cash to value if you have it. And then it's available to the body on its first run. And then you don't have to do that round trip. And that can make a really big difference. And there's a great example of that in the talk this year at DubDub on lazy stacks. So Renz talks about how you can-- actually, it's this exact example, how you can move that loading earlier in the process. And SwiftUI is smart enough that it can instantiate a view, it can process the layout, and then it can do the rendering in separate frames. And so as you're scrolling and a view is about to come on screen, if we can have it all laid out before it gets there, it can render super fast and avoid glitching when you scroll. It's super cool. And the talk is so good. I just love it. It is a really good talk. There are a lot of depth in that talk. While we're here in On a Pier, my favorite feature of the year. The rhyme. The poet. Nick is dropping some rhymes on late night. It's really subtle, but it was a lot of attention to detail paid by one of the engineers on the team to take advantage of new Swift concurrency features to make task and On a Pier have the same timing. So there was this really subtle behavioral difference where if you stack like a task and an on appear on a view So you have you dot task dot on appear the on appear would fire first because the task incurred an isolation hop And now that doesn't happen with the latest with concurrency features, and so they'll execute top-down nice It's a nice like ordering improvement awesome So the the next one Who should I throw this at? I think we'll start with Russell because he raised his eyebrows out Let's go and feel free to bounce it to someone else if you don't want it so Developer asks I've heard in multiple places including the last two Swift UI group labs this week That I should be using If to conditionally hide elements So what's Apple's recommendation? And part of why I love this question is the example that was provided. So, for example, only at 941 should I show that it's 941. Otherwise, I shouldn't show something. Somebody pays attention to their Apple demos. It's always 941 somewhere in Apple Park. In Apple Park. If you wanted to show 941 only at 941, then the best thing would be to add like an opacity modifier or whatever transition you wanted, which is part of why I love animations. It's like one of the things I've worked on for so many years because the animations often inform much more than just what happens when it moves. They can inform the structure of the whole thing you're building. Anyway, back to 941. If you wanted it to fade in and out at that time, just use an opacity with a conditional in that modifier and have it be one at 941 and zero at any other time. So then it's always there, but it disappears at the other times. Now, if you need to actually remove it from your layout so that it doesn't take up space, I might bop to see who else has a good suggestion for how to handle that. No, if you're doing something like that, then it is fine to conditionalize it. If you're actually removing the view and putting it back in, then you're going to have to do new layout and all these things. The reason to avoid doing that is we don't want to have to reflow layout and reinitialize state and things like that if the view is not actually going away and reappearing. It's just visually changing with the opacity. But if it really is being removed from the hierarchy and not just hidden, then yeah, that's the time to return. But what about in view modifiers? like conditionals for the content of a view modifier, for instance, like where people, like if you had a 941 view modifier and like inside, it was like, you know, like if 941 content dot overlay your text, otherwise just content. What are the implications of that? - So I mean for conditionalizing view modifiers, right, generally you wanna make sure the view modifiers take arguments such that like you can pass in an argument that will do nothing. And you see that with a lot of, hopefully most of our modifiers, where there will be a value that we consider inert, as in it will do nothing. Just like one was for opacity. Yeah, exactly, right? Like if you call opacity one on something, it doesn't modify the content at all. And you want to be putting the conditional expression, not like an if statement, inside of the arguments. And one of the challenges, and we see it all the time, is if a conditional is inside the body of a view modifier, then that view modifier gets applied all over the place, and you just made those views relay out, and as the person applying the modifier, you don't really know that you're doing that. It's like... And if it happens upstream, you're very confused. Yeah, if you ever see the pattern of making an if modifier that basically is just a modifier around a conditional branch, it's really dangerous for exactly that reason. You can end up with all sorts of conditionals in places you don't expect them, and that can cause state to get reset, because if you switch a conditional branch, you lose state because it's a new view. So you want to be very careful with that kind of stuff. - Just like an interesting pattern when you're designing modifier APIs is sometimes you have the inert one because it makes sense and then there are other SwiftUI modifiers that won't have an inert version and that's not an oversight, it's more so in the spirit of that particular API. So like certain styles are static in that you pass a type to them that's generic and that binds to that modifier You can't change that, and that's kind of intentional because SwiftUI uses that static information to render more efficiently. And so switching styles like that on the fly is something that you might want to do. If you really need to do that, that's more of an if-else type of thing. I think the place where it came up earlier in the week about avoiding if in particular was an if statement at the top level of a view that's in like a lazy stack or a for each. Because in that case, SwiftUI is counting the number of views. It's identifying the views and position based on how many there are. And if a view is like scrolled out of the screen, but it had a conditional at the top level of it, we don't know whether that view should be there or not. And so we have to keep it around so that we can tell whether the conditional state changed. And so, again, Renz talks about that in the lazy stacks video this year. But that's a case where, you know, if you really do need that conditional, should maybe wrap the whole thing in a stack so that there's always a view there and it's empty sometimes. Yeah, so to provide a little additional clarity on that, since it can be hard to get a mental model for these things, the problem case for like lazy containers like list and lazy stack is when you have a view that could resolve to multiple sub views. So if you just wrote like a view builder, text, text, text. If instead you wrap that whole thing in a vstack, right? Now that vstack is one resolved view. So you're always going to get one view out of it. And the same advice applies for things like any view. Any view conceptually can have any type under the hood. So it could produce one view. It could produce 10 views. Custom layout is the same. Yeah, exactly. So if you have any of those things, if you wrap them in a unary container, like a vstacker, some layout, you'll be guaranteed to always produce one view and then you'll get the fast path for those lazy containers. - But if you just make your own view type, that doesn't do that, right? Like if you return something from body, and it's not-- - No, yeah, you can return multiple views from body. - Exactly. - Right. - And that's still multiple views. - And that's still multiple views. - And that's still multiple views. - And like group is like that as well, it doesn't flatten. - And there's a reason for that, right? Like you could imagine you'd make a custom view that you want to be able to pass to a list and have it expand out to multiple list rows instead of just like one list row that's surrounded in like a stack or something like that. - Right. - So that's important functionality And it's very intentional. We have to be careful about it when working with lazy containers. Yeah, well, the other data flow thing that I think not as – people, if you've been developing in SwiftUI, I think most people have heard of the environment. But I think something that people have sometimes heard about less are preferences and traits, which can flow upward. And the other thing is traits are accessible to kind of like your surrounding container. And so if you put it – Latrips, you mean container values? Yes, container values. Sorry. Thank you. More naming. - More naming. - More naming, yeah. - Container values, so they're accessible to your surrounding containers, so the one thing to know is if you're wrapping something in a container, like a VStack, that will mean that a container outside of it can't read those container values. So that might be desirable, or that might not be, but that is one thing to take a look at when you're debugging. - And that actually, both of these last two things, the counting the number of views that a view actually expands to, and the container values API are covered in that Demystify Containers session from 24, which is just super cool. It's also karaoke themed. It is. We love karaoke. The next one I'm going to throw to you, Sam, and this is a bit of a segue. You mentioned any view in that conversation. We moved on from it, but let's go back to it. What's the concrete cost of type erasing with any view if it's in a deeply nested or frequently updating view? When should I worry about it? When should I not? So you know how I mentioned with the if else case, right? Sometimes you need to switch the view that you're showing, and then that's okay. With any view, in general, there are places where you need to type erase views, right? It could just be that at compile time, you don't know what the type of some view is going to be. And in cases like that, any view is a fine thing to reach for. The case to look out for is when the underlying type would change Because if the underlying type were to change, like let's say it starts out as a text and then you change it to my special view, when that change happens, just like if else, you have to sort of tear down the view hierarchy and then rebuild it. And that is not super efficient. So if you can, try to avoid changing the underlying type as much as possible. And that will get you in good performance cases. And then the other one is exactly the thing which I was just mentioning, which is if you're in a lazy container, you need to be careful because it won't be able to tell the surrounding lazy container how many views it resolves to. As mentioned, you can resolve that by like wrapping it in a stack. Right. So I'm going to throw this one to you, Nick, and you can throw it to someone else if you'd like. So the the question is are there any tips for making Swift UI layouts more adaptable now that Xcode previews are resizable? We talked about this a little bit but But like is there anything with with custom layouts that maybe we should think about differently? Anything along these lines? I'm gonna need some time to think about this. This is like an abstract question. It's kind of one of those like Give me a little more about kind of what you're doing, but yeah, it's tough to say without like Specifics here, but that's right good. I think you have more to say about this tonight You start I mean, I feel like when you're writing layouts So sometimes in your app you may be writing like a really bespoke layout and you may have been thinking like okay This is going to be a particular size like I know maybe I hard-coded some things it happens. We've done it but Like the size is an input parameter So if you've set up your layout such that you're kind of prepared to accept any size and do something That is reasonable in any of these sizes Then like you're really already well on the way and I would probably you know test that like you have You know now a way to test that I would kind of tested at all the different sizes See do you like the results that you're getting if not then maybe you know evaluate what you're doing But honestly, you're probably in a pretty good place if you're writing a custom layout right and that that actually I think is a brilliant way to think about this is like, actually the question is kind of backwards. Now that you've got resizable previews, resize your app and see what happens. Find out where you made assumptions. Find out where the layout breaks. And then go in and find where you put that magic number that causes this to break and figure out how you need to react to it. And also just use your app in context where it is resizable, like on iPad. You really quickly find out when you're trying. Yeah, iPhone mirroring. You really quickly find out when you're trying to resize your app and use it when it doesn't quite work in certain situations, and then it's much easier to patch that stuff. You use other people's apps. I like to apps and websites. Just resize them and see how different people deal with this. It's one of my most favorite parts of looking at a lot of indie apps. Indie developers in particular, they get to do their own. They're not bound to a product team or a design team, and so they get to be really creative with how their app adapts. So there are a lot of apps out there that do something really special and compact, and then you wind them up and you're like, oh, this is a very creative use of space. So cop-out answer. Figure out what your app should do by looking at other apps and figuring out what you like. Inspiration, right? Take inspiration from other apps. All right. Ah, this is a challenging one. We'll start with you on this, Adam. You might choose to throw it to Russell because this is a topic all three of us have discussed, I think. But the question is, what's your advice for presenting full screen Swift UI overlays on top of everything else in the app, including Sheets? Is there any way to do this that doesn't interfere with modal presentation? Look at the wheels turning. This is a hard question. All three of them go into loading spinner mode. I can elaborate more because this has come up in our workshops sometimes. A common case where people face this problem is they'll want to present a login interface over the app. And so if you happen to get logged out because of a network disconnect or something like that, teams will want to bring up a UI over the top of the existing UI. And I'm not actually sure there's a way to accomplish that in SwiftUI. Or I think you would have to be probably pretty coordinated about your navigation model and your data model Like if you're able to get like because a full screen cover once you've presented it That will take up the whole screen provided like kind of if you think of it as like a little like hierarchy Like if you're at zero and you want to present something on top of zero and that's like a full screen cover You're good to go But if you have like this question said another modal presentation and maybe you have another modal presentation presented Like that's gonna be trickier. So I think at least if you want to be using like Swift UI with like the API's currently as is I would probably try to track the presentations and you know See but we'd also probably welcome a feedback for like your use case. So we make this better. Yeah, for sure I mean, this is right. I mean for I know it's a Swift UI lab We love frameworks friends we love frameworks drop some UI window on us Thank you for the invitation I feel safe saying that now. Yeah, I mean, because even in UIKit, even if you had a UIKit app that was using SwiftUI at all, it's difficult to present something or to get something on top of other presentations in your app, especially if you don't have a central way to manage all your presentations and don't know if there's anything there. And so the easiest way maybe to drop down to UIKit and you can make a new UI window If you're using UI kits, scene lifecycle, then you have access to the scene, and you can end it with a scene, and you can position it on top of things. And so if you have a HUD or a very specific use case that really needs to be over something, then you can drop down and do that. And you can put SwiftUI in there, so you could make its root view controller a UI hosting controller and then do anything you want. And it probably wouldn't be so bad. It should work. Yeah. There's plenty of people doing it. I've hacked it to. Yeah. For years and years and years. It does then kind of lead you into another area where, well, what if something wants to draw on top of that? Right. I do find this way of thinking can sometimes be like, well, I'm the number one thing. Of course, this thing should always be on top of everything, which is true until you think of something else that needs to be on top of everything. Or a person on your team who didn't know that you thought your view needed to be on top comes along. Right. And if you don't, I think it'll be last UI window wins. So if you have two teammates making UI windows, whichever one is last wins. And that's the whole thing SwiftUI is trying to solve. And I think that actually gets at a really interesting way of thinking about problems like this sometimes. It's kind of a reducto ad absurdum. It's like, oh, actually, we can't have a distributed decision-making process about which window is on top. There has to be some source of truth for what layering we're doing there. And if it's just all the different pieces of code can say, no, now it's me, that's a bug waiting to happen. And so think about whether the design brief is right here. Maybe that's not the right way to design the app. Maybe whatever you would present the full screen cover for should actually be a more elegant flow. Maybe it is rewinding the navigation stack to some base view and then restoring that navigation when they log in. There's other ways to approach that problem. I'm not saying it's always wrong to present a full screen cover, but think about it. It feels very disruptive to the user. In general, for any of these things where you do need to drop down to UIKit for these sort of things, that is not a bad thing. We build our frameworks with real interop in mind for exactly this reason. There are cases that will work better in one framework, better in the other. And but if you find things that like you really want to accomplish in Swift UI and you need the drop-down to UI kit for them Follow feedbacks about that we want to hear like where you're running into those corners so we can ship some maybe eyes to make them better Excellent So this question is along a similar line. I think I'll start with you on this one Anna So the the question is what's the best way of building a pure Swift UI custom control? And I think we'll come back to pure Swift UI before we're done with this, but for now at face value, a pure SwiftUI custom control, like a dropdown that can expand on top of other elements and be interacted with, but doesn't impact the layout of those other elements. So how can I go about building a custom control like that? Yeah, I mean, definitely. So I think first, like I would think about, does this need to be custom? Does this not need to be custom? Kind of like going back to what we were talking about, you know, if there's a control that exists in like UIKit or exists in AppKit and SwiftUI doesn't have it and you're considering building your own custom one in SwiftUI, I would probably think about using the framework interop and just using that UIKit or AppKit control because then you don't, like if things change in the framework, like this year we made some tweaks to the new design, you just get that for free and you don't have to then go and make updates in your app. But if you wanna do that, that's definitely a very fun question. SwiftUI is definitely pretty compositional and so you can kind of compose a lot of those building blocks to build really powerful things. I think one principle I would say that is good to think about here, because the question is kind of impacting the layout of other elements, is the way that SwiftUI layout works is the parent asks the child for its size, but it's kind of a proposal. The child can still decide to draw bigger, to draw smaller, and it reports its size. So one thing that you can do here, and I would love a double check just to make sure, because this can get kind of complicated, but you can effectively, you get proposed a size, but you might tell your child actually to draw a bit bigger than that. Hey, you're cool to draw this big, but then you tell your parent, I'm only this size. So you might be lying a little bit, but that means that you can lay outside of those bounds effectively and do an overlay that isn't going to affect the layout because you're just reporting a stable size. But also you can use SwiftUI overlays or kind of like a higher level convenience on top of that. - Yeah, I'd go so far as to say that's not even like lying. That's kind of the intent of like the SiftyWise layout system, right? Is that parents propose sizes to children and then the children get to look at the proposal and say, no, I'm actually this size or I do fit in those bounds and I'm gonna go here. Or rather, I do fit in the size, I'm gonna be this big and the parent can place. There is one case where that can, well, maybe more than one, but I know it's one case where that can get you into trouble. If you're drawing outside of your reported bounds or outside of the layout frame that you've been given and you're in a scroll view, the system may remove your view from the view hierarchy because it thinks your layout bounds are off screen. But you have a protubant sticking out into the screen and suddenly it disappears. And so combined... We'll talk about that. Yeah, it does. Yeah, and so I learned that this year. It's a good time. So that's even a gotcha with overlay too. Because I was going to go with overlay just because overlay you know that you won't affect the surrounding layout. you're very isolated in that render. But also, to that point, if you're, like, overlaying a view big and your host view is small and it scrolls up off the screen, that's a tricky one. Yeah, yeah. I need to watch Renz's talk. Yeah, you should. It's really good. All these design talks that were really good this year. And that's another reason to stick with custom controls. There are all these interesting corner cases you have to consider. And so, maybe the drop-down menu should actually collapse when the view that's hosting it scrolls, right? Because the person's demonstrated intent not to interact with that because they're scrolling it away. Or maybe it should stay and they're trying to scroll it so they can see more information. It's like there are these really fine corners that you need to consider when you build your own custom controls. Swipe actions are a really good example of this. The container for swipe actions is responsible for coordinating all of the various actions. And when you scroll, you'll notice that if you have like a like a if it's swiped, basically, that it'll dismiss so that that, you know, it's detecting that intent that you're scrolling away. And it's all those fine little details like you were saying. Yeah. And thank you for bringing up swipe actions because it is my favorite API that's new this year. And Stephen and Julia's What's New in SwiftUI talks about this. But previously, you could apply swipe action modifier to rows in a list. but nowhere else in SwiftUI. And now you can make any container a container that supports swipe actions by putting swipe action container on it. I think it's a very literal name. And now you can add swipe actions there, which I think is so much fun. Before we move on fully, I do want to add one note, which is some of the things we said are like, oh, use system standard controls. And I totally agree. But I also don't want to discourage people from making their own controls. Like, yes, it's complicated. There are a lot of things to consider. It's why it's a serious investment. But sometimes they can be like, you know, the little touches of magic that like turn an app from like good to great But I encourage you to think very critically when you're doing this Like am I adding like real value to the experience by designing this as a custom control? Or is it better a system standard UI because using system standard UI means you get like an experience people are immediately familiar with But if your app has a very specific case where you can do something more than don't be afraid to drop down get your hands dirty And the other thing I bring up, and it's something that Jason mentioned in our last panel, if there is an ability to add custom styles for that, reach for a custom style before you wrap a control and make a custom control. Because you're going to get all the accessibility support and everything, and you're just controlling how it looks. And so that's a great way to approach sort of that style that you might want to go for Not to overload the term I guess Well still you know getting that you know all the built-in behaviors you would expect from a built-in control Well, the other thing that I thought was interesting about what he said in that was Not only do you get that but also you can use all of like the normal control initializers So you don't have to create a million ones like that was a point I feel like I just think styling is really cool because of the points you just mentioned So that initializer benefit, not having to maintain it, is really nice. Yeah. How many initializers does button have? A lot. Many. There's one fun thing I want to share about swipe actions in particular. I don't know the technical term, but the small circle buttons that exist as you swipe it open, if you're using that outside, if you're using the swipe actions modifier, those can be any view now. It's not just a label. It's not just a text. I wouldn't recommend it, but you can put a navigation split view in there. Like your own your own custom view it doesn't again it won't just be limited All right, I think I think we can take a couple more questions. We're getting near the end of our time I'm Stephen. I'm gonna I'm gonna direct this one to you So it's it's well known and thanks we've done our good job of communicating the breaking large Swift UI views into smaller views benefits with UI's performance, but how small should they be and Like is there a best practice when we should make new struck to views versus just adding at view builder computed properties. Right, so the way that I like to think about this is that breaking things into smaller views is not just about making smaller pieces. It's actually about isolating the pieces of data that are actually responsible for those views updating. So the example that I like to use is, let's say that you have a view that has a header and some content and a footer, and the header could update independently, the content could update independently, same with the footer. you wouldn't want to be in a situation where the entire view is being invalidated and the body is running for everything when only one of those pieces of data changes. And so that's a case where it would make sense to maybe split that into three different views for header, content, footer. If you're in a situation where the dependencies are kind of shared across everything, then splitting things up isn't really going to give you any benefit at all because you're doing the same amount of work. So the way to think about it is that the goal is to, at the initialization point in a view body, to provide a boundary where SwiftUI can basically do its comparison and say, actually, there's nothing new here. So I don't need to actually do this work. And that's why using view builders as computed properties instead of views, you don't get that benefit because you're basically declaring the same thing as one giant view body. Right. You're taking your implementation and you're moving it out of line. But it's functionally the same as if it's all just combined into one. And so all the dependencies are still there. Whereas like just to – I love this question. So I sort of like even like re-summarize it for myself a little bit that you want to like if you can break things into smaller groups of dependencies. So you could think of a view as like it runs as often as any of its inputs change. Like any of the things you pass into it, bindings, environment, like whatever you read in body. When any of those things change, the entire thing is going to be reevaluated. And so if there's like one thing that changes all the time and eight things that change very infrequently and only a tiny part of your view body that changes based on that one thing that's changing frequently, if you can move that bit out, then when that frequent thing is changing and the original body doesn't need it anymore, then it won't run at all. Now if you like had to pass it through then Then that that body would still run because it's being passed through and that's other ways to like jump over That's a case where observable comes in handy because the pointer to the observable doesn't change and so it doesn't change the Superview, but the property that that little tiny subview is reading out Does cause it to redraw it so you can skip the big stuff up above and just do the little one right? And don't be afraid of having lots of views like views are or structs their value types. They're cheap You know, we shouldn't be afraid of having lots of smaller pieces All right, we're nearing the end, but I I wanted to get to this question. I think it might be a Good closer for us so Sam I'm gonna start with you and we'll just swing across the panel. Okay, so Having used Swift UI since day one Swift UI 1 maybe the framework has truly come of age Thank you. Looking back at the evolution from the early state and the navigation pain points to the mature declarative engine we use today, what are y'all most proud of? - Oh man, that's really tough. What am I most proud of? I would say it's a combination of two things. I think the first one is just like a smaller thing that I got to work on that I'm really proud of, which is the custom containers API. So I talk about them a lot. And it's a very complicated thing to express that I think we managed to distill down to its essence. I'm really happy with how that turned out and how the cool things people have made with it. And then the other is more about the overall shape of the framework. We've done a really good job of making sure that we think about things in terms of a little bit more semantic pieces rather than like, oh, this is going to appear in this specific way on the device thinking, okay, what is the thing? Like a tab view. A tab view can either be the standard thing you've seen or it can be like a page and ending scroll view, but like ultimately they're the same pieces like data flow wise. And it's been really cool getting to like rethink like the platform's UI systems in terms of like this new way of thinking about them, like how is their data flow arranged? And I'm really proud of the job we've done with putting the pieces together there. Cool. Russell, do you have something? Yeah, I can just quickly say that I'm most proud of how it's grown and how we've been able to use it more and more internally. As someone who's worked on UIKit for a very long time, you could poke around inside of UI Navigation Controller and the U Debugger and you would see that we're starting to use SwiftUI to build some of the new core UI components that are used across all of the apps, even apps that have not been rebuilt using SwiftUI. And it's really nice to see it reach a level of maturity that we can use it in such broad systems. Yeah. Nick? I'm blanking. The only thing that's coming into my head is just like I'm just really proud of the team. A lot of people on the team have been around since day one and a lot of people are newer. And it's just such a nice group of people and the way they think together. And I just love seeing people like laugh about horrible API things. Like tonight. Yeah. It's like building that over some amount of years, it's just as hard as building the framework. And so that's something that I really like about it. Nice. I love that. I like how we've taken things that end up being suboptimal, like, for instance, Geometry Reader, figuring out the reasons why people are using them and actually providing new APIs that solve those problems. Things like on Geometry Change, on Scroll Visibility Change, all of these places where people would reach for something, like really figuring out those cases. Really like seeing that adaptation I think it's just been really cool to see over the course of you know The years how like more of the lower level building blocks have been exposed to allow You know people to be able to build their own custom things They feel like some of the stuff that we get to use internally developing for Swift UI are really cool And it's cool to also give those tools to the broader world and see what people build yeah Also, of course now that we've all said this like I'm sure all of us are thinking of like 10 better Like they're just flooding into my mind But hopefully that will suffice. We'll save those for the next group lab. Exactly. So we've reached the end of this one. And we're so thankful that you all joined us today and hope you found this helpful and maybe entertaining. A big thanks to our panelists and to all the folks working hard behind the scenes to make this happen this evening. If we didn't get to your questions, please visit the developer forums at developer.apple.com slash forums to continue the discussion. and visit feedbackassistant.apple.com to file any bugs or feature requests and let us know about your use cases. Speaking of feedback, you should receive an email with the survey link to let us know about your experience with all of WWDC. We'd love to incorporate your feedback into future events. Again, thanks for joining us. I hope you have a great WWDC.