Skip to content

Commit 913cd1b

Browse files
committed
Support dynamic content updates in SwiftUI
Store content hosting controller reference and update it dynamically in updateUIViewController(), allowing panel content to change without recreation. Resolved #672
1 parent 41d7580 commit 913cd1b

File tree

2 files changed

+56
-12
lines changed

2 files changed

+56
-12
lines changed

Examples/SamplesSwiftUI/SamplesSwiftUI/UseCases/MainView.swift

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,28 @@ import UIKit
66
import os.log
77

88
struct MainView: View {
9+
enum CardContent: String, CaseIterable, Identifiable {
10+
case list
11+
case detail
12+
13+
var id: String { rawValue }
14+
}
915
@State private var panelLayout: FloatingPanelLayout? = MyFloatingPanelLayout()
1016
@State private var panelState: FloatingPanelState?
17+
@State private var selectedContent: CardContent = .list
1118

1219
var body: some View {
1320
ZStack {
1421
Color.orange
1522
.ignoresSafeArea()
16-
.floatingPanel(
17-
coordinator: MyPanelCoordinator.self
18-
) { proxy in
19-
ContentView(proxy: proxy)
20-
}
21-
.floatingPanelSurfaceAppearance(.transparent())
22-
.floatingPanelLayout(panelLayout)
23-
.floatingPanelState($panelState)
24-
.onChange(of: panelState) { newValue in
25-
Logger().debug("Panel state changed: \(newValue ?? .hidden)")
26-
}
27-
2823
VStack(spacing: 32) {
24+
Picker("type", selection: $selectedContent) {
25+
ForEach(CardContent.allCases) {
26+
type in
27+
Text(type.rawValue).tag(type)
28+
}
29+
}
30+
.pickerStyle(.segmented)
2931
Button("Move to full") {
3032
withAnimation(.interactiveSpring) {
3133
panelState = .full
@@ -46,8 +48,29 @@ struct MainView: View {
4648
Text("Switch to My layout")
4749
}
4850
}
51+
Spacer()
52+
}
53+
}
54+
.floatingPanel(
55+
coordinator: MyPanelCoordinator.self
56+
) { proxy in
57+
switch selectedContent {
58+
case .list:
59+
ContentView(proxy: proxy)
60+
case .detail:
61+
VStack {
62+
Text("off")
63+
.padding(.top, 32)
64+
Spacer()
65+
}
4966
}
5067
}
68+
.floatingPanelSurfaceAppearance(.transparent())
69+
.floatingPanelLayout(panelLayout)
70+
.floatingPanelState($panelState)
71+
.onChange(of: panelState) { newValue in
72+
Logger().debug("Panel state changed: \(newValue ?? .hidden)")
73+
}
5174
}
5275
}
5376

@@ -104,3 +127,4 @@ class MyFloatingPanelLayout: FloatingPanelLayout {
104127
#Preview("MainView") {
105128
MainView()
106129
}
130+

Sources/SwiftUI/FloatingPanelView.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,11 @@ struct FloatingPanelView<MainView: View, ContentView: View>: UIViewControllerRep
110110
_ uiViewController: UIHostingController<MainView>,
111111
context: Context
112112
) {
113+
uiViewController.rootView = main
114+
115+
context.coordinator.updateContent(content(context.coordinator.proxy))
113116
context.coordinator.onUpdate(context: context)
117+
114118
applyEnvironment(context: context)
115119
applyAnimatableEnvironment(context: context)
116120
}
@@ -160,6 +164,9 @@ class FloatingPanelCoordinatorProxy {
160164

161165
private var subscriptions: Set<AnyCancellable> = Set()
162166

167+
// Store a reference to the content hosting controller for dynamic updates
168+
private weak var contentHostingController: UIViewController?
169+
163170
var proxy: FloatingPanelProxy { origin.proxy }
164171
var controller: FloatingPanelController { origin.controller }
165172

@@ -181,12 +188,25 @@ class FloatingPanelCoordinatorProxy {
181188
mainHostingController: UIHostingController<Main>,
182189
contentHostingController: UIHostingController<Content>
183190
) {
191+
// Store the content hosting controller reference
192+
self.contentHostingController = contentHostingController
193+
184194
origin.setupFloatingPanel(
185195
mainHostingController: mainHostingController,
186196
contentHostingController: contentHostingController
187197
)
188198
}
189199

200+
/// Updates the content of the floating panel with new content.
201+
func updateContent<Content: View>(_ newContent: Content) {
202+
guard
203+
let hostingController = contentHostingController as? UIHostingController<Content>
204+
else {
205+
return
206+
}
207+
hostingController.rootView = newContent
208+
}
209+
190210
func onUpdate<Representable>(
191211
context: UIViewControllerRepresentableContext<Representable>
192212
) where Representable: UIViewControllerRepresentable {

0 commit comments

Comments
 (0)