Filip Růžička

SwiftUI and MVVM: A Match Made in Heaven

SwiftUI and MVVM: A Match Made in Heaven

SwiftUI is a powerful framework for building user interfaces on Apple platforms, and one of the most significant advantages of SwiftUI is that it is a single source of truth for building interfaces across all Apple platforms. With this in mind, it's important to choose the right architecture for your app to ensure that it's easy to maintain, test, and update. In this post, we will discuss two popular architectures for SwiftUI apps: Model-View-ViewModel (MVVM) and The Coordinator Architecture (TCA).

Model-View-ViewModel (MVVM) is a design pattern that separates the data model from the view, allowing for a cleaner and more maintainable codebase. In this architecture, the view model acts as an intermediary between the view and the model, providing the view with the data it needs to display and handling any user interactions. This separation of concerns makes it easier to test and update the user interface without affecting the underlying data. MVVM is a great choice for apps that have a simple or moderately complex data model and user interface.

The Coordinator Architecture (TCA) is another popular architecture for SwiftUI apps. TCA is a pattern that separates the navigation logic from the view, making it easy to test and update the navigation flow of the app. The coordinator is responsible for managing the navigation flow and triggering the appropriate transitions between views. This separation of concerns makes it easy to add new features or update the navigation flow without affecting the rest of the app. TCA is a great choice for apps that have a complex navigation flow or multiple entry points.

In conclusion, both MVVM and TCA are great choices for building SwiftUI apps. MVVM is a good choice for apps that have a simple or moderately complex data model and user interface. TCA is a great choice for apps that have a complex navigation flow or multiple entry points. Ultimately, the choice of architecture depends on the specific requirements of your app and your personal preference.

struct Recipe: Identifiable {
    var id: Int
    var name: String
    var ingredients: [String]
    var instructions: String
}

Next, we'll create our ViewModel:

class RecipeViewModel: ObservableObject {
    @Published var recipes: [Recipe] = []
    @Published var searchText = ""
    
    func fetchRecipes() {
        // Fetch recipes from a remote API
    }
    
    func filteredRecipes() -> [Recipe] {
        if searchText.isEmpty {
            return recipes
        } else {
            return recipes.filter { $0.name.contains(searchText) }
        }
    }
}

The RecipeViewModel class is an ObservableObject, which means it can be observed by the View. It has two Published properties, recipes and searchText, which can be bound to the user interface. The fetchRecipes() method is used to fetch the recipes from a remote API, and the filteredRecipes() method is used to filter the recipes based on the searchText.

Finally, we'll create our View:

struct RecipeList: View {
    @ObservedObject var viewModel = RecipeViewModel()
    
    var body: some View {
        NavigationView {
            VStack {
                SearchBar(text: $viewModel.searchText)
                List(viewModel.filteredRecipes()) { recipe in
                    RecipeCard(recipe: recipe)
                }
            }
        }
    }
}

The RecipeList struct is a SwiftUI View that displays a list of recipes. It has an ObservedObject property, viewModel, which is an instance of the RecipeViewModel class. The body of the View is a NavigationView containing a VStack, which includes a SearchBar and a List of RecipeCard views. The SearchBar is bound to the searchText property of the viewModel, and the List is bound to the filteredRecipes() method of the viewModel.

In this example, the Model and ViewModel are separated, and the View is responsible for displaying the data, allowing for a more maintainable and testable codebase. With MVVM, you can easily test your business logic in isolation from the user interface, and make changes to the user interface without affecting the business logic.

This is just a simple example of how you can use MVVM architecture in your swiftUI app.