КОМЕНТАРІ
@alexandr8328
@alexandr8328 2 дні тому
Hello! When is your Swift Concurrency course released? It says it is still in progress. Thx
@nigelgee3576
@nigelgee3576 2 дні тому
I know that you are using person name as an example code. But it should said that when dealing with with names that should use PersonNameComponentsFormatter as this will put the correct format for user locale
@srzurka
@srzurka 2 дні тому
Thanks for the video. I concur. I would only add that, computed properties feel Swifty to me so I start with a bias towards using them, then change to a function when there's one of the situations that you've identified. (needs arguments, it's not lightweight, potential side-effects, etc)
@user-qg8nc5bk4p
@user-qg8nc5bk4p 2 дні тому
Sound became better :) Could you please share your thoughts on usage of extensions, e.g. extending models with some methods, formatting methods etc. When an object that does something is better than extension of some model that handles the model certain way and returns the data I need, the only think that comes to my mind is inability to use DI in extension, so testability is limited for these functionality
@tiagoalexbastos
@tiagoalexbastos 3 дні тому
your videos are so good man, top tier content! Keep it up :)
@DonnyWalsdev
@DonnyWalsdev 3 дні тому
Thanks!!!
@nigelgee3576
@nigelgee3576 7 днів тому
Nice generator. I have already added it to my new project so I do not forget it. Is it required for TestFlight?
@DonnyWalsdev
@DonnyWalsdev 6 днів тому
Not required for TestFlight but I’d recommend just adding it anyway :)
@venuvenu2719
@venuvenu2719 7 днів тому
Awesome, Is the required reasons API, the only thing that needs to be added? What about privacy nutrition labels? Let's say, my app uses email id info and Username. What do I do here?
@DonnyWalsdev
@DonnyWalsdev 6 днів тому
You should be adding them all. However, Apple will only reject you for not declaring required reason APIs.
@jairoalexanderlaurenteceli9966
@jairoalexanderlaurenteceli9966 11 днів тому
Excelente video, muchas gracias por compartir información valiosa!!✌✌
@DonnyWalsdev
@DonnyWalsdev 8 днів тому
¡Gracias! Me alegro que te guste el vídeo
@victorriurean
@victorriurean 16 днів тому
🔥
@filmaniac1984
@filmaniac1984 17 днів тому
Thanks @DonnyWalsdev! Great example and well explained.
@roym27
@roym27 23 дні тому
I had to stop watching because of the background music - it’s not great when you’re narrating as I was unable to focus on what you were saying.
@DonnyWalsdev
@DonnyWalsdev 22 дні тому
I'll probably do a re-record of this video at some point without the bg music. It's a shame that it's not possible to "update" a video without a full reupload
@srinivasanmunna
@srinivasanmunna 25 днів тому
This is a great one. I was actually expecting to see another dictionary variable that keeps track of running tasks. But the enum with associated type looks so much better.
@DonnyWalsdev
@DonnyWalsdev 25 днів тому
Thanks!
@JumpingCow
@JumpingCow 25 днів тому
Subtle and complex! Thank you.
@0xifarouk
@0xifarouk 26 днів тому
This is amazing, thank you for the explanation 🙏🏻 Can we have a video on task cancellation please?
@DonnyWalsdev
@DonnyWalsdev 26 днів тому
Noted!
@bobdel
@bobdel 28 днів тому
This video is very helpful. I am still confused by the body property. As I understand it, Body is annotated via a protocol to run on MainActor. Is this correct: a view such as the one in your example that does not have a @MainActor annotation, but the function is called from a task modifier inside the Body will run on the MainActor.
@DonnyWalsdev
@DonnyWalsdev 26 днів тому
It's the opposite, unless the function definition itself has a @Mainactor annotation (or in other words, is isolated to the main actor) it doesn't matter where you call it from. The function itself decides where it runs and if it's not isolated to the main actor explicitly it will run in the background even if it was called from a main actor isolated spot
@muncho404
@muncho404 Місяць тому
the title was enough to trigger my anxiety😅
@jyotinkarpandey
@jyotinkarpandey Місяць тому
Can we have a sample project link ?
@DonnyWalsdev
@DonnyWalsdev 26 днів тому
Hey! So sorry, I don't have a (publicly available) sample project available for this.
@victorriurean
@victorriurean Місяць тому
@weeee733
@weeee733 Місяць тому
Thanks for the tip! Also these closures make use of withContinuation methods)
@loganblevins8633
@loganblevins8633 Місяць тому
Nice video! Why not make a smaller protocol only giving the needed capability and then make the other protocol conform to the smaller if needed?
@DonnyWalsdev
@DonnyWalsdev Місяць тому
You'd end up with loads of small protocols that are composed into larger ones when needed. This can certainly help with scoping and mocking, but at the same time having so many protocols can be quite unwieldy; especially when an object needs to have a composition of parts of protocols and you end up having to break things down even further. Of course, it might make more sense for some codebases then others. This is just one tool in your toolbelt for injecting and composing dependencies
@priceringo1756
@priceringo1756 Місяць тому
Thank for such great, simple but not trivial, examples!
@user-jz8op2dc4e
@user-jz8op2dc4e Місяць тому
Why can you input content in the canvas preview? How do I set it up?
@DonnyWalsdev
@DonnyWalsdev 26 днів тому
You can start "playing" the canvas from the previews UI and that should make it interactive
@indiekiduk
@indiekiduk Місяць тому
I think makeStream is an anti-pattern because I ran into issues when using like cancellation not working. Once I redesigned my async code and made AsyncStream own the object that yields values all my problems were solved!
@DonnyWalsdev
@DonnyWalsdev Місяць тому
Any chance you have a gist that would demonstrate the issues you've had? The tests I ran involved moving from the older AsyncStream init to makeStream and I didn't see these issues.
@indiekiduk
@indiekiduk Місяць тому
@@DonnyWalsdev ok I'm trying to work on that. I noticed you had onTermination = { [weak self] that must have been to work around the retain cycle issue.
@indiekiduk
@indiekiduk Місяць тому
I've been investigating this all day and I think makeStream is fine. By using a weak var in the parent object and using onTerminate to capture a strong reference to the stream's object I can make cancellation deinit the stream's object properly. My test harness has a task group with 2 tasks that call the same stream property on its containing object (to make sure the first stream is cancelled). I can only have one stream working at a time despite the object's stream property being a computed var that returns a new stream, so I wanted it to also cancel a previous stream.
@w0mblemania
@w0mblemania Місяць тому
Thanks for this.
@syakhiskk
@syakhiskk Місяць тому
Earned a sub! This feels like talking to a coworker instead of watching a youtube video. THANKS!
@victorriurean
@victorriurean Місяць тому
🔥
@andresraigoza2082
@andresraigoza2082 Місяць тому
I found very useful the idea of thinking that @State is telling SwiftUI who owns that object. I'll never forget that, thank you so much!
@Hgvpuncher
@Hgvpuncher Місяць тому
tickets are damn expensive for stuff that you find for free on UKposts...
@victorriurean
@victorriurean Місяць тому
@victorriurean
@victorriurean Місяць тому
@victorriurean
@victorriurean Місяць тому
@w0mblemania
@w0mblemania 2 місяці тому
This was very useful. Thanks.
@DonnyWalsdev
@DonnyWalsdev 2 місяці тому
Thank you!
@NicholasGJeria
@NicholasGJeria 2 місяці тому
Love these videos, keep them coming.
@DonnyWalsdev
@DonnyWalsdev 2 місяці тому
Thank you 😁
@chovuse
@chovuse 2 місяці тому
Your style of tutorial makes it more easier to understand Swift coding. Thanks a Lot !
@DonnyWalsdev
@DonnyWalsdev 2 місяці тому
Thanks! Happy to hear that
@venugopalreddy6618
@venugopalreddy6618 2 місяці тому
would love to see concurrency playlist since you are the trusted person in dev community to learn hard topics .
@DonnyWalsdev
@DonnyWalsdev 2 місяці тому
Once I’ve got a bunch of videos up I’ll start grouping them 😁 unlikely I’ll do a comprehensive concurrency course on UKposts since I’m working on having one for sale but I’ll certainly be uploading videos about concurrency
@user-qg8nc5bk4p
@user-qg8nc5bk4p 2 місяці тому
Donny, how can I donate for a new mic :D. As a non-native speaker I need to be very concentrated on your voice to get the understanting.
@DonnyWalsdev
@DonnyWalsdev 2 місяці тому
I don’t think the problem is the mic 😂 I need to work on some of the room acoustics most likely. Currently working on getting some stuff up on the walls and all that
@user-qg8nc5bk4p
@user-qg8nc5bk4p 2 місяці тому
@@DonnyWalsdev It can be the case, I feel a huge echo as well
@_marlon
@_marlon 2 місяці тому
Thanks for the video. Looking forward to more
@AryamanSharda
@AryamanSharda 2 місяці тому
Awesome, really well explained!
@DonnyWalsdev
@DonnyWalsdev 2 місяці тому
Thank you!
@aalecaar
@aalecaar 2 місяці тому
Thank you so much for this video, Donny! I have a question. You said we should use @State if the view owns the @Observable object. However, the following code works perfectly fine, even tough it was not marked with @State: @Observable class MyCounter { var count = 0 } struct ContentView: View { private let counter = MyCounter() var body: some View { VStack { Button(action: { counter.count += 1 }, label: { Text("Increment") }) Text("The counter is \(counter.count)") } } } You gave a great and clear explanation about the fact that we use @State if the object is within a view that is itself a subview, and we want to persist its value if the parent view updates. But let’s suppose we are sure the view from the example above won’t be a nested view. We also know that this view owns the object. But given the fact that everything works normally without using @State, is there really a good reason to use it besides the case when the object is in a subview and we don’t want to lose its value if a parent view updates? And thank you again for your video, it helps a lot.
@DonnyWalsdev
@DonnyWalsdev 2 місяці тому
Thanks for watching! Yes, the good reason here IMO is semantics. Using @Stare will clearly mark the ownership and intent and will help prevent problems in the future if your view does get reinitialized because something changed over time. You’re absolutely right that your example will work if you know the view never gets reinitialized but we should always assume that our views might need to be reinitialized and make sure that our code handles that correctly
@aalecaar
@aalecaar 2 місяці тому
@@DonnyWalsdev Semantics makes perfect sense. Seems like a good practice to follow. It's like the same reason why you make private the things that don't need to be exposed. I appreciate your time and patience:)
@alperenunal3975
@alperenunal3975 2 місяці тому
Hey, nice video 🎉 should i use @observationIgnored property wrapper for non tracked properties in observable macro object ? Is observable macro handles itself ?
@DonnyWalsdev
@DonnyWalsdev 2 місяці тому
You only need ObservationIgnored if you want to be able to use a property in a view and assign values to it without having the view redraw. If no view uses the property at all then the views won’t update when you assign to a property that isn’t ObservationIgnored
@JosephHeck
@JosephHeck 2 місяці тому
Lovely video overview, although your use of "we" and "you" when describing ownership and what's acting on what in comparing the differences was a bit confusing in places. I'm not yet using @Observable myself, more because of the brutal hit to compile time with macros, but I also want a shared observation publisher setup in a couple of places, which (as you mentioned near the end) Observable doesn't have anything to help with.
@DonnyWalsdev
@DonnyWalsdev 2 місяці тому
Thanks! Would you say that either we or you works better, and is there one that would be best? Or do you feel like I mixed them up in a confusing way but using both in a video is okay?
@JosephHeck
@JosephHeck 2 місяці тому
@@DonnyWalsdev I'd suggest not using either - that's what I found confusing. You started with 'you', talking about ownership and @State and how that transfers things, and clarified it a bit later that the view "owned" that variable. It would have been more clear if you started off with "your code" owning that, instead of "you" and then switched to clarify that with @state, the view "owns" the reference and manages its lifecycle. That's one of the key differences in the new semi-defunct ObservableObject vs StateObject - you touch on it well with the newest Observation bits, but it was just confusing getting there.
@DonnyWalsdev
@DonnyWalsdev 2 місяці тому
@@JosephHeckThanks! That makes a lot of sense :) I appreciate that you took the time to explain what you meant, I'll pay attention to that going forward!
@nikandrii
@nikandrii 2 місяці тому
I wonder if this is working for you now. I'm getting the error "Return from initializer without initializing all stored properties" if I don't set movie in required init(from:)
@larschristiansen3136
@larschristiansen3136 2 місяці тому
Thank you for this video. The reason why an object can sometimes be a let and not a var has puzzled me, but thanks to your video I now understand why.
@DonnyWalsdev
@DonnyWalsdev 2 місяці тому
Thanks! So happy the video was able to clear this up. I think it's pretty much one of the major things people trip over with the new macro
@alperenunal3975
@alperenunal3975 2 місяці тому
Btw what’s your xcode theme ? Looks very cool :)
@DonnyWalsdev
@DonnyWalsdev 2 місяці тому
It's "Material theme Ocean high contrast" in VS code
@alperenunal3975
@alperenunal3975 2 місяці тому
If we are using @observable macro on our viewmodel, should we use @mainactor at the same time ?
@DonnyWalsdev
@DonnyWalsdev 2 місяці тому
I would advice that you do on the view, SwiftUI views aren’t main actor isolated by default
@alperenunal3975
@alperenunal3975 2 місяці тому
@@DonnyWalsdev so we should mark View as a main actor ?
@DonnyWalsdev
@DonnyWalsdev 2 місяці тому
@@alperenunal3975IMO, yes that would be a good idea. It's honestly a little surprising to me that Apple doesn't enforce this
@alperenunal3975
@alperenunal3975 2 місяці тому
@@DonnyWalsdev oh, I got it. Thanks for explanation :)
@priceringo1756
@priceringo1756 2 місяці тому
That is why Apple will be pairing the new typed throws with the ErrorHandlerBuilder DSL. With the @ErrorHandlerBuilder decoration in our catch block we ... just kidding.
@DonnyWalsdev
@DonnyWalsdev 2 місяці тому
Not going to lie, I almost googled ErrorHandlerBuilder 😅
@pmatar
@pmatar 2 місяці тому
private var imageUrl: String? { didSet { dowloadImage() } } func setImage(_ imageUrl: String?, placeholder: UIImage?) { self.image = placeholder self.imageUrl = imageUrl } private func dowloadImage() { guard let imageUrl else { return } Task { @MainActor in do { let loadedImage = try await ImageLoader.shared.downloadImage(from: imageUrl) if imageUrl == self.imageUrl { image = loadedImage } } catch { debugPrint(error) } } } That’s the example of what I mean
@DonnyWalsdev
@DonnyWalsdev 2 місяці тому
This would work perfectly fine. Your task is run on the main thread which means the assignment you do at the end is on the main actor
@pmatar
@pmatar 2 місяці тому
@@DonnyWalsdev but won’t the download will also happen on the main thread, instead of global/background?
@DonnyWalsdev
@DonnyWalsdev 2 місяці тому
@@pmatar no, because the download function itself most likely is defined non isolated. If not, you can be certain that URLSession’s networking is non isolated. So that code run on the global executor. While you await, the main thread is free to work on other stuff because an await doesn’t block; it frees the actor up for other work
@pmatar
@pmatar 2 місяці тому
Great video, thanks for sharing! And what about the assigning of the result of async func to UI-related piece? How exactly it works and should we care about main thread the same way as with gcd?
@DonnyWalsdev
@DonnyWalsdev 2 місяці тому
Yes you should make sure you assign on the main actor. The easiest way is to make sure that the property you’re assigning too is main actor annotated. That way you’ll never forget because all access to the property will be isolated to the main actor. Alternatively you can use MainActor.run to run a piece of code on the main actor
@pmatar
@pmatar 2 місяці тому
@@DonnyWalsdev oh I see what you mean. Thank you for your response!
@FloWritesCode
@FloWritesCode 2 місяці тому
This is an interesting topic, thanks a ton for sharing!
@qkrotor
@qkrotor 2 місяці тому
Nicely explained. I would say the music is a little distracting and doesn't add anything IMO.
@DonnyWalsdev
@DonnyWalsdev 2 місяці тому
Thanks! i do like to have some sound in the background instead of pure silence so in my latest video I brought the volume down by a lot. It's an ongoing experiment for the moment