While TCA was designed with SwiftUI in mind, it provides comprehensive tools for UIKit applications through the UIKitNavigation framework.
Basic UIKit Integration
Using @UIBindable
The @UIBindable property wrapper enables observation and binding creation in UIKit view controllers:
Using @ViewAction
The @ViewAction macro simplifies sending actions from view controllers:
Source: LoginViewController.swift:6-12
Observing State Changes
Use the observe method to react to state changes:
Source: LoginViewController.swift:86-92
Always use [weak self] and [weak view] captures in observe closures to prevent retain cycles.
Two-Way Bindings
Create UIKit bindings using the $store syntax:
Source: LoginViewController.swift:42-50
Navigation
Navigation Destinations
Use navigationDestination(item:) to handle push navigation:
Source: LoginViewController.swift:98-100
Stack-Based Navigation
For more complex navigation, use NavigationStackController:
Source: NavigationStackControllerUIKit.swift:4-78
Programmatic Navigation
Push to the stack programmatically using UIPushAction:
Source: NavigationStackControllerUIKit.swift:80-110
Alerts and Dialogs
Presenting Alerts
Use UIAlertController with store scoping:
Source: LoginViewController.swift:94-96
Alert State Integration
Define alerts in your feature’s state:
The UIAlertController initializer automatically handles the alert presentation:
Source: AlertStateUIKit.swift:7-30
Confirmation Dialogs
Similar to alerts, present confirmation dialogs:
Source: AlertStateUIKit.swift:32-54
Modal Presentation
Present view controllers modally using the present(item:) method:
Custom Bindings
Create custom bindings for UIKit controls:
Best Practices
Memory Management
Always use weak references in closures:
View Lifecycle
Set up observations in viewDidLoad():
Combine @UIBindable with @ViewAction
Use both macros together for the best experience:
Some UIKit integration features require specific iOS versions:
Source: NavigationStackControllerUIKit.swift:1-3
Complete Example
Here’s a complete UIKit view controller example:
Migration from ViewStore
If you’re migrating from the legacy ViewStore pattern: