
Explore how SwiftUI's declarative paradigm challenged traditional mvvm, and trace how navigation, environment values and environment objects sharing shape modern SwiftUI apps with global state.
Explore advanced UI architecture in SwiftUI, comparing MVVM, container pattern, and MVT pattern, with a focus on validation, global navigation, error display, and targeted testing.
Explore the presentation model and MVVM origins, tracing how early binding between view and view model evolved from Windows Forms to WPF, and how two-way binding simplifies synchronization.
Master the MVVM design pattern by separating the model as domain with business logic, the view as the user interface, and the viewmodel as a data provider for the view.
Explore the limitations of MVVM in SwiftUI and how a single observable object or aggregate models can replace multiple view models, using environment value and bounded contexts.
Take a practical tour of a SwiftUI MVVM app that fetches coffee orders via an HTTP client and navigates a list to a detail and add screen, exploring dependency management.
Remove view models and access a shared HTTP client directly from views via a custom environment value, enabling simple, server-driven order loading with a reusable service.
Move from view models to the environment HTTP client to post orders. Encode to JSON and push results via closures or bindings, then preview the aggregate model pattern for state.
Learn how to replace per-screen view models with a single observable coffee store that manages the app's global state, using environment injection to load and place orders within bounded contexts.
Explore bounded context in a domain-driven SwiftUI architecture, from a food truck model to catalog and order stores connected by a shared network layer.
Split a coffee store app into ordering and employee management stores using bounded context and domain driven design, with environment sharing as the source of truth.
Examine bounded contexts such as patient management and medical records management, and how aggregate roots, data stores, and a network layer for views enable cross-context communication.
Examine nested observables in a SwiftUI expense tracker, showing how nested observable objects affect UI updates and how iOS 17's observable macro simplifies change notifications.
Discover how to fix nested observables in SwiftUI by composing small views that observe an observable object with published properties, and applying the observable macro in iOS 17.
Explore how bounded contexts like medical record management, patient management, and appointments communicate, using HTTP clients, stores, and environment injections to coordinate data across contexts.
Explore how SwiftUI views are declarations rather than renderers, and how they map to UIKit components like CG drawing view, collection view, and UI switch, with debugging insights.
SwiftUI views are actually view models that take data from the model and bind it to the view, using state, binding, environment values, and fetch requests.
Explore how SwiftUI tracks dependencies and rerenders views, contrasting it with React’s rendering model, and learn how dependencies trigger reevaluation of the view.
Explain the screen versus view distinction in SwiftUI, using a container pattern where screens fetch data and pass it to reusable views. Use clear naming to improve organization and reusability.
Group view events in SwiftUI by replacing separate closures with a movie cell events enum, improving reusability and delegating actions to the content view and movie store.
Implement simple validation on a SwiftUI login screen by checking username and password, disable the login button until the form is valid, and use string extensions.
Refactor a SwiftUI driver license form by extracting state into a form model, binding fields, validating SSN format, and displaying errors via a validation summary view.
Learn to replace string arrays with localized error handling in a SwiftUI form, using a localized error enum, error descriptions, and localization files to support multiple languages.
Display login errors with an error wrapper that adds guidance. Present the error via a sheet or overlay and reuse an error view.
Create a global error handling system in SwiftUI by introducing a show error environment key and error wrapper, enabling sheets, modals, and overlays to display sample errors with guidance.
Display errors globally with overlays in SwiftUI; learn to unwrap the error wrapper, bind to an error view, and auto dismiss after two seconds using a task sleep.
Display errors globally in SwiftUI by wrapping content with a custom error modifier, using overlays, bindings, and environment values across sheets and detail views.
Navigate SwiftUI with navigation links, stacks, and destinations, mastering programmatic routing and enum-based and value-based navigation. Compare simple static links to destination-driven patterns for scalable apps.
Learn programmatic navigation in SwiftUI by using a navigation path with a typed, hashable enum of routes to drive transitions across movie, login, and review screens.
Expose a global router as an observable object and inject it into the environment to enable routes across all views, with path-based navigation, previews, and unwinding.
Explore a SwiftUI-inspired, environment-based global navigation pattern using a custom navigate environment value, supporting push and unwind navigation for dynamic, programmatic routing.
Explore programmatic navigation in SwiftUI tab views by giving each tab its own navigation stack with an observable router injected into the environment, enabling dynamic routes and destinations.
Master test driven development by writing a failing test (red), making it pass (green), then refactor without new tests, and balance unit, integration, and end-to-end tests.
Identify why tests often validate frameworks rather than domain logic. Learn to write domain tests for a budget app using Swift data, exploring in-memory versus persistent storage and duplicate-name rules.
Learn to test domain logic in SwiftData by ensuring saving budgets with duplicate names throws a duplicate name error using a save function and budget exists check via fetch descriptor.
Write tests to compute budget expenses total, model expenses with a one to many relationship, and implement spent and remaining calculations, while refactoring to remove duplication.
Refactor both production code and tests by centralizing container and context initialization in a per-test setup, using teardown for cleanup, and validating domain logic in SwiftData.
Understand mocks and stubs in testing managed versus unmanaged dependencies, and how mocks verify interactions with third-party services like a credit score API while stubs provide hard coded responses.
Learn how to stub the credit score service response in unit tests by using a protocol and a mock, enabling fixed scores (like 720) to test apr calculations.
Learn to mock inter-service communication by creating and fulfilling expectations between the Apr service and the credit score service, using a mocked on get credit score closure to drive tests.
Write a unit test that mocks the credit score service to return nil, then verify the APR service throws a credit score not found exception.
Learn why unit tests for a view model don’t verify UI correctness in MVVM, and how UI tests validate the registration form with SSN validation.
Extract view logic into a separate registration form struct, bind fields, and test form validity as a value type, with unit and optional end-to-end tests.
Explore testing presentation logic in SwiftUI by mocking the HTTP client with a protocol, using a mocked data source for previews, and validating product filtering with unit tests.
Explore end to end testing (e2e) as a holistic approach that simulates real user journeys from the user interface through backend processes, databases, and external systems.
Master end-to-end testing in SwiftUI by validating a loan app flow from launch to APR, using staging URLs, accessibility identifiers for SSN text field and submit button, and no mocking.
Load a SwiftUI view in a UIKit app using a UIHostingController. Add a UIKit button to push the SwiftUI stock list screen.
Embed a SwiftUI rating view in a UIKit view controller using UIHostingController, display it as a subview, center it with constraints, and prepare to retrieve the rating later.
Wrap the SwiftUI rating view in a hosting container and expose an observable rating object, then subscribe with Combine to update a UIKit label as the rating changes.
Learn to load a UIKit view into a SwiftUI app using the UIViewRepresentable protocol, implementing makeUIView and updateUIView to wrap a UIActivityIndicatorView controlled by a loading state.
Learn how to embed a UIKit map view in SwiftUI using UIViewRepresentable, configure a map view coordinator as MKMapViewDelegate, and customize annotations with a custom Apple marker annotation.
Learn to load a SwiftUI donut cell into a UIKit table view using UI hosting configuration and cell content configuration.
Preview a view controller in Xcode previews by creating a view controller representable conforming to UI view controller representable and implementing make UI view controller.
Learn to format date and time in SwiftUI using now.formatted with date style and time style options, including omitted, abbreviated, long, numeric, and ISO 8601 formats for flexible user interfaces.
Explore SwiftUI list formatting with the list modifier to display names and numbers using currency, percentages, and end and or separators, localized.
Since its introduction in 2019, the SwiftUI architecture has sparked ongoing debates. Over the past two years, I've dedicated myself to exploring various patterns and best practices aimed at simplifying the development of SwiftUI applications.
I've gained a comprehensive understanding of SwiftUI architecture and how to utilize it in accordance with Apple's guidelines. This course is the culmination of my years of research and hands-on experience. Its aim is to assist you in mastering SwiftUI architecture and embracing best practices throughout your development journey.
Course Overview
In this course, we will cover a wide range of topics crucial for building robust SwiftUI applications. Below is a detailed outline of what you can expect to learn:
Limitations of MVVM in SwiftUI
Model-View-ViewModel (MVVM) is a popular design pattern in iOS development. However, it presents unique challenges when applied to SwiftUI:
- State Management: Managing state across views can become cumbersome.
- Complexity: ViewModels can grow large and complex.
- Performance Issues: Improper state handling can lead to performance bottlenecks.
We will delve into these limitations and explore alternative approaches to streamline your SwiftUI development process.
Migrating from MVVM to MV
SwiftUI encourages a more straightforward approach to architecture, often favoring a Model-View (MV) pattern over MVVM. In this module, you will learn:
- Differences between MVVM and MV: Understanding the core distinctions and when to apply each pattern.
- Migration Strategies: Step-by-step guidance on transitioning your existing MVVM codebase to MV.
- Best Practices: Leveraging MV to simplify your SwiftUI code.
Understanding Aggregate Models/Stores
Aggregating models and stores can significantly improve data management in SwiftUI applications. Key topics include:
- Data Aggregation Techniques: Methods for combining multiple data sources.
- State Management: Efficiently managing state in aggregate models.
- Practical Examples: Implementing aggregate stores in real-world scenarios.
SwiftUI Views
Designing and structuring views effectively is critical in SwiftUI. This section will cover:
- View Composition: Building reusable and modular views.
- Declarative Syntax: Utilizing SwiftUI's declarative syntax to create intuitive and maintainable UIs.
- Performance Optimization: Techniques to ensure your views are performant.
Validation
Input validation is a common requirement in applications. Here, we will explore:
- Validation Patterns: Different approaches to input validation in SwiftUI.
- Real-time Feedback: Providing users with immediate feedback on their input.
- Best Practices: Ensuring validation logic is maintainable and scalable.
Navigation
SwiftUI's navigation system offers unique capabilities and challenges. Topics include:
- NavigationStack: Understanding and using NavigationStack for hierarchical navigation.
- NavigationLinks: Proper usage of NavigationLinks and managing their state.
- Complex Navigation Flows: Handling complex navigation scenarios.
Testing
Testing is essential for ensuring the reliability of your applications. This module will focus on:
- Unit Testing: Writing and running unit tests for your SwiftUI components.
- UI Testing: Automating UI tests to verify user interactions.
- Testing Strategies: Best practices for integrating testing into your development workflow.
UIKit & SwiftUI Interoperability
Many existing projects still rely on UIKit, and interoperability is often required. In this section, you will learn:
- Bridging Techniques: How to integrate UIKit components into SwiftUI and vice versa.
- Hybrid Applications: Strategies for developing hybrid applications that use both frameworks.
- Real-world Examples: Practical examples of interoperability in action.
By the end of this course, you will have a solid understanding of SwiftUI architecture and the skills to implement best practices in your projects. Let's embark on this journey to master SwiftUI together!