Welcome to Under the Radar, a show about independent iOS app development. I'm Marco Arment. And I'm David Smith. Under the Radar is usually not longer than 30 minutes. And we say the usually because of days like today, special days where we have special guests and we have abilities to do things that are out of our ordinary. So we are recording, as I would say, live, but we're not actually live. But we are recording from the Apple Podcast Studio at Apple Park at WWDC 2023. And even more importantly, we have two guests with us today. We have Josh Schaffer and we have
Chris Thielen, who will be joining us to talk about the announcements, to talk about the things that we talked about. I think in many ways, for me, while the morning keynote is exciting, the morning keynote is something that is really cool to see and I can watch it with my kids.
The afternoon platform State of the Union is where the real fun happens for me. That's, you know, it's like have lunch, settle down, and then that's where the real show starts. And I would love to kind of get some context and some things about that platform State of the Union and kind of get the director's commentary of that. And so I'm so glad to have you guys here to do that. And it's just wonderful to have you. So let's get started. So let's get started. That's right. I forgot to say that.
So I always feel like at the beginning of the, if you pay attention to the platform state of the union and there's always a sense of, there's a theme, there's something that you're trying to get across. Last year, I would say it was the best way to make apps is with Swift and Swift UI. That was the theme that I think was trying to be communicated last year. And a phrase that came up several times is,
this year was that the natural sort of the natural way to write a to write code is now the best or the safest way to write the code. And that seemed to be the philosophy that you were trying to communicate this year. And I was wondering if you could elaborate a bit on that philosophy or sort of approach.
Yeah, I mean, I think from the beginning of Swift UI, one of our key goals is that like we made the thing that you would naturally write be the right thing to write. You know, Swift UI aimed to have a very succinct syntax where you would just describe the elements in your UI and doing it the way that was most natural would get you the right result.
And we certainly tried to extend that to Swift data this year where you'd naturally in Swift just write a bunch of types. You'd write some classes and structs and enums and you want them to be persisted. The way you wrote it should just naturally work for you and you shouldn't have to go and restructure your data in unnatural ways in order to get it to be persisted. And I think that kind of philosophy has been following what we've been doing in this space now for a few years.
And I think it's been working really well. And with Swift more broadly, I think even going back, was it nine years now? With Swift UI and Swift data, I think you can kind of start to see the trajectory of what sort of the era of Swift frameworks looks like. And that's absolutely one of the design principles. Yeah. And I think too, it's something that I noticed is, I mean, it's like speaks to the maturity of the platform that you're able to,
have a sense of what is the idiomatically best way to do something now in a way that maybe like eight years ago, that was still something that we collectively, like as the developer community and as, you know, the developer tools community are coming up with. And it's like now things are mature to a place that it makes sense to have something like macros where you can, you know, it can replace our boilerplate code with something more idiomatic and because it knows what idiomatic, the correct thing is now.
Yeah, and I think if you look across the frameworks we've been doing over the last few years in Swift, there's some patterns that are emerging now of things like you create a struct that conforms to a protocol, and then there's a bunch of standard methods that you implement. So things like SwiftUI has the body method,
Things like the app intents have a perform method and there's a bunch of structure around it. And it feels very object oriented, but most of these APIs in Swift are structured around structs, except where it makes sense, like in Swift data where your primary persisted objects are classed.
Sure. Yeah. And code first too. I mean, with Swift data now, you don't have to go into the core data model editor as great as it is. I still love that model editor. Yeah. You know, App Intents is the same way. There's this sort of code first approach now. And I love that, by the way. Like, you know, having previously used the former, you know, intent definition files and things like that, you know, those would then generate some code behind them. And that process always was, I thought, a little bug prone and a little bit more difficult to get into and difficult to manage in certain areas. Yeah.
And so moving things to code first and everything, you know, everything becomes easier to version, easier to merge, easier to work with. And the tooling around it becomes much, much simpler and more reliable. So I very much appreciate that. I'm curious, you know, talking about macros in the sense that, you know, you have these two competing, you know, a pro and a con here.
The pro, as Josh mentioned a second ago, is it's easier to write correct code. And of course, we've all seen times when we're writing SwiftUI and we're like, why isn't my view updating when this changes for some reason? And you've got to kind of dive through and figure out somewhere that you...
should have used a binding and said use a state or somewhere you weren't updating the observable, various protocols and triggers and things like that. With the new observable macro, that is taking care of a lot of that for us and thank goodness for that. But also, as we look at what macros will enable...
there's also large potential for hidden magic or hidden complexity that is non-obvious for the caller or at the call sites. And so how do you manage the problems of having hidden, unexpected behavior happening versus the benefits of something like Observable where you're taking away all this bug surface? Yeah, that's a great point. I think...
If anything, macros are actually designed to help us make that less magical and easier for developers to understand. Because if you look at something like property wrappers, which we did a few years ago, they have a huge amount of power behind them. And there's a ton of stuff that the community has done with these that is really cool. But the transform is mostly hidden. You write a property wrapper on something and you can't really, as a developer using it, see what happened.
Yeah.
And so the really cool thing about at observable and at model is that there actually is no magic there. And in Xcode, there's like a deep integration with the macro system where you can just right click on at observable and say expand macro and see exactly what it does.
So the fact that it transforms some properties from stored properties into computed properties becomes immediately visible and evident. Now that same thing happens with the property wrappers. It converts stored properties into computed properties, adds a backing property, but you can't see it. So the really cool thing about macros is that this kind of
behavior is no longer magical. You can actually see exactly what's happening, debug through it, and fully understand it if you want. If all you want to do is use it and you're not worried about how it works, you don't have to see that. The complexity can stay hidden. So it's a really great balance between ease of entry, where a new developer just coming to the platform and trying to learn can know, like, oh, I want to use my object with SwiftUI. Let me mark it at observable. It's just going to work for me. But as you get more advanced, or if you really want to get into the details, you can go expand it and see what's happening, and there's nothing that's fully...
hidden and obfuscated for me. Yeah, I think there was a moment when Holly was doing the step into debug mode. I think there was an audibly gasped. It was the like, how is that possible? That is absolutely amazing. It's like, oh, just add, what is it, add async to a thing. And then just like, and then just, it was all there. And it wasn't just magic that, oh, there's some thing. It's like, no, no, you can just, in the debugger, you could debug it and you could work out, well, why isn't this continuation being called in the way that I'm expecting it to? And you could just
Yeah.
is a great way to understand like, why is, you know, how, how should you make an async method? And this is clearly you, you know, Apple has come up with this macro is the canonical best place to start from. Yeah. And that, that progressive disclosure, I think is one of the things that, that macros are a great example of, and Swift has been trying to do the whole time of, you don't have to know what a macro is. You don't have to understand them to start using them, right? If you just want to pick up Swift data and you're relatively new to the platform, it's
pretty easy to just add app model to your class and understand the behaviors that you get. But then, of course, if you want to dive deep, if you want to make your own, you can still do that. And so just balancing that ease of use with these more sophisticated features is, I think, a trick that's been pulled off time and time again at Swift. Yeah. And I think in the way that sort of extending that into the way that this allows, I imagine, on your side, as the platform developers, with, I think, of the new data flow changes in SwiftUI, or at least
I don't know if they're necessarily changes, but enhancements or sort of straight simplifications that,
In a non-significant amount of time, the last couple of years has been spent debugging issues where it's like, oh, I'm using the wrong... It should have been a state object rather than an observable object, or it should have been a state. A lot of those issues where if you get it right, it's fabulous. But if you get it slightly wrong, then you can have really strange things where either it's never updating or it's updating way more often than you think it should. And it seems like you're able to, because you're controlling both ends of that...
you're able to eliminate a whole host of issues that we're running into currently because we don't, we're not the ones writing the observable class in the same way. We're just, we just add a macro to it and then you can take advantage of the fact that you know how it should behave because you wrote the macro. Yeah.
Yeah, I mean, I think this is one of the things that we've learned over the last few years, both observing how people are using it in the community and using it ourselves more, is the observable integration for observable object was a source of challenge for people doing some adoption. Yes, absolutely. And so it was clearly one of the things that we were most excited about trying to address here. And I think...
Yeah.
object. And you won't end up with extra invalidation for things that didn't actually contribute to this body. Sure. Yeah. That contorted people's data models too. I mean, to handle these sort of performance issues, people would have to break up their data models in unnatural ways just to get the view and validation right, which no one wants to have to do. Yes. And observable. Yeah. Back to our previous statement about like the natural thing to write is the correct thing to write. Like you shouldn't have to contort your data model in order to appease the framework. You should be able to write it the way that it's
most natural. Well, there's a huge benefit too in learning and education of, you know, learning how to code in SwiftUI because, you know, SwiftUI for all of the clean code that we see up front on presentation slides and stuff, some of the concepts there are very advanced. And for a beginner programmer, heck, even for an experienced programmer, a lot of this stuff can be very tricky to get right because there is so much really advanced abstraction and programming concepts going on, you know, below the surface.
And what I like about the new observable system is the little details of... I'll tell you, I'll be honest. I just learned about State Object two weeks ago. And I've been using certain things wrong because I didn't know about that. There's so many little subtle differences in what's the right one of these things to use. So the more you can keep that on your end and the tooling end and let people just write what comes naturally to us...
And we don't even have to know about those differences. The more of that you can do, the better, because not everyone is going to be a super expert in all these little detailed areas of this. Yeah, totally. I mean, we were very excited to write the slides that went from like, here's five things down to here's two, because it seems like a kind of silly slide transition, but it's a big deal. Everyone loves the slides where the things go away. Exactly. Because deleting code is the most satisfying thing for programs. It's very satisfying.
Can you talk a little bit to the backwards compatibility aspect of those kinds of things in terms of one of the things that I found challenging over the years with SwiftUI is it has been something that has evolved.
It is something that, which is wonderful in the sense of it is getting tremendously better as time is moving on, but it is definitely every year there is certainly changes and there are wonderful steps forward, but it sometimes can be difficult then to, if you still are, you know, deploying something back to iOS 14 or 15 or 16. And in terms of with this kind of the new observable system and these kinds of things, can you talk a bit to kind of what we should expect there and sort of our philosophy as we're adopting these new things? Yeah.
Look, it's been a long-running philosophy that we have an SDK and we have a set of APIs and you deploy them. And totally get that does mean that when you go to back deploy, the new things that we just introduced might require a little while before you can use them. But I think there's a few things there. One, the adoption rate of this stuff in our community and, you know...
the population of iOS users is incredibly fast. So, you know, people can start using these things pretty quickly without, you know, losing much deployment audience. Right. I think we just published 81% of adoption for iOS 16. And then 90% if you look at devices that were introduced in the last four years, right? So, you know, users are aggressively adopting the latest. And so...
I think developers, I certainly understand the desire to maintain sort of this compatibility that where you're kind of climbing the exponential curve of how old can I go? But I'm not sure that you buy that much by going back, say, three years. But that's probably a hot debate in the developer community as to what to set that min-deploy target to. No, you're pretty much right. It's mostly like our bosses tell us you have to support iOS 9 or whatever, but we want to push it to 17. That's...
That's mostly, I think, what we mostly hear. I think for the .00000001% of people out there with iOS 9, it's probably, they appreciate it. So one difference, though, with back compatibility, obviously some new library functions are going to be 17...
and up only. But is it safe to assume that macros are more of a tooling version issue and that you can use macros to generate code that works on older versions? Yeah, so I mean it does depend a little on what the macro generates, obviously. But if a macro is going to generate something that did exist before, you can write a macro that supports back deployment. It's just that what you generate must obviously be available on the target.
Sure, but that is because it's being integrated so deeply into the actual compilation process that it's not an iOS feature so much as it is a toolchain feature. Like if you do the add async thing, anywhere that would support Swift async should be able to then run that code and it would work just as you would expect. Yeah, the macros themselves are defined in Swift and they're written in Swift and they run at the Swift compilation time and then generate new code.
And so they basically can transform the code that they're applied to. But yeah, what they generate then is pretty flexible. Like you can do some pretty complicated things in them. Yeah, and it seems, I think that's one of those things that when I saw that, it's like this is, in some ways I'm glad that you did it in that, to taking that approach because it does make that so much an easier story for us with backwards compatibility and those kinds of issues. Because as long as the code that I end up with is the code that I would have written in myself,
and it would have worked if I needed to support iOS 15, then I'm great. It's not a problem. I'm not taking, it's not, you didn't build it into iOS 17. You built it as a tool for us to be more efficient and more correct in our work. Yeah, absolutely. And macros can be defined in packages as well so that they can be shared and deployed with others who want to use your tools as well. Yeah. Yeah,
Yeah, you know, we didn't look to, you know, the C preprocessor for too much inspiration on macros, but that is one of the ones where it's completely on your code. So by the time you actually have that binary, you don't have to worry about compatible. Yeah, and actually to that point, like they're very different than the C preprocessor in a lot of ways. But one key one is that your code has to compile and fully type check
before the macro is applied. So you don't end up in a place where somebody's going to maybe define a macro that results in your code looking super weird and not even syntactically accurate in Swift. It has to be syntactically valid code before the macro is actually expanded, which keeps code looking more natural and standard. And I mean, the fact that macros can generate, it seems like, custom errors and warnings and things is also just...
And fix it. It's genius to be able to integrate into the actual development process itself. It's not just something that is being used and then you write it and then it only happens in compilation. It can be helping you while you're writing it. If you're using the macro wrong, it can tell you, hey, it seems like you're using this wrong, which is amazing. Yeah, absolutely. Yeah, right. Fix it, quick help. These are components of people's APIs, so they have full support for all those features that you would expect. Yeah.
This episode of Under the Radar is brought to you by Indeed. What's a game where no one wins? The waiting game. When it comes to hiring, don't wait for great talent to find you. Find them first with Indeed. When you're hiring, you need Indeed. Indeed is the hiring platform where you can attract, interview, and hire all in one place. Instead of spending hours on multiple job sites searching for candidates with just the right skills, you can use their powerful hiring platform that can help you do it all.
all. Indeed streamlines hiring with powerful tools that find you matched candidates. With Instant Match, over 80% of employers get quality candidates whose resume on Indeed matches their job description the moment they sponsor a job, according to Indeed Data US. Indeed's hiring platform really is great because it matches you with quality candidates instantly.
Even better, Indeed is the only job site where you only pay for applications that meet your must-have requirements, making it an unbelievably powerful hiring platform, delivering four times more hires than all other job sites combined, according to Talent Nest 2019.
Join more than 3 million businesses worldwide that use Indeed to hire great talent fast. Start hiring now with a $75 sponsored job credit to upgrade your job post at Indeed.com slash undertheradar. Offer good for a limited time. Claim your $75 credit now at Indeed.com slash undertheradar. That's Indeed, I-N-D-E-E-D dot com slash undertheradar to support the show by saying you heard about it on this podcast.
podcast. Terms and conditions apply. Need to hire? You need Indeed. Our thanks to Indeed for their support of this show and RelayFM. Swift data. Amazing. First of all, let me be the one to say finally. Also, thank you for Sherlocking the library. I spent the last six months writing. So I'm curious on a lot of the... Obviously, macros were key to making Swift data possible the way it is written. So the timing of it makes sense.
What's the story with Swift data? Should we all start using it now? Is this like a 1.0 that we should kind of wait on? Because obviously it's backed by core data and built upon core data in so many ways. Where do you see it fitting in? Is this like the new default that everyone should be using?
I think it's a really great default. It follows a long line of technologies in this space, core data being the most recent, and builds upon the infrastructure of core data, uses the persistence backend of core data. So the storage to SQL is well-tested and well-used. It's very understood and reliable. So yeah, I think it's a much more natural, swift interface on something that is very well-understood and well-trusted.
What's the what are your guidelines around concurrency with that? I see there's some actor classes for it, but documentation is a little thin right now. How do you see the role of Swift data with managing concurrency?
Yeah, so Swift data is certainly designed to integrate really well with Swift concurrency. If you looked at how core data worked, conceptually a managed object context was an actor and you would enqueue operations on it. Like you could ask it to perform a closure. We kind of inverted that with Swift data and
the the object context is not itself an actor but it is actor bound so if you have a main object context for your views on the main queue uh or the main actor you can you know you've got a set of objects an object graph out of that object context that you can operate on on on the main actor but if you have another actor uh where you're maybe doing some networking or data processing or something you can have another uh separate object context in that actor uh with its own object graph and you
In that isolation domain, you can have a separate graph, mutate it, and save, and they'll all merge on the back end. So one object context per actor, and then you merge them when you save. It seems too like Swift data is just one of these things where it's
It's in the same way that it creates this very natural syntax for an operation that is very common. That it is a very natural thing that you're going to create objects and then you need to get them back later is a very natural thing rather than having to... But it's interesting for me to be doing it totally in Swift that it isn't, like you're saying, it's not an object editor. It's not a database. Like behind the scenes, deep down, there's dark magic turning it into a database. But from my perspective...
this is just Swift. Like I'm just, the fact that it happens to be persistible and perhaps it happens to be able to, you know, come back and be queryable and all the things that are very, you know, like the, the really cool aspects of it functionally. But from the, the developer's perspective, they're just, you know, Swift classes and structs and hot properties and things that I'm working with normally. And it's, you know, the ability to just, you're adding macro to it and a couple of other things in your environment to set it up. And then
then it's persistible. I think making it so native was just such a wonderful aspect of this to me. Even down at the predicates, I don't know if you got a chance to look at that, but the predicates are in Swift now. They're fully type checked. It's quite nice. Yeah, and that kind of thing was where it's by making it then, you know, the tooling can help me make sure that I'm doing it right, that I'm not in core data. You would sometimes run into the issue where, well, if you misspelled a, you
you know, a column name in your predicate, you wouldn't, you would just get no, oh, well, you get no data back or you get a weird error at runtime or things like that in a way that you would just, you wouldn't know because, well, the schema was defined in a different file than the Objective-C version that was using it. And you're just like, you just hope for the best and eventually it works. But this is like first class, just part of Swift itself. Yeah.
Yeah, and I mean, to the point we talked about earlier, we really wanted it to be natural that what you would have written in Swift normally is what you would write here, and we just give you persistence of it. And just being able to model your types the way you normally would is a really key part of that. And so things that are just natural in Swift, like enums with associated values, you shouldn't have to think about the fact that, okay, there's a database on the back end that I'm trying to write into. It just works. And so yeah, that was really a key part. Another thing in the early days that we spent a lot of time talking about was
kind of a minimal edit distance between an early prototype where you were just doing some in-memory prototyping with maybe some objects in that state and turning it into a persisted object. And so the demo that we did in State of the Union showed going from at state with some default data to an at query
And that's an example of where we were trying to get to, like, what you would have written naturally if you were just prototyping something can be easily transformed with, like, the smallest number of edits into now a truly persisted real thing. Yeah. And I think it's the magics because they're both just...
natural Swift things, the translation between those two things, they aren't, oh, now I'm using a database. I need to write a whole new model layer. I need to do a whole new thing. It's like they're the same as if in your prototyping phase, if you just throw together some structs to hold some example data. Well, those same structs, you just need to annotate in a slightly different way to make sure that they're appropriate to be
stored and they are stored. I think that, that, that, that step, yeah, between it, we don't have to keep rewriting what we're doing based on the context. It's all just the same basic, uh,
Model your domain in Swift using the things you would normally do and then model your UI based on the states that that data projects and you're good to go. Yeah, totally. And if you have relationships between two objects, you probably shouldn't have to learn about foreign keys and everything in order to do that in Swift. It just works. You don't even have to write at relationship. We detect the relationships and it all just happens. So,
There's been a lot of, I don't know, Dave, if you are familiar with the widget system. I have some passing familiarity with widgets. That is definitely something that I have some familiarity with. There's been quite a lot of movement there this year, to put it lightly. One area that I think we're all very excited to see, that frankly I was not expecting, even though a lot of people were, is interactive widgets and
The reason I wasn't expecting this is because the structure of how that's run, where your process is not just continuously running in the background and you're being woken up for timeline updates every so often or whatever...
That didn't seem like it was possible to combine that with the narrativity in any way that we knew it. And what you delivered is this app intent-based system where you can have buttons and things that trigger app intents to presumably wake up the background process of the app or the extension and have it do things. I'm wondering, is the intention here for this to be kind of like real-time interaction when someone is interacting with it? Or is it more kind of like...
set it and forget it. You check off that box and then you go away and the app learns, hopefully within a short amount of time, but is the app expected to respond in real time or is it more just like, we're going to modify the state variable in the UI and kind of async tell the app? Is this meant for real-time interaction? Yeah, it's absolutely meant for real-time interaction. Some of the examples that you saw, like checking off reminders or turning on your lights with HomeKit, I guess maybe you could get away with the reminders one not being real-time, but the HomeKit one, absolutely not. They really are meant...
to be live and interactive and quick to respond. And they do. I don't know if you've tried it yet, but the speed of interaction is pretty great. You check off a reminder and you're going to see the number update and it'll animate out. It's pretty cool. And the animations really make it feel lively in a way that is really just pretty great. One thing that I was a little surprised to hear, but
When I thought about it, it kind of broke my brain. It might make some sense. It seems like you're now encouraging us to create reusable components that fire off app intents as the interaction model and actually use those in our regular app UIs, kind of using the app intent system as almost like an action trigger system. Did I understand that correctly? Yeah.
So you definitely the API that we added to trigger app intents from buttons and toggles is was designed for widgets is the reason we added it so that we can enable this. But it's also available in regular Swift UI apps. So if you already have app intents that perform the actions that you want, that's actually, you know, a lower overhead way then to go set up your UI as well.
And it then will pay potentially dividends in other ways because if you've created your app intent for some action, it can now be available in the shortcuts app so you can set up shortcuts based on it. It can be exposed to Siri. So there's a bunch of value that you get out of wrapping your functionality in an app intent that now makes it available in these different places.
It's not the only way to do it. The regular closure initializers, the button and the binding for toggle are available and great. They're very low friction ways to do stuff. But wrapping it up in an App Intent gives you some extra flexibility too to use it in other ways.
Yeah, and I think with widgets, I mean, obviously, it's like I've been using widgets since they began. It's been a huge part of my life and career at this point. And I think what has been fascinating to me is to watch how there is some, like the architecture of widgets where being able to archive a SwiftUI view in a way that means that my code can exist in a place that is very...
I don't know, very fundamentally important to the device that like I can, my code is running on, you know, on the main home screen of a user's phone and to do that in a way that is safe, reliable, performant. And it seems like it's all coming from that sense of SwiftUI's
you know, sort of declarative architecture that you can archive something that you can do it. And then, yeah, it's a fascinating thing for me is how that then extends to being able to, well, you can send that archive across over to a Mac. You can, in the case of the interactive widgets aspect that you're just updating the archive rather than running my app, you're just, I'll just ask my app for another archive and get it back. And it seems like a really beautiful extension of the, just that the way that you had originally structured it.
to be able to do these kind of operations without having to tell me, oh, we're doing interactive widgets. You have to build this whole new thing in this whole new way. It's just an extension of this existing and initial widget system that we had from the start.
Yeah, I mean, there's a ton of cool stuff we've been able to do with this. The fact that now you can add interactivity. The timelines in widgets give you a flexibility to, without having to rerun your code, have a large amount of updated data throughout the day. So if you have a calendar or something, it can be updating without the extension having to run again. And then, yeah, the fact that we can encapsulate this thing and send it over the network really extends the power of what we can do with this stuff in a pretty cool way.
Yeah, the idea that you can kind of beam your widget state from the iPhone to a Mac without there being a companion app on the Mac installed. That was one of those head-blowing moments for me during the keynote as well. I hope that works as well as I want it to. It's very cool. And the interaction and interactivity and animations all work in that environment too. So if you have your interactive widget and you tap it on the Mac...
Message gets sent back to the phone, operation happens, UI updates, and it's all just seamless. It's very cool. And to the animation point, in terms of it seems like those are animated in the same way that I would expect sort of animations to happen within a SwiftUI app as I was doing it in the sense of it's just you have the value before and the value after and it's diffing the view tree and just...
changing things between it rather than it's not just, oh, you can in say like last year with in live activities, there were a couple of kind of animatable things you could do when you were changing numbers in labels. It's like, no, this is seems the full on we can do
Swift UI animation between different states and it's doing all the things you would logically expect. If you move a control from one corner to the other, well, it'll animate smoothly between those two places. Yeah, we maintain the view identity in the archives so that as you go from archive to archive, we match them up and can do the kinds of transition animations you'd expect where something slides around or scales or any of that. And there's also these content animations, which is sort of what you mentioned from live activities, but they're also very cool where you can do things like
If you have a number that might increment or decrement, like the count of your uncompleted reminders, when it changes, you can have it do this really cool slide-up-down transition animation. There's some really very...
well-designed animations in there. And as someone who spends my entire life working on widget timelines, I got to say just as a thank you to you, to you, to everyone who worked to make the new Xcode previews system for widgets, that is incredible. Like it is like absolutely life-changing for someone who spends my life making widget timelines to now be able to see my timeline as it's going to be rendered, to interact with them, to even animate between those various timeline entries and
like that was one of those things where it is lovely for me to see the, obviously there's enough, you know, sort of widgets are in a lot of places, but they're also in the tools. It isn't just a user facing feature. It is also a developer focus, biggest focus feature to make our life better and to make it easier for us to make good widgets. And,
And so I think, yeah, so somebody was like, just straight up thank you. It's just amazing. We'll let the team know. Yeah, because... That one is huge, right? The new pound preview syntax is for widgets, but for everything else, it's just a much lighter weight way to get into previews, which is super cool. But for the widgets in particular, we really wanted to make it a first class experience in previews because...
It is less convenient than testing an app to test a widget. You have to go put it somewhere. If you want to see the timeline, you have to figure out how to get it to update while you're trying to test it. Being able to just see it splayed out and quickly move between it, I think is going to make previews by far the best way to develop and test widgets. We're pretty excited about what we did there.
Oh, sure. Because I say previews are just a fundamental change, I find, to the philosophy you take as you're developing because it becomes – it's so easy to iterate, to change –
well, what happens if I change this? What happens if I change this? And I can progressively add complexity in a way that is interactive. I know if I made a mistake, it's not something where there's this long build and run cycle that I have to do between every operation. Instead, it is a situation where I can make small changes, see what they do, and then just keep iterating on it. And I feel like that changes the philosophy of how you are as a developer to be able to work collaboratively
sort of incredibly quickly and with that sense of the code isn't getting in your way. It's very much, it's the tooling is encouraging you to write and if you do it the right way, using the, doing things the Swift and SwiftUI way, everything just works. Yeah. And AppKit, AppKit and UIKit. Oh, sure. Yeah, I love that you just slipped that in there. Like, it was like two words. You can also use AppKit. What? Like, what? Yeah.
Well, it's funny because it's actually always been possible to do previews of your UIKit and AppKit content, but I think it wasn't front of mind for people because you would have to have created a UI view or NSVU representable and then set up the Swift UI preview for your UIKit or AppKit content. But it is a great way to develop your UIKit and AppKit views. I mean, if you were debugging your auto layout constraints and trying to change some things...
making a change, building and running, seeing how it worked, is a pretty high overhead way to do that. Being able to just go and edit your constraints and see the results right there is really great. Yeah, it's yet more areas where you've moved what used to be custom configuration files, in this case, Zibs and Xcode, moved from that to a code-focused world in more ways throughout the tooling and everything. I'm a huge fan of that. And I also appreciate that a lot of times when new technologies come out at WWW,
we think, oh, wow, this will be great until we, you know, once we can start requiring it. And that's, for everyone, that's a little bit different as we talked about earlier. But another thing is like, oh, this will be great if I was rewriting my entire app from scratch. But I'm not, right? And I like that with SwiftUI, you've maintained a lot of interop between SwiftUI, UIKit, AppKit, you know, that we don't have to go all in on SwiftUI. And I really appreciate that. And I think
All of us. All of us do. Yeah, I mean, not only have we maintained a lot of Interop, we're continuing to invest in Interop. You may not have seen it yet if you haven't gone deep in it, but this year we added really first-class bridging between environment and trait collections.
So UIKit trait collections were now expanded this year to have support for custom traits so you can define your own. But we also added full bridging between the SwiftUI environment and the UIKit trait collection. So if you have the same trait and environment that map one-to-one, you can connect them together and access the value across...
the boundary on either side through either API and are fully bridged. It's a great way to move data between UIKit and SwiftUI. But like they said in Platform State of the Union, these are the same tools and frameworks and libraries that we use ourselves. There's a lot of code written in AppKit, there's a lot of code written in UIKit, so that interop story is something that we invest in, not just for the developer community, but for ourselves as well, because that's the realistic path to adopting SwiftUI. Cool.
For a lot of folks. Oh, sure. I mean, I think it's one of those things that it makes it easier as a developer to invest our time, energy and effort into SwiftUI and having that be the path that we take forward.
because clearly it's like every platform that Apple makes, SwiftUI is the primary thing and it's kind of amazing. I think at the beginning you talked about where it's like you start the code in your widget and then you put it into your watch app and you put it from your watch app into your main app and it's like now that same thing can go everywhere. And I think there is something that code first and it's even the same code in multiple places first. It's trying to get...
the maximal expressiveness in a particular thing because it can be expressed, it can express itself appropriately on watchOS and will express itself appropriately on iPadOS or anywhere that that's that, you know, you're doing that work for us rather than us having to write our app four times.
We're doing it just the one time, and then you're doing the sort of the hard work on the back end to make that actually something that can work and be appropriate. Right, right. I mean, you know, Mac apps, iPad apps, iPhone apps, they're different, but there's a lot of commonality, you know, and so it's nice to be able to leverage the same APIs where there is commonality. Yeah, and I think it speaks to just, yeah, it's like, I think so much it's the...
I appreciate, you know, sort of getting back to the overall theme of this year of the sense of like, you know, like the best is that the natural way to write something is also the correct and best way is writing.
It's like that natural way is now applies in so many more contexts and applies in the same way that it's nice that the way that you define a widget is the same as it was before. And it's a very natural, natural syntax. Oh, you want to make it interactive? Well, you just add an app intent to the button and then it happens. And I think there is something very powerful in that philosophy that you guys have taken that it seems very like it's easy to get started. It's easy to learn. And then as you get more mature and as sort of develop in your,
developer career, all those skills transform forward with you. That you're not having to, oh, now you're an advanced developer. Then you can take off the training wheels and then you'll use the real thing. It's like, no, no, Swift data is the same thing that you would use in some super complicated thing versus if it's the first time you're ever building a Hello World application and you're just trying to learn how to model anything.
And I think it helps too, you know, for people like us, you know, our audience and the two of us, there's a lot of us who are very small teams, one person, two people, you know, and it helps a lot that,
We are able, as individual developers or as small teams, to make first-class apps that look as good and work as well as apps that are made by giant companies that have thousands of engineers. And a lot of that is due to these factors of pushing more stuff to code, making things more reusable. The surface area that our apps are expected to cover by modern consumers is
is huge. We have all these different platforms. We have all these different areas within each platform that our apps might have some surface area to appear or to integrate. We need these kind of productivity multiplying tools and techniques. And so we very much appreciate that. Yeah. And I think that's probably a good place to wrap up our time. There's a timer flashing letting us know that we are very close to the end. But I just wanted to say thank you so much for joining us and to talk about this. It's a
it's I've been coming like Marco and I both started coming to WGC in 2009 like we've been doing this a long time and this is this year feels very special it feels both in terms of the things that were announced the feeling of all being back together in a way that last year had a slightly tentative feel this year is the opposite this is you know the community is back together people are excited in a way that they can express to you know to each other and I think
it's been a very cool year and it's, you know, it's been, I feel very fortunate to be able to have been part of it. And so it's very exciting. And I, I'm sure, you know, hopefully you guys can now rest and, you know, relax slightly after I'm sure it's been a tremendous amount of effort to, you know, clearly to get it, bring, bring these tools on this event to this level and to this point.
There's nothing like the Monday of DubDub. Sure. It's a great feeling. It is. And thanks for having us. It was great chatting. Yeah, thank you. Yeah, thank you, Josh and Chris. We'll have so much more to talk about. Obviously, this is a big event. We're going to cover Apple Vision Pro and Vision OS and everything else at DubDub in future episodes. So thank you, everybody, for listening. And we'll talk to you in two weeks. Bye.