iOS-Using-SwiftUI-with-our-existing-UIKit-codebase-Proposal 2
iOS-Using-SwiftUI-with-our-existing-UIKit-codebase-Proposal 2
Executive Summary
This proposal outlines a strategy for incrementally integrating SwiftUI into our existing
UIKit-based mobile application while maintaining compatibility with our current architecture
and development patterns.
Current State
The application currently uses:
UIKit for view construction
SnapKit for programmatic constraints
MVVM architecture with UIViewController handling business logic
Proposed Solution
Propose to implement a hybrid approach that allows SwiftUI views to be seamlessly
integrated into existing UIKit ViewControllers while maintaining our current architectural
patterns so our workflows won't be affected too much
Key Components
1. SwiftUI Wrapper System
1 // Main wrapper to host SwiftUI views in UIKit
2 class SwiftUIWrapper<Content: View>: UIView {
3 private var hostingController: UIHostingController<Content>
4
5 init(content: Content) {
6 self.hostingController = UIHostingController(rootView:
content)
7 super.init(frame: .zero)
8
9 // Add the hosting controller's view as a subview
10 hostingController.view.backgroundColor = .clear
11 addSubview(hostingController.view)
12
13 // Setup constraints
14
hostingController.view.translatesAutoresizingMaskIntoConstraints =
false
15 NSLayoutConstraint.activate([
16 hostingController.view.topAnchor.constraint(equalTo:
topAnchor),
17
hostingController.view.bottomAnchor.constraint(equalTo:
bottomAnchor),
18
hostingController.view.leadingAnchor.constraint(equalTo:
leadingAnchor),
19
hostingController.view.trailingAnchor.constraint(equalTo:
trailingAnchor)
20 ])
21 }
22
23 required init?(coder: NSCoder) {
24 fatalError("init(coder:) has not been implemented")
25 }
26
27 // Update the SwiftUI view's content
28 func update(content: Content) {
29 hostingController.rootView = content
30 }
31 }
32
33 // Extension utilities for easy integration
34 extension UIView {
35 func addSwiftUIView<Content: View>(_ view: Content) ->
SwiftUIWrapper<Content> {
36 let wrapper = SwiftUIWrapper(content: view)
37 addSubview(wrapper)
38 return wrapper
39 }
40 }
41
42 extension UIStackView {
43 func addArrangedSwiftUIView<Content: View>(_ view: Content) ->
SwiftUIWrapper<Content> {
44 let wrapper = SwiftUIWrapper(content: view)
45 addArrangedSubview(wrapper)
46 return wrapper
47 }
48 }
49
50 extension UIViewController {
51 func addSwiftUIView<Content: View>(_ view: Content) ->
SwiftUIWrapper<Content> {
52 let wrapper = SwiftUIWrapper(content: view)
53 self.view.addSubview(wrapper)
54 return wrapper
55 }
56 }
Implementation Strategy
1. View Integration Pattern
1 class ExampleViewController: UIViewController {
2 private lazy var swiftUIContent = addSwiftUIView(
3 ExampleSwiftUIView(
4 viewModel: viewModel
5 )
6 )
7
8 override func viewDidLoad() {
9 super.viewDidLoad()
10
11 // Setup constraints using existing SnapKit patterns
12 swiftUIContent.snp.makeConstraints { make in
13 make.edges.equalToSuperview()
14 }
15 }
16 }
2. Migration Approach
Start with new features using SwiftUI
Gradually refactor existing views starting with simple, self-contained components
Keep complex interactive elements in UIKit initially
Maintain existing navigation patterns using UIKit
Benefits
Category Benefits
Technical Considerations
Category Details