I like how Swift Concurrency is taking all the good things from Kotlin Coroutines (context switching behind the scenes, async streams) and doing it in its own flavor.
Great videos, Nick! One small issue with creating tasks inside the view model in order to keep the UI synchronous is that it makes it harder to unit-test it. For instance if updateData() was an async function, all you would need to do in the test is to await and check data property. Otherwise you will probably need to convert the data property to an async sequence and await until it emits a particular value or times out.
Yes, I came here to write this. Every method that has a Task in it is hard to test. Also, as was already mentioned earlier in this series, the View offers this .task modifier that is made for calling async methods. So I think that I personally prefer having my Tasks in the View right now, which can't really be tested anyway.
So excited to watch this, been thinking about architecture a lot recently. Would be keen to see more content from you on architecture/design patterns 🤓
Hi Nick, how can we have a protocol-oriented codebase following the async/await pattern? That would help immensely with unit testing and dependency injection. Thanks so much for the videos and I just joined the discord!
Many thanks for making, publishing, explaining how to implement the MVVM pattern in Swift. Could you do other(s) explaining the edge cases you mention?, Many thanks, best regards
And how it will work if I tap button many times? I have to cancel previous task before? If I will have many functions with different things will I have to do many task variables for this?
Really great video. I went through most of the playlist and it is phantastic, in terms of content and presentation. However, would appreciate your opinion on the MVVM in the light of SwiftData. Functions like @Query are only available in Views, so in order to do a lot of data manipulation in a view model you would have to pass the data you got from the Query into the view model, do some stuff there, and pass the updated data back into the view. To me it looks like Apple is not really supporting the MVVM architecture and wants programmers to do most data manipulation in the view itself. Of course you can still structure the view accordingly, e. g. moving the functions to an extension in order to keep the view clean. What do you think?
My opinion is that most apps should not use SwiftData. It’s a beginner tool that is new and lacks many features that we’ve had in CoreData for years. If you’re using the SwiftData property wrappers, I agree MVVM feels anti-pattern. If you’re using SwiftData, chances are it’s a beginner app and you don’t need much architecture anyway. If you’re using MVVM, then CoreData could be a better solution. However, I would not say that Apple doesn’t support MVVM. Apple never makes comments on architecture, but there are recent examples of them using ViewModels in WWDC videos. Additionally, they created the entire @Observable framework around it 🤙
In a case I want to pass an EnvironmentObject from the view to view model, for example a service that is passed as an environmentObject, what is the correct way to pass that to the vm so only vm does the actions
First the separation of managers and viewmodels is critical. It really cleans up so much code. Not saying never, but I have found .onAppear, .task, and .onDisappear can be problimatic for manager code because a view “appears” and “disappear” more often than you might suspect and enhancements may cause them to fire at the wrong times. .task is sometimes described as onappear with a Task built in. There seems to be some subtle differences After working through the Firebase playlist so much became clear. Pre loading on startup for environment objects, Creating and loading and then injecting observed objects from one level up then reloading on user actions in the view is much more stable and drives down the psychometric complexity and far less business logic in the view.
Strange because when I put the whole class on @MainActor, the main view complains. But if the @MainActor is on the private(set) and on the Task, it doesn't 😢
Hey Nick,
It would be GREAT if you can add a new video showing how to write unit tests for viewModels having async await functions.
You are AWESOME 👏
I like how Swift Concurrency is taking all the good things from Kotlin Coroutines (context switching behind the scenes, async streams) and doing it in its own flavor.
Great videos, Nick! One small issue with creating tasks inside the view model in order to keep the UI synchronous is that it makes it harder to unit-test it. For instance if updateData() was an async function, all you would need to do in the test is to await and check data property. Otherwise you will probably need to convert the data property to an async sequence and await until it emits a particular value or times out.
Yes, I came here to write this. Every method that has a Task in it is hard to test. Also, as was already mentioned earlier in this series, the View offers this .task modifier that is made for calling async methods. So I think that I personally prefer having my Tasks in the View right now, which can't really be tested anyway.
So excited to watch this, been thinking about architecture a lot recently. Would be keen to see more content from you on architecture/design patterns 🤓
THank you Nick for all of your hard work!
Hi Nick, how can we have a protocol-oriented codebase following the async/await pattern? That would help immensely with unit testing and dependency injection. Thanks so much for the videos and I just joined the discord!
You are awwwwesome. Me and my colleagues are always waiting for you to upload new videos. Thanks!!
Thanks Thais 😊
tks for this video! I am going to use it on my project
Many thanks for making, publishing, explaining how to implement the MVVM pattern in Swift. Could you do other(s) explaining the edge cases you mention?, Many thanks, best regards
And how it will work if I tap button many times? I have to cancel previous task before? If I will have many functions with different things will I have to do many task variables for this?
wonderful video, thanks!!
Really great video. I went through most of the playlist and it is phantastic, in terms of content and presentation.
However, would appreciate your opinion on the MVVM in the light of SwiftData. Functions like @Query are only available in Views, so in order to do a lot of data manipulation in a view model you would have to pass the data you got from the Query into the view model, do some stuff there, and pass the updated data back into the view. To me it looks like Apple is not really supporting the MVVM architecture and wants programmers to do most data manipulation in the view itself. Of course you can still structure the view accordingly, e. g. moving the functions to an extension in order to keep the view clean. What do you think?
My opinion is that most apps should not use SwiftData. It’s a beginner tool that is new and lacks many features that we’ve had in CoreData for years.
If you’re using the SwiftData property wrappers, I agree MVVM feels anti-pattern.
If you’re using SwiftData, chances are it’s a beginner app and you don’t need much architecture anyway.
If you’re using MVVM, then CoreData could be a better solution.
However, I would not say that Apple doesn’t support MVVM. Apple never makes comments on architecture, but there are recent examples of them using ViewModels in WWDC videos. Additionally, they created the entire @Observable framework around it 🤙
"This Task is on the MainActor, of course" - I am confused. Does a Task inherit the actor context of the enclosing function?
The best! Thanks!
thanks for wonderful video ... we need more on mvvm pattern please make with realtime api
In a case I want to pass an EnvironmentObject from the view to view model, for example a service that is passed as an environmentObject, what is the correct way to pass that to the vm so only vm does the actions
Thanks Nick
First the separation of managers and viewmodels is critical. It really cleans up so much code.
Not saying never, but I have found .onAppear, .task, and .onDisappear can be problimatic for manager code because a view “appears” and “disappear” more often than you might suspect and enhancements may cause them to fire at the wrong times.
.task is sometimes described as onappear with a Task built in. There seems to be some subtle differences
After working through the Firebase playlist so much became clear.
Pre loading on startup for environment objects, Creating and loading and then injecting observed objects from one level up then reloading on user actions in the view is much more stable and drives down the psychometric complexity and far less business logic in the view.
so confused video
Did you watch the rest of the playlist?
Strange because when I put the whole class on @MainActor, the main view complains. But if the @MainActor is on the private(set) and on the Task, it doesn't 😢