- Видео 49
- Просмотров 60 938
donny wals
Добавлен 19 фев 2009
I love sharing everything I know about Swift, iOS development, and other programming related topics.
Case Let Syntax in Swift Explained
If case let is probably one of those syntax pieces of Swift that we all forget all the time.
In this video, I explain how it's used.
If you prefer reading instead of watching, I have a blog post about if case let right here: www.donnywals.com/if-case-let-in-swift-explained/
In this video, I explain how it's used.
If you prefer reading instead of watching, I have a blog post about if case let right here: www.donnywals.com/if-case-let-in-swift-explained/
Просмотров: 289
Видео
Knowing when to use the require macro in Swift Testing
Просмотров 152День назад
Learn how you can leverage the #require macro in Swift testing to make sure that pieces of state in your code are exactly what you expect at the right times. See how #require is different from #expect, and in which cases each of these macros are a good choice. If you prefer reading the contents of this video in a blog post, you'll find it right here: www.donnywals.com/testing-requirements-with-...
Solving "passing closure as a sending parameter" errors in Swift 6
Просмотров 83714 дней назад
Once you start your migration to Swift 6, you'll run into several hard to read, hard to understand, and hard to solve errors. In this video, we'll explore an error that reads: Passing closure as a 'sending' parameter risks causing data races between code in the current task and concurrent execution of the closure We'll also look at an error about "capturing a non-Sendable value in a Sendable cl...
Asserting state with #expect in Swift Testing
Просмотров 159Месяц назад
Learn how you can ensure that your code is working as expected with the #expect macro in Swift Testing. You'll learn how to evaluate boolean conditions and ensure that your code throws the errors you expect, or that it doesn't throw errors at all. This video is a companion for my blog post on the same topic: www.donnywals.com/asserting-state-with-expect-in-swift-testing/
Improving your test coverage with parameterized testing in Swift
Просмотров 3332 месяца назад
Level up your concurrency skills with my book: practicalswiftconcurrency.com/ Or join one of my workshops: www.donnywals.com/workshops/ Find the blog post for this video here: www.donnywals.com/improving-test-coverage-with-parameterized-tests-in-swift-testing/ Learn how you can leverage parameterized tests in the Swift Testing frameworks to make testing loads of test inputs a breeze. We'll look...
Getting started with Swift Testing
Просмотров 5492 месяца назад
Level up your concurrency skills with my book: practicalswiftconcurrency.com/ Or join one of my workshops: www.donnywals.com/workshops/ Find the blog post for this video here: www.donnywals.com/swift-testing-basics-explained/ Learn how you can get started with the new Swift Testing framework in existing projects as well as new projects. In this video we take a look at the @Test macro and the #e...
Testing completion handler code with Swift Testing
Просмотров 3032 месяца назад
Level up your concurrency skills with my book: practicalswiftconcurrency.com/ Or join one of my workshops: www.donnywals.com/workshops/ Find the blog post for this video here: www.donnywals.com/testing-completion-handler-apis-with-swift-testing/ In this video, I dive into an interesting challenge I faced while updating my Swift Concurrency book, specifically when converting tests from XCTest to...
Dependency Injection for Swift Developers
Просмотров 7772 месяца назад
Welcome back to the channel! In today’s video, we dive deep into the concept of Dependency Injection-a fundamental yet often misunderstood topic. You’ve probably been using dependency injection without even realizing it! Whether you’re creating objects with initializers or leveraging more advanced patterns like service locators, this video will guide you through the pros and cons of each approa...
Toggling the Swift 6 language mode in Xcode
Просмотров 7783 месяца назад
With Xcode 16 you get access to the Swift 6 compiler. This compiler can compile your project in different language "modes". For example, Swift 5 mode which is the default mode for new Xcode projects. Your Swift packages however will use the Swift 5 language mode by default. In this video, we'll explore how you can set the Swift language mode in your projects and packages. This video is a compan...
Animating SF Symbols on iOS 18
Просмотров 4723 месяца назад
This video is a companion for the following blog post: www.donnywals.com/animating-sf-symbols-on-ios-18/ I love SF Symbols. Every year Apple makes them a bit better and we can do a little bit more with them. In this video we take a close look at SF Symbols and animation. Level up your Swift Concurrency skills with my concurrency course: donnyplus.com/p/practical-swift-concurrency-the-video-cour...
What are Optionals in Swift?
Просмотров 4444 месяца назад
This video is a companion for the following blog post: www.donnywals.com/what-are-optionals-in-swift/ Optionals are a powerful tool in Swift that enables us to eliminate a notorious kind of crash related to null pointers and exceptions. By encoding the nullability of a Swift type into your code the compiler can help you make sure that you properly handle the possibility of nil values in your co...
Lazy vars in Swift explained
Просмотров 5335 месяцев назад
What are lazy vars used for? Do we even need them? And how are they used? In this video, you'll learn everything you need to know about lazy vars in Swift! This video is a companion video for www.donnywals.com/what-are-lazy-vars-in-swift/ Level up your Swift Concurrency skills with my concurrency course: donnyplus.com/p/practical-swift-concurrency-the-video-course
Richer previews with Xcode 16 and iOS 18
Просмотров 7015 месяцев назад
Richer previews with Xcode 16 and iOS 18
Adding keys to SwiftUI's environment with Xcode 16 and @Entry
Просмотров 9545 месяцев назад
Adding keys to SwiftUI's environment with Xcode 16 and @Entry
Programmatic Navigation in SwiftUI explained
Просмотров 8 тыс.6 месяцев назад
Programmatic Navigation in SwiftUI explained
How to decide between a Set and an Array in Swift?
Просмотров 3806 месяцев назад
How to decide between a Set and an Array in Swift?
Let's build an app with iOS 18's new sidebar!
Просмотров 2,2 тыс.6 месяцев назад
Let's build an app with iOS 18's new sidebar!
Build a stretchy header with SwiftUI on iOS 18
Просмотров 2,2 тыс.6 месяцев назад
Build a stretchy header with SwiftUI on iOS 18
WWDC 2024 recap - Apple Intelligence and more
Просмотров 4146 месяцев назад
WWDC 2024 recap - Apple Intelligence and more
Swift’s “if” and “switch” expressions explained
Просмотров 2656 месяцев назад
Swift’s “if” and “switch” expressions explained
@preconcurrency usage in swift explained
Просмотров 8767 месяцев назад
@preconcurrency usage in swift explained
Deciding between a computed property and a function in Swift
Просмотров 7457 месяцев назад
Deciding between a computed property and a function in Swift
Avoid App Store Rejection! Add a Privacy manifest to your app today
Просмотров 1,6 тыс.8 месяцев назад
Avoid App Store Rejection! Add a Privacy manifest to your app today
How to use experimental Swift versions and features in Xcode?
Просмотров 3388 месяцев назад
How to use experimental Swift versions and features in Xcode?
Actor Reentrancy in Swift explained
Просмотров 3,5 тыс.8 месяцев назад
Actor Reentrancy in Swift explained
Building an AsyncSequence with AsyncStream.makeStream
Просмотров 6809 месяцев назад
Building an AsyncSequence with AsyncStream.makeStream
Five tips and tricks for exploring a new codebase
Просмотров 3699 месяцев назад
Five tips and tricks for exploring a new codebase
Yeah, I really do not understand why they use assigment (=) rather than a test for equality (==). There must be a good reason, but I really do not like this syntax at all. Unfortunately, I think Swift has become a monster. A plaything for compsci students. It's starting to make C++ look lean.
Imagine what might happen if Apple took a SwiftData style approach to reducing the amount of code needed to support JSON. I'm amazed at how easy Apple has made using a DB with simple plain old swift objects. I wish they would rethink Codable - with macros capability.
Could you _please_ consider turning off the _visible blanks and line breaks_ in your Xcode code, it is distracting from your code samples. Thank you ;-)
That's quite nice actually. Something I've implemented similarly in my own programming language, where you can destructure an enum, in my case the syntax is `:loaded(data) := enum` which can go within if statements, had no idea Swift had something like this, that's really cool.
Fairly, nothing about stack-based navigation in iOS rocks... but it's what we have and NavigationStack is a more flexible and better option than the old way.
good video but font could be bigger.
Noted for the next one 👍🏼 this is the font I normally use on a 14” MBP screen but seems like a couple of points larger won’t hurt
Thanks for the video, these all help a lot to understand what is happening and how to solve it. May I have a question, you said that you typically annotate the view models with the main actor. My question is this the best solution? Do we have other? Or do we have best practice that we can follow? For example if you annotate the view model with my actor everything in the view model will run on the main actor, so when we write and run the unit test everything will run on the main actor, includes the init as well.
At the moment I think main actor annotated view models are your best approach. The Swift team is working on some changes to concurrency that would make it so you wouldn't need that anymore but those are ideas at the moment so there's no timeline on when (and if) these changes will be available in the language. Yes, everything would run on the main actor which is, from an app point of view, where things will run most of the time anyway (you call view model methods from your main thread so those methods run on main too, traditionally). Networking functions etc would run away from the main actor (granted that these are async functions that aren't main actor annotated). In unit tests I'm not sure that would be a problem since usually your heavy / slow work would happen in nonisolated async functions which don't run on the main actor.
For those not watching on a monitor, either zooming or making the font much larger would be helpful. Thanks for your work!
I'll keep that in mind! I'm currently using a 13" MBP to make sure the text is legible (for me). Would you expect a much smaller screen to work? Or is "legible for me" too small for you (which is totally fair, just want to know how much larger we're talking here)
@@DonnyWalsdev I typically watch on an iPad. If you have one, or any tablet, you can get a better direct sense. I would probably try anywhere from 3-5 points from where you are now.
Will do!
Nice video, ty for your work!
Thanks!
Nice to meet a fellow Swift enthusiast!
did you mean to keep fetchUsers as an async func in the end?
Not per se, I noticed it didn’t need to be async while editing but didn’t want to re-record the whole segment so I decided to let it be; it doesn’t impact the problem / the solution
Come on Donny! Async funcs should not even be in model classes or even in classes in general. Change Networking to be a struct. Call its async func and set the result on the model (from the outside).
Why shouldn’t they be in classes in general? And why wouldn’t they be in a view model? I think a view model is a good place for async functions since they’re the glue between your models, data layer, and view. Also this isn’t an architecture video. It’s about solving a compiler error/warning…
@@DonnyWalsdev you wouldn't have the compiler error if it was architected the way Swift intends. You need to use the View struct as the view model (Which SwiftUI will use to drive the actual UI objects), use .task for async/await, put the async func anywhere except in a class (depending on what isolation you want). Try: .task { model.users = await Network.fetchUsers() // or use network value from Environment for DI }
Sure, but the reality of the matter is that not all codebases will, should, or can follow this “view is the view model” approach. Furthermore, this specific scenario would be solved but other scenarios would still run into the same compiler error. Take the view out of the equation and do some work on a moderately complex data layer and you’ll run into this error eventually unless you managed to get everything right from the get-go. Which is unlikely if you’re migrating your existing codebase… As I said at the start of the video, the example is heavily simplified to demonstrate a compiler error and explain why the error is there. The intent isn’t to educate on something as opinionated as app architecture
Second this. Models should be loaded by utility/usecase/factory classes, models should be structs.
What about the setupWithError and tearDownWithError that we were using in XCTests?
We don't have equivalents for that, I think you'd have to call your own setup and teardowns from within a throwing test for example if you require that kind of behavior
What
Just spent half of the day to find a solution. I hate videos, more prefer articles and it costs me 4 hours. Thanks for sharing this!
I can imagine! That's why every video I create has a blog post companion. If you're ever on a video of mine, go to the description and you'll find a link to the corresponding blog post :)
I'm still using geometry in background Color to get offset, which is the only way I tested with acceptable frequency.
I’d love for you to talk about test performance compared to XCTTests.
Which performance characteristics do you have in mind? Overall time to run the suite from compilation or just one aspect of it?
@ run times, yes. When it was first in beta I read about people doing performance tests and it was significantly slower than XCTests.
Interesting, I'll definitely see if I can do a comparison video some day; I've mostly been exploring smaller scale test suites so for the time being I don't think I can say anything of use about performance
would love if you included the repo in these videos
That's a good suggestion; there often isn't a repo/sample project but making one shouldn't take too long 😁
Great description and clarity. 👍
Thank you 😁
Thank you for the great explanation. Another example that Swift concurrency should be used sparingly and designed properly, supplied with comment to explain "what is going on" without the believes that "this is just amazing and compiler will solve everything". By the way: "Doing one thing at a time but not atomically" should be printed on a t-shirt :) I am wondering what if an actor contain just private cache, async getter to read from the cache and sync setter to write to the cahe, will it behave as an atomic storage?
What's preventing you from just using the view model factory approach, and make that factory an environment object? Then any view that needs to instantiate another can just refer to factory from its environment
Nothing, it’d be just another flavor of passing a factory around
I think this throws some warning when swift 6 and complete modes enabled. I was hoping for something compatible with swift 6
Neither DI approach is incompatible with Swift, what kinds of warnings do you get?
@@DonnyWalsdev Static property 'current' is not concurrency-safe because it is nonisolated global shared mutable state; this is an error in Swift 6 language mode.
@@Avolua ah I see, so that’s entirely unrelated to how you do DI. The compiler is complaining about that property being mutable without any means to ensure data race safety. Making current a let should work, or converting whatever holds that property to an actor might work too. It’s a bit of an annoying error that one because sometimes fixing it will mean you’ll have to move away from static vars (or marking those vars as nonisolated(unsafe))
There is something weird with the audio processing
Yeah I’m not exactly sure what got messed up in processing. The initial upload I had was completely out of sync. This one’s much better in terms of syncing but there’s still something off and I have no idea what it is exactly 😅
I definitely prefer the service locator pattern. Sure you can get a crash if you forget a dependency, but that’s something that you should be picking up during development.
You have a talent for explaining complex concepts clearly
Thank you!
You can also set the Swift language level at the package level, if you want to all your module targets to be in a specific Swift version
Just a quick note: the "block" declaration is not needed if you're just creating the object without doing anything else with it. This would work too: lazy var urlSession = URLSession(configuration: .default, delegate: self, delegateQueue: nil)
You can also just use an array for the path and use an enum for the value type. Then you can use a switch in the navigationDestination, which gives the benefit of having multiple detail views for the same model, and you'll get an error if you try to push an optional or something else that isn't listed in the enum.
❤
Thanks for this. Very helpful. I gotta say that Swift has become a nightmare. It was supposed to be a clear, expressive language. Instead, it's become a plaything for comp-sci grads. Feature creep has made it a kitchen sink of a language, which rivals (and indeed surpasses) C++ for complexity and verbosity. It's hard to imagine explaining half of Swift's keywords to a new Swift developer.
Thank you for this ray of light into Swift 6 obscurity
Helpfull.
Really good example, thank you! I learned a lot and think more in this new async/await way now instead of thinking in queues 😁
This doesn't show navigating forwards & backwards to any point in the path. For example: Root -> Dest1 -> Dest2 -> Dest3 -> Dest4 then jump to Dest2 then jump to Root then jump to Dest4, etc.
With a plain navigation path you wouldn't really be able to achieve that. Luckily, you can also use an array as your navigation path. When doing that, you could easily remove the last 'n' entries to pop back to any place. Going back and then forward again isn't possible because NavigationStack always presents the last item in your path. So if you want to go back, you have to drop the items that came after the place you wanted to go to.
Hi Sir first I would like to thanks u for help some tutorial Video But can I request Video about How to login with Gmail in Firebase ? I can find the the resource
I avoided actors at the beginning because they were repentant in ways that broke my mental model. After watching apple’s concurrency video with the islands several times the phrase that clicked was that the serialization mechanism was tasks. So, rather than doing complex threading models or queuing work to run in the background I just create tasks from the UI and call actor methods for background work. This usage reduces the reentrancy issues as the control flow is in single tasks. If I need to spawn long running background tasks (detached) this will again raise the reentrancy issues.
Do I need this even when my app isn't asking users to put in any of their information ?
Yes. If your app leverages UserDefaults to store preferences, or if you're interacting with the filesystem you'll need to provide a privacy manifest
Great explanation and good catch about Actor reentrancy.
superb 👌👏
Thanks Donny for the clear and detailed explanation. Optionals surely are a very handy and safe feature of Swift.
Hey danni. I have a question for you. Let say in iOS 18, new Xcode 16, every view is already annotated with the @MainActor. Furthermore, let’s say I have a certain function, called func sortArray() async. Now, since this functino is inside a view, that is annotated with a main actor, but it is marked as async, it will block the main thread. I tested it in SwiftUI. Inside this sortArray() async, i have var array = Array(repeating: 2, count: 30_000_000); array.sort(). And let’s say that this function is triggered by a certain button press. As soon as i press this button, the UI totally freezes, and does not respond until the array sort operation finishes. However, as soon as i mark this async function as non isolated, then everything works fine, and the UI responds, while another thread is sorting this array. Why does this happen? You said int the video that marking a function as await does not freeze the UI. I don’t understand it conceptually
Hey! Thanks for your question. So the await itself isn't why your function blocked the main actor. It's because the thing you were awaiting itself runs on the main actor that your UI freezes. That's also why marking the function as nonisolated fixes your problem. Even though you're awaiting the nonisolated function from the main actor, the main actor can do other stuff (like keeping your UI responsive) while it waits for the nonisolated async function to come back. In other words, while the await does not block the main actor, the thing your waiting for might.
To your last point about the environment. Prior to iOS 17 we had @EnviornmentObject which had bindings With iOS 17, there is a new environment property wrapper that does not take an environment key. I believe it also has bindings. So you can do something like: MyView() .environment(myObservable) And then in your view: @Environment var myObservable: MyObservable This does have the same downside as EnvironmentObject, as in, there is no default value. So your app will crash if you forget to inject the value in.
I would like to have a sidebar for iOS rather than tabs. Is that possible? They have this in the Substack app, for example: you can slide from the side of the screen to reveal the sidebar, and can also slide it away again.
Not with the built in navigation components. You'd have to build that from scratch
Thanks for the explanation Donny. It's funny, until now i was only using lazy for when i needed to show the user an alert on my controllers, and i was creating them as lazy var alert = someAlert(), with the thought process that those alerts might never show so why bother creating them when the view is shown if they won't be triggered.
Ok but how do you make a view to be presented in full screen mode by using the navigation stack and the path thing ?
Do you mean as an overlay? Or pushed on the navigation stack except the top bar is hidden? Neither relate to the path to be honest since the path just describes which models are in the stack of presented views. Hiding bars should be possible with the `navigationBarHidden` view modifier. If you're looking for an overlay, you'd use the fullScreenCover view modifier. This can't be captured in a navigation stack's path because navigation stack is just a list of views presented in a navigation stack; not including any overlays that you have presented on top of your NavigationStack
❤ The content, keep it up!!