Explore the various UI frameworks available for building app interfaces. Discuss the use cases for different frameworks, share best practices, and get help with specific framework-related questions.

All subtopics
Posts under UI Frameworks topic

Post

Replies

Boosts

Views

Activity

NavigationSplitView content column renders list in plain style – even on iPhone
Hi everyone, I’m building an iOS app that originally targeted iPhone using NavigationStack. Now I’m adapting it for iPad and switched to using NavigationSplitView to support a three-column layout. The structure looks like this: NavigationSplitView { A // Sidebar } content: { B // Middle column – this shows a list } detail: { C // Detail view } The issue is with the list shown in view B (the content column). It appears completely unstyled, as if it’s using .listStyle(.plain) — with no background material, no grouped sections, and a very flat look. I can understand that this might be intentional on iPad to visually distinguish the three columns. However, the problem is that this same unstyled list also appears on iPhone, even though iPhone only shows a single column view at a time! I tried explicitly setting .listStyle(.insetGrouped) or .listStyle(.grouped) on the list in view B, but it makes no difference. When I go back to NavigationStack, the list in B is styled properly, just as expected — but then I lose the enhanced iPad layout. What I’m looking for: I’d like to keep using NavigationSplitView, but I want the list in the content column (view B) to use the default iOS list styling, at least on iPhone. Is there any way to achieve this? Thanks!
0
0
99
Aug ’25
NavigationSplitView content column renders list in plain style – even on iPhone
Hi everyone, I’m building an iOS app that originally targeted iPhone using NavigationStack. Now I’m adapting it for iPad and switched to using NavigationSplitView to support a three-column layout. The structure looks like this: NavigationSplitView { A // Sidebar } content: { B // Middle column – this shows a list } detail: { C // Detail view } The issue is with the list shown in view B (the content column). It appears completely unstyled, as if it’s using .listStyle(.plain) — with no background material, and a very flat look. I can understand that this might be intentional on iPad to visually distinguish the three columns. However, the problem is that this same unstyled list also appears on iPhone, even though iPhone only shows a single column view at a time! I tried explicitly setting .listStyle(.insetGrouped) or .listStyle(.grouped) on the list in view B, but it makes no difference. When I go back to NavigationStack, the list in B is styled properly, just as expected — but then I lose the enhanced iPad layout. What I’m looking for: I’d like to keep using NavigationSplitView, but I want the list in the content column (view B) to use the default iOS list styling, at least on iPhone. Is there any way to achieve this? Thanks!
0
0
92
Aug ’25
How to opt out of tinting content in visionOS widgets
During the WWDC Session called "Design widgets for visionOS" the presenter says: You can choose whether the background of your widget participates in tinting. If you opted out, for example to preserve a photo or illustration, make sure it still looks good alongside the selected color palette. https://developer.apple.com/videos/play/wwdc2025/255 Unfortunately, this session has no example code. Can someone point me to the correct way to do this? Is there a modifier we can use on views? When a user selects one the tint colors using the configuration screen, we would like to prevent some views from being tinted.
0
0
95
Jul ’25
[Want] A View detects one from multiple Gestures.
SwiftUI Gesture cannot detect one of multiple gestures. I made a library for it because one of my apps needs it. library: https://github.com/Saw-000/SwiftUI-DetectGestureUtil I think the function like this library maybe is needed in the core, and can be used with "import SwiftUI", isn't it?
Topic: UI Frameworks SubTopic: SwiftUI
0
0
122
Nov ’25
Swift UI の 日時表示の.timerでのコロン(:)のユニコードについて
I'm currently exploring ways to update a widget's display independently of the timeline mechanism. While researching, I came across this thread and started experimenting with the approach: https://developer.apple.com/forums/thread/720640 As part of the implementation, I'm attempting to render a 00:00-style time string using a single custom font glyph via .timer. However, I noticed that the colon character used in .timer doesn't appear to be the standard Unicode 0x003A (colon). It seems to be a different character entirely. Does anyone happen to know exactly which character this colon is? Any insights would be appreciated.
0
0
67
Jul ’25
How to replicate Mail toolbar
The toolbar in the the Mail app uses seems to force a .soft scrollEdgeEffectStyle, however I can't seem to reproduce this. Even when putting .scrollEdgeEffectStyle(.soft, for: .top) all over my code, a NavigationSplitView seems to force a "classic" toolbar. Example, top is the mail app, bottom is my swiftUI app:
0
0
154
Jul ’25
Pushing a UIHostingController has delayed toolbar items and title transitions
For over five years, this persistent issue has affected all platforms, and despite submitting numerous feedback reports, my concerns have remained unaddressed. When utilizing a UIHostingController within a UINavigationController, the toolbar items and title defined in the SwiftUI view manifest with a substantial delay. This delay is particularly noticeable with the introduction of Liquid Glass, resulting in a jarring transition. Although I had nearly lost hope, the issue was resolved in iOS 26 beta 3 when the push occurs from within a UISplitViewController. However, the problem persists outside of this context. Ultimately, this issue hinders my ability to develop high-quality applications and restricts my use of SwiftUI within my UIKit project for similar purposes. I sincerely hope that this issue can be resolved, enabling me to fully rely on SwiftUI in my project. Please prioritize this matter and make the necessary changes that were already made in UISplitViewController. This feedback has all the details and a sample project. FB14000542 Before the push: During the push: A second after the push finishes:
0
1
162
Jul ’25
tabBarMinimizeBehavior not working if subview has TabView with .tabViewStyle(.page)
We are using a TabView as the TabBarController in our app for main navigation. On one of the tabs we have a view that consists of a TabView with .tabViewStyle(.page) in order to scroll horizontally between pages inside of that specific tab. The .tabBarMinimizeBehavior(.onScrollDown) works on all the other TabItem views, but for this one it does not recognise any vertical scrolling in any of the pages, in order to minimize the TabBar. I believe this is a bug? If we don't wrap the views inside the TabView with .page style, we are able to get the expected behaviour using the tabBarMinimizeBehavior. Please let us know if this is going to be fixed in a future iOS 26 beta release.
0
3
228
Jul ’25
Is it reasonable to vend an NSView from a "ViewModel" when using NSViewRepresentable instead of implementing the Coordinator pattern?
I'm currently integrating SwiftUI into an AppKit based application and was curious if the design pattern below was viable or not. In order to "bridge" between AppKit and SwiftUI, most of my SwiftUI "root" views have aViewModel that is accessible to the SwiftUI view via @ObservedObject. When a SwiftUI views need to use NSViewRepresentable I'm finding the use of a ViewModel and a Coordinator to be an unnecessary layer of indirection. In cases where it makes sense, I've just used the ViewModel as the Coordinator and it all appears to be working ok, but I'm curious if this is reasonable design pattern or if I'm overlooking something. Consider the following pseudo code: // 1. A normal @ObservedObject acting as the ViewModel that also owns and manages an NSTableView. @MainActor final class ViewModel: ObservedObject, NSTableView... { let scrollView: NSScrollView let tableView: NSTableView @Published var selectedTitle: String init() { // ViewModel manages tableView as its dataSource and delegate. tableView.dataSource = self tableView.delegate = self } func reload() { tableView.reloadData() } // Update view model properties. // Simpler than passing back up through a Coordinator. func tableViewSelectionDidChange(_ notification: Notification) { selectedTitle = tableView.selectedItem.title } } // 2. A normal SwiftUI view, mostly driven by the ViewModel. struct ContentView: View { @ObservedObject model: ViewModel var body: some View { Text(model.selectedTitle) // No need to pass anything down other than the view model. MyTableView(model: model) Button("Reload") { model.reload() } Button("Delete") { model.deleteRow(...) } } } // 3. A barebones NSViewRepresentable that just vends the required NSView. No other state is required as the ViewModel handles all interactions with the view. struct MyTableView: NSViewRepresentable { // Can this even be an NSView? let model: ViewModel func makeNSView(context: Context) -> some NSView { return model.scrollView } func updateNSView(_ nsView: NSViewType, context: Context) { // Not needed, all updates are driven through the ViewModel. } } From what I can tell, the above is working as expected, but I'm curious if there are some situations where this could "break", particularly around the lifecycle of NSViewRepresentable Would love to know if overall pattern is "ok" from a SwiftUI perspective.
0
0
68
Apr ’25
UIViewRepresentable Coordinator @Binding returns stale value when accessed via context.coordinator but fresh value when accessed via self
I'm encountering unexpected behavior with @Binding in a UIViewRepresentable's Coordinator. The same Coordinator instance returns different values depending on how the property is accessed. Environment: iOS 17+ / Xcode 15+ SwiftUI with UIViewRepresentable Issue: When I access @Binding var test inside the Coordinator: ✅ Via self.test in Coordinator methods: Returns the updated value ❌ Via context.coordinator.test in updateUIView: Returns the stale/initial value Both access the same Coordinator instance (verified by memory address), yet return different values. Minimal Reproducible Example: struct ContentView: View { @State private var test: [Int] = [1, 2, 3, 4, 5] var body: some View { VStack { TestRepresentable(test: $test) Text("State: \(test.description)") } } } struct TestRepresentable: UIViewRepresentable { @Binding var test: [Int] func makeUIView(context: Context) -> UIButton { let button = UIButton(type: .system) button.setTitle("Toggle", for: .normal) button.addTarget( context.coordinator, action: #selector(Coordinator.buttonTapped), for: .touchUpInside ) return button } func updateUIView(_ uiView: UIButton, context: Context) { // Log coordinator instance address let coordAddr = String(describing: Unmanaged.passUnretained(context.coordinator).toOpaque()) print("[updateUIView] Coordinator address: \(coordAddr)") // Log values print("[updateUIView] self.test: \(self.test)") print("[updateUIView] context.coordinator.test: \(context.coordinator.test)") // These should be the same but they're not! // self.test shows updated value // context.coordinator.test shows stale value } func makeCoordinator() -> Coordinator { Coordinator(test: $test) } class Coordinator: NSObject { @Binding var test: [Int] var idx: Int = 0 init(test: Binding<[Int]>) { _test = test } @objc func buttonTapped() { idx += 1 if idx < test.count { test[idx] += 5 } // Log coordinator instance address let selfAddr = String(describing: Unmanaged.passUnretained(self).toOpaque()) print("[buttonTapped] Coordinator address: \(selfAddr)") // Log value - this shows the UPDATED value print("[buttonTapped] self.test: \(test)") } } } Actual Output: [Initial] [updateUIView] Coordinator address: 0x600001234567 [updateUIView] self.test: [1, 2, 3, 4, 5] [updateUIView] context.coordinator.test: [1, 2, 3, 4, 5] [After first tap] [buttonTapped] Coordinator address: 0x600001234567 [buttonTapped] self.test: [1, 7, 3, 4, 5] ✅ Updated! [updateUIView] Coordinator address: 0x600001234567 ← Same instance [updateUIView] self.test: [1, 7, 3, 4, 5] ✅ Updated! [updateUIView] context.coordinator.test: [1, 2, 3, 4, 5] ❌ Stale! [After second tap] [buttonTapped] Coordinator address: 0x600001234567 [buttonTapped] self.test: [1, 7, 8, 4, 5] ✅ Updated! [updateUIView] Coordinator address: 0x600001234567 ← Same instance [updateUIView] self.test: [1, 7, 8, 4, 5] ✅ Updated! [updateUIView] context.coordinator.test: [1, 2, 3, 4, 5] ❌ Still stale! Questions: Why does context.coordinator.test return a stale value when it's the same Coordinator instance? Is this intended behavior or a bug? What's the correct pattern to access Coordinator's @Binding properties in updateUIView? Workaround Found: Using self.test instead of context.coordinator.test in updateUIView works, but I'd like to understand why accessing the same property through context yields different results. Related: I've seen suggestions to update coordinator.parent = self in updateUIView, but this doesn't explain why the same object's property returns different values. Binding documentation states it's "a pair of get and set closures," but there's no explanation of how Context affects closure behavior. Any insights would be greatly appreciated! P.S - https://stackoverflow.com/questions/69552418/why-does-a-binding-in-uiviewrepresentables-coordinator-have-a-constant-read-valu This is the link that I found out online with same problem that I have but not answered well.
0
0
59
Nov ’25
MFMessageComposeViewController: Close button disappears after sending message on iOS 26
Description When presenting MFMessageComposeViewController from SwiftUI using UIViewControllerRepresentable, the close button disappears after sending a message on iOS 26. As a result, the message compose screen cannot be dismissed, leaving the user stuck on the Messages UI. struct MessageComposeView: UIViewControllerRepresentable { typealias Completion = (_ messageSent: Bool) -> Void static var canSendText: Bool { MFMessageComposeViewController.canSendText() } let recipients: [String]? let body: String? let completion: Completion? func makeUIViewController(context: Context) -> UIViewController { guard Self.canSendText else { let errorView = MessagesUnavailableView() return UIHostingController(rootView: errorView) } let controller = MFMessageComposeViewController() controller.messageComposeDelegate = context.coordinator controller.recipients = recipients controller.body = body return controller } func updateUIViewController(_ uiViewController: UIViewController, context: Context) {} func makeCoordinator() -> Coordinator { Coordinator(completion: self.completion) } class Coordinator: NSObject, MFMessageComposeViewControllerDelegate { private let completion: Completion? public init(completion: Completion?) { self.completion = completion } public func messageComposeViewController(_ controller: MFMessageComposeViewController, didFinishWith result: MessageComposeResult) { if result == .cancelled { controller.dismiss(animated: true, completion: nil) } completion?(result == .sent) } } } Before sending message: After sending message:
Topic: UI Frameworks SubTopic: SwiftUI
0
1
113
Nov ’25
iOS26: Programmatically Minimize TabView
In our app we have a view with a custom scroll implementation in a TabView. We would like to programmatically minimize (not hide) the TabView, like .tabBarMinimizeBehavior(...) does when a List is behind the tab bar and a user scrolls. I haven't found any view modifier that I can attach that allows me to do so, is this not possible? I would have expected something like .tabBarMinimized($tabBarMinimized)
Topic: UI Frameworks SubTopic: SwiftUI
0
0
123
Jul ’25
How to scale a SwiftUI view to fit its parent
Code that reproduces the issue import SwiftUI @main struct KeyboardLayoutProblemApp: App { var body: some Scene { WindowGroup { iOSTabView() } } } struct iOSTabView: View { var body: some View { TabView { GameView() .frame(maxWidth: UIScreen.main.bounds.width, maxHeight: UIScreen.main.bounds.height) .tabItem { Label("Play", systemImage: "gamecontroller.fill") } } } } struct GameView: View { var body: some View { VStack { Text("Play") Spacer() KeyboardView() } .padding() } } struct KeyboardView: View { let firstRowLetters = "qwertyuiop".map { $0 } let secondRowLetters = "asdfghjkl".map { $0 } let thirdRowLetters = "zxcvbnm".map { $0 } var body: some View { VStack { HStack { ForEach(firstRowLetters, id: \.self) { LetterKeyView(character: $0) } } HStack { ForEach(secondRowLetters, id: \.self) { LetterKeyView(character: $0) } } HStack { ForEach(thirdRowLetters, id: \.self) { LetterKeyView(character: $0) } } } .padding() } } struct LetterKeyView: View { let character: Character var width: CGFloat { height*0.8 } @ScaledMetric(relativeTo: .title3) private var height = 35 var body: some View { Button { print("\(character) pressed") } label: { Text(String(character).capitalized) .font(.title3) .frame(width: self.width, height: self.height) .background { RoundedRectangle(cornerRadius: min(width, height)/4, style: .continuous) .stroke(.gray) } } .buttonStyle(PlainButtonStyle()) } } Problem GameView doesn't fit its parent view: Question How do I make GameView be at most as big as its parent view? What I've tried and didn't work GameView() .frame(maxWidth: .infinity, maxHeight: .infinity) GeometryReader { geometry in GameView() .frame(maxWidth: geometry.size.width, maxHeight: geometry.size.height) } GameView() .clipped() GameView() .layoutPriority(1) GameView() .scaledToFit() GameView() .minimumScaleFactor(0.01) GameView() .scaledToFill() .minimumScaleFactor(0.5) I'm not using UIScreen.main.bounds.width because I'm trying to build a multi-platform app.
Topic: UI Frameworks SubTopic: SwiftUI
0
0
95
Jul ’25
Tipkit for VisionOS (TabView, etc.)
I am trying to create a user flow where I can guide the user how to navigate through my app. I want to add a tip on a TabView that indicates user to navigate to a specific tab. I have seen this work with iOS properly but I am a little lost as VisionOS is not responding the same for .popoverTip etc. Any guidance is appreciated!
0
0
212
Jul ’25
How can I build a custom `PickerStyle` in SwiftUI?
I am trying to create a radio group picker in SwiftUI, similar to this: https://www.neobrutalism.dev/docs/radio-group I already have a working view based version here: https://github.com/rational-kunal/NeoBrutalism/blob/main/Sources/NeoBrutalism/Components/Radio/Radio.swift Now I want to replace it with a more concise/swifty way of Picker with PickerStyle API: However, I can't find any official documentation or examples showing how to implement PickerStyle. Is it possible to create my own PickerStyle? If not, what’s the recommended alternative to achieve a radio‑group look while still using Picker? struct NBRadioGroupPickerStyle: PickerStyle { static func _makeView<SelectionValue>(value: _GraphValue<_PickerValue<NBRadioGroupPickerStyle, SelectionValue>>, inputs: _ViewInputs) -> _ViewOutputs where SelectionValue : Hashable { <#code#> } static func _makeViewList<SelectionValue>(value: _GraphValue<_PickerValue<NBRadioGroupPickerStyle, SelectionValue>>, inputs: _ViewListInputs) -> _ViewListOutputs where SelectionValue : Hashable { <#code#> } } Crossposting: https://forums.swift.org/t/how-can-i-build-a-custom-pickerstyle-in-swiftui/80755
0
0
191
Jun ’25
How to have different colors in Charts with AreaMark
I would like to have different fill colors in my chart. What I want to achieve is that if the values drop below 0 the fill color should be red. If they are above the fill color should be red. My code looks as follows: import SwiftUI import Charts struct DataPoint: Identifiable {     let id: UUID = UUID()     let x: Int     let y: Int } struct AlternatingChartView: View {          enum Gradients {         static let greenGradient = LinearGradient(gradient: Gradient(colors: [.green, .white]), startPoint: .top, endPoint: .bottom)         static let blueGradient = LinearGradient(gradient: Gradient(colors: [.white, .blue]), startPoint: .top, endPoint: .bottom)     }          let data: [DataPoint] = [         DataPoint(x: 1, y: 10),         DataPoint(x: 2, y: -5),         DataPoint(x: 3, y: 20),         DataPoint(x: 4, y: -8),         DataPoint(x: 5, y: 15),     ]               var body: some View {         Chart {             ForEach(data) { data in                 AreaMark(                     x: .value("Data Point", data.x),                     y: .value("amount", data.y))                 .interpolationMethod(.catmullRom)                 .foregroundStyle(data.y < 0 ? Color.red : Color.green)                                  LineMark(                 x: .value("Data Point", data.x),                 y: .value("amount", data.y))                 .interpolationMethod(.catmullRom)                 .foregroundStyle(Color.black)                 .lineStyle(StrokeStyle.init(lineWidth: 4))                              }         }         .frame(height: 200)     } } #Preview {     AlternatingChartView() } The result looks like this: I also tried using foregroundStyle(by:) and chartForegroundStyleScale(_:) but the result was, that two separate areas had been drawn. One for the below and one for the above zero datapoints. So, what would be the right approach to have two different fill colors?
0
0
138
Jun ’25
Display a broader track of a user on ios app with Mapkit.
Hello I'm currently building a feature within an ios app using SwiftUI and Mapkit to record the gps cordinates of a user as they move and render the track on the map. the idea is not really to have a "track" but to have a visual representation of the area the user sees while they are moving around. I need this width/breadth to be relative to the map and not the screen, such that when I zoom in and out of the map, the size will adjust automatically.
0
0
74
May ’25
NavigationSplitView content column renders list in plain style – even on iPhone
Hi everyone, I’m building an iOS app that originally targeted iPhone using NavigationStack. Now I’m adapting it for iPad and switched to using NavigationSplitView to support a three-column layout. The structure looks like this: NavigationSplitView { A // Sidebar } content: { B // Middle column – this shows a list } detail: { C // Detail view } The issue is with the list shown in view B (the content column). It appears completely unstyled, as if it’s using .listStyle(.plain) — with no background material, no grouped sections, and a very flat look. I can understand that this might be intentional on iPad to visually distinguish the three columns. However, the problem is that this same unstyled list also appears on iPhone, even though iPhone only shows a single column view at a time! I tried explicitly setting .listStyle(.insetGrouped) or .listStyle(.grouped) on the list in view B, but it makes no difference. When I go back to NavigationStack, the list in B is styled properly, just as expected — but then I lose the enhanced iPad layout. What I’m looking for: I’d like to keep using NavigationSplitView, but I want the list in the content column (view B) to use the default iOS list styling, at least on iPhone. Is there any way to achieve this? Thanks!
Replies
0
Boosts
0
Views
99
Activity
Aug ’25
NavigationSplitView content column renders list in plain style – even on iPhone
Hi everyone, I’m building an iOS app that originally targeted iPhone using NavigationStack. Now I’m adapting it for iPad and switched to using NavigationSplitView to support a three-column layout. The structure looks like this: NavigationSplitView { A // Sidebar } content: { B // Middle column – this shows a list } detail: { C // Detail view } The issue is with the list shown in view B (the content column). It appears completely unstyled, as if it’s using .listStyle(.plain) — with no background material, and a very flat look. I can understand that this might be intentional on iPad to visually distinguish the three columns. However, the problem is that this same unstyled list also appears on iPhone, even though iPhone only shows a single column view at a time! I tried explicitly setting .listStyle(.insetGrouped) or .listStyle(.grouped) on the list in view B, but it makes no difference. When I go back to NavigationStack, the list in B is styled properly, just as expected — but then I lose the enhanced iPad layout. What I’m looking for: I’d like to keep using NavigationSplitView, but I want the list in the content column (view B) to use the default iOS list styling, at least on iPhone. Is there any way to achieve this? Thanks!
Replies
0
Boosts
0
Views
92
Activity
Aug ’25
How to opt out of tinting content in visionOS widgets
During the WWDC Session called "Design widgets for visionOS" the presenter says: You can choose whether the background of your widget participates in tinting. If you opted out, for example to preserve a photo or illustration, make sure it still looks good alongside the selected color palette. https://developer.apple.com/videos/play/wwdc2025/255 Unfortunately, this session has no example code. Can someone point me to the correct way to do this? Is there a modifier we can use on views? When a user selects one the tint colors using the configuration screen, we would like to prevent some views from being tinted.
Replies
0
Boosts
0
Views
95
Activity
Jul ’25
[Want] A View detects one from multiple Gestures.
SwiftUI Gesture cannot detect one of multiple gestures. I made a library for it because one of my apps needs it. library: https://github.com/Saw-000/SwiftUI-DetectGestureUtil I think the function like this library maybe is needed in the core, and can be used with "import SwiftUI", isn't it?
Topic: UI Frameworks SubTopic: SwiftUI
Replies
0
Boosts
0
Views
122
Activity
Nov ’25
Swift UI の 日時表示の.timerでのコロン(:)のユニコードについて
I'm currently exploring ways to update a widget's display independently of the timeline mechanism. While researching, I came across this thread and started experimenting with the approach: https://developer.apple.com/forums/thread/720640 As part of the implementation, I'm attempting to render a 00:00-style time string using a single custom font glyph via .timer. However, I noticed that the colon character used in .timer doesn't appear to be the standard Unicode 0x003A (colon). It seems to be a different character entirely. Does anyone happen to know exactly which character this colon is? Any insights would be appreciated.
Replies
0
Boosts
0
Views
67
Activity
Jul ’25
How to replicate Mail toolbar
The toolbar in the the Mail app uses seems to force a .soft scrollEdgeEffectStyle, however I can't seem to reproduce this. Even when putting .scrollEdgeEffectStyle(.soft, for: .top) all over my code, a NavigationSplitView seems to force a "classic" toolbar. Example, top is the mail app, bottom is my swiftUI app:
Replies
0
Boosts
0
Views
154
Activity
Jul ’25
Pushing a UIHostingController has delayed toolbar items and title transitions
For over five years, this persistent issue has affected all platforms, and despite submitting numerous feedback reports, my concerns have remained unaddressed. When utilizing a UIHostingController within a UINavigationController, the toolbar items and title defined in the SwiftUI view manifest with a substantial delay. This delay is particularly noticeable with the introduction of Liquid Glass, resulting in a jarring transition. Although I had nearly lost hope, the issue was resolved in iOS 26 beta 3 when the push occurs from within a UISplitViewController. However, the problem persists outside of this context. Ultimately, this issue hinders my ability to develop high-quality applications and restricts my use of SwiftUI within my UIKit project for similar purposes. I sincerely hope that this issue can be resolved, enabling me to fully rely on SwiftUI in my project. Please prioritize this matter and make the necessary changes that were already made in UISplitViewController. This feedback has all the details and a sample project. FB14000542 Before the push: During the push: A second after the push finishes:
Replies
0
Boosts
1
Views
162
Activity
Jul ’25
tabBarMinimizeBehavior not working if subview has TabView with .tabViewStyle(.page)
We are using a TabView as the TabBarController in our app for main navigation. On one of the tabs we have a view that consists of a TabView with .tabViewStyle(.page) in order to scroll horizontally between pages inside of that specific tab. The .tabBarMinimizeBehavior(.onScrollDown) works on all the other TabItem views, but for this one it does not recognise any vertical scrolling in any of the pages, in order to minimize the TabBar. I believe this is a bug? If we don't wrap the views inside the TabView with .page style, we are able to get the expected behaviour using the tabBarMinimizeBehavior. Please let us know if this is going to be fixed in a future iOS 26 beta release.
Replies
0
Boosts
3
Views
228
Activity
Jul ’25
Is it reasonable to vend an NSView from a "ViewModel" when using NSViewRepresentable instead of implementing the Coordinator pattern?
I'm currently integrating SwiftUI into an AppKit based application and was curious if the design pattern below was viable or not. In order to "bridge" between AppKit and SwiftUI, most of my SwiftUI "root" views have aViewModel that is accessible to the SwiftUI view via @ObservedObject. When a SwiftUI views need to use NSViewRepresentable I'm finding the use of a ViewModel and a Coordinator to be an unnecessary layer of indirection. In cases where it makes sense, I've just used the ViewModel as the Coordinator and it all appears to be working ok, but I'm curious if this is reasonable design pattern or if I'm overlooking something. Consider the following pseudo code: // 1. A normal @ObservedObject acting as the ViewModel that also owns and manages an NSTableView. @MainActor final class ViewModel: ObservedObject, NSTableView... { let scrollView: NSScrollView let tableView: NSTableView @Published var selectedTitle: String init() { // ViewModel manages tableView as its dataSource and delegate. tableView.dataSource = self tableView.delegate = self } func reload() { tableView.reloadData() } // Update view model properties. // Simpler than passing back up through a Coordinator. func tableViewSelectionDidChange(_ notification: Notification) { selectedTitle = tableView.selectedItem.title } } // 2. A normal SwiftUI view, mostly driven by the ViewModel. struct ContentView: View { @ObservedObject model: ViewModel var body: some View { Text(model.selectedTitle) // No need to pass anything down other than the view model. MyTableView(model: model) Button("Reload") { model.reload() } Button("Delete") { model.deleteRow(...) } } } // 3. A barebones NSViewRepresentable that just vends the required NSView. No other state is required as the ViewModel handles all interactions with the view. struct MyTableView: NSViewRepresentable { // Can this even be an NSView? let model: ViewModel func makeNSView(context: Context) -> some NSView { return model.scrollView } func updateNSView(_ nsView: NSViewType, context: Context) { // Not needed, all updates are driven through the ViewModel. } } From what I can tell, the above is working as expected, but I'm curious if there are some situations where this could "break", particularly around the lifecycle of NSViewRepresentable Would love to know if overall pattern is "ok" from a SwiftUI perspective.
Replies
0
Boosts
0
Views
68
Activity
Apr ’25
ShareLink in iPad menu bar does not show up
This is my code: CommandGroup(before: .printItem) { ShareLink(item: answer) .disabled(answer.isEmpty) } It works fine on Mac, when selecting the share menu from Mac, it works. But when select from iPad menu bar, nothing shows up.
Topic: UI Frameworks SubTopic: SwiftUI
Replies
0
Boosts
0
Views
84
Activity
Jul ’25
Bottom toolbar inside a modal Sheet
Although it doesn't seem to be a forbidden practice, placing toolbar items in the bottom bar of a modal Sheet (which has its own NavigationStack) triggers massive layout warnings. The same thing occurs when using the .searchable(...) view modifier inside a Sheet (which affects the bottom bar too). LayoutWarning.txt
Replies
0
Boosts
0
Views
123
Activity
Jul ’25
Need Help: Swift Playground
Can anyone help me why i cannot move on? I thought I had finished the instrcutions. However, it seems that i missed something that I didnt find out.
Replies
0
Boosts
1
Views
331
Activity
Jul ’25
UIViewRepresentable Coordinator @Binding returns stale value when accessed via context.coordinator but fresh value when accessed via self
I'm encountering unexpected behavior with @Binding in a UIViewRepresentable's Coordinator. The same Coordinator instance returns different values depending on how the property is accessed. Environment: iOS 17+ / Xcode 15+ SwiftUI with UIViewRepresentable Issue: When I access @Binding var test inside the Coordinator: ✅ Via self.test in Coordinator methods: Returns the updated value ❌ Via context.coordinator.test in updateUIView: Returns the stale/initial value Both access the same Coordinator instance (verified by memory address), yet return different values. Minimal Reproducible Example: struct ContentView: View { @State private var test: [Int] = [1, 2, 3, 4, 5] var body: some View { VStack { TestRepresentable(test: $test) Text("State: \(test.description)") } } } struct TestRepresentable: UIViewRepresentable { @Binding var test: [Int] func makeUIView(context: Context) -> UIButton { let button = UIButton(type: .system) button.setTitle("Toggle", for: .normal) button.addTarget( context.coordinator, action: #selector(Coordinator.buttonTapped), for: .touchUpInside ) return button } func updateUIView(_ uiView: UIButton, context: Context) { // Log coordinator instance address let coordAddr = String(describing: Unmanaged.passUnretained(context.coordinator).toOpaque()) print("[updateUIView] Coordinator address: \(coordAddr)") // Log values print("[updateUIView] self.test: \(self.test)") print("[updateUIView] context.coordinator.test: \(context.coordinator.test)") // These should be the same but they're not! // self.test shows updated value // context.coordinator.test shows stale value } func makeCoordinator() -> Coordinator { Coordinator(test: $test) } class Coordinator: NSObject { @Binding var test: [Int] var idx: Int = 0 init(test: Binding<[Int]>) { _test = test } @objc func buttonTapped() { idx += 1 if idx < test.count { test[idx] += 5 } // Log coordinator instance address let selfAddr = String(describing: Unmanaged.passUnretained(self).toOpaque()) print("[buttonTapped] Coordinator address: \(selfAddr)") // Log value - this shows the UPDATED value print("[buttonTapped] self.test: \(test)") } } } Actual Output: [Initial] [updateUIView] Coordinator address: 0x600001234567 [updateUIView] self.test: [1, 2, 3, 4, 5] [updateUIView] context.coordinator.test: [1, 2, 3, 4, 5] [After first tap] [buttonTapped] Coordinator address: 0x600001234567 [buttonTapped] self.test: [1, 7, 3, 4, 5] ✅ Updated! [updateUIView] Coordinator address: 0x600001234567 ← Same instance [updateUIView] self.test: [1, 7, 3, 4, 5] ✅ Updated! [updateUIView] context.coordinator.test: [1, 2, 3, 4, 5] ❌ Stale! [After second tap] [buttonTapped] Coordinator address: 0x600001234567 [buttonTapped] self.test: [1, 7, 8, 4, 5] ✅ Updated! [updateUIView] Coordinator address: 0x600001234567 ← Same instance [updateUIView] self.test: [1, 7, 8, 4, 5] ✅ Updated! [updateUIView] context.coordinator.test: [1, 2, 3, 4, 5] ❌ Still stale! Questions: Why does context.coordinator.test return a stale value when it's the same Coordinator instance? Is this intended behavior or a bug? What's the correct pattern to access Coordinator's @Binding properties in updateUIView? Workaround Found: Using self.test instead of context.coordinator.test in updateUIView works, but I'd like to understand why accessing the same property through context yields different results. Related: I've seen suggestions to update coordinator.parent = self in updateUIView, but this doesn't explain why the same object's property returns different values. Binding documentation states it's "a pair of get and set closures," but there's no explanation of how Context affects closure behavior. Any insights would be greatly appreciated! P.S - https://stackoverflow.com/questions/69552418/why-does-a-binding-in-uiviewrepresentables-coordinator-have-a-constant-read-valu This is the link that I found out online with same problem that I have but not answered well.
Replies
0
Boosts
0
Views
59
Activity
Nov ’25
MFMessageComposeViewController: Close button disappears after sending message on iOS 26
Description When presenting MFMessageComposeViewController from SwiftUI using UIViewControllerRepresentable, the close button disappears after sending a message on iOS 26. As a result, the message compose screen cannot be dismissed, leaving the user stuck on the Messages UI. struct MessageComposeView: UIViewControllerRepresentable { typealias Completion = (_ messageSent: Bool) -> Void static var canSendText: Bool { MFMessageComposeViewController.canSendText() } let recipients: [String]? let body: String? let completion: Completion? func makeUIViewController(context: Context) -> UIViewController { guard Self.canSendText else { let errorView = MessagesUnavailableView() return UIHostingController(rootView: errorView) } let controller = MFMessageComposeViewController() controller.messageComposeDelegate = context.coordinator controller.recipients = recipients controller.body = body return controller } func updateUIViewController(_ uiViewController: UIViewController, context: Context) {} func makeCoordinator() -> Coordinator { Coordinator(completion: self.completion) } class Coordinator: NSObject, MFMessageComposeViewControllerDelegate { private let completion: Completion? public init(completion: Completion?) { self.completion = completion } public func messageComposeViewController(_ controller: MFMessageComposeViewController, didFinishWith result: MessageComposeResult) { if result == .cancelled { controller.dismiss(animated: true, completion: nil) } completion?(result == .sent) } } } Before sending message: After sending message:
Topic: UI Frameworks SubTopic: SwiftUI
Replies
0
Boosts
1
Views
113
Activity
Nov ’25
iOS26: Programmatically Minimize TabView
In our app we have a view with a custom scroll implementation in a TabView. We would like to programmatically minimize (not hide) the TabView, like .tabBarMinimizeBehavior(...) does when a List is behind the tab bar and a user scrolls. I haven't found any view modifier that I can attach that allows me to do so, is this not possible? I would have expected something like .tabBarMinimized($tabBarMinimized)
Topic: UI Frameworks SubTopic: SwiftUI
Replies
0
Boosts
0
Views
123
Activity
Jul ’25
How to scale a SwiftUI view to fit its parent
Code that reproduces the issue import SwiftUI @main struct KeyboardLayoutProblemApp: App { var body: some Scene { WindowGroup { iOSTabView() } } } struct iOSTabView: View { var body: some View { TabView { GameView() .frame(maxWidth: UIScreen.main.bounds.width, maxHeight: UIScreen.main.bounds.height) .tabItem { Label("Play", systemImage: "gamecontroller.fill") } } } } struct GameView: View { var body: some View { VStack { Text("Play") Spacer() KeyboardView() } .padding() } } struct KeyboardView: View { let firstRowLetters = "qwertyuiop".map { $0 } let secondRowLetters = "asdfghjkl".map { $0 } let thirdRowLetters = "zxcvbnm".map { $0 } var body: some View { VStack { HStack { ForEach(firstRowLetters, id: \.self) { LetterKeyView(character: $0) } } HStack { ForEach(secondRowLetters, id: \.self) { LetterKeyView(character: $0) } } HStack { ForEach(thirdRowLetters, id: \.self) { LetterKeyView(character: $0) } } } .padding() } } struct LetterKeyView: View { let character: Character var width: CGFloat { height*0.8 } @ScaledMetric(relativeTo: .title3) private var height = 35 var body: some View { Button { print("\(character) pressed") } label: { Text(String(character).capitalized) .font(.title3) .frame(width: self.width, height: self.height) .background { RoundedRectangle(cornerRadius: min(width, height)/4, style: .continuous) .stroke(.gray) } } .buttonStyle(PlainButtonStyle()) } } Problem GameView doesn't fit its parent view: Question How do I make GameView be at most as big as its parent view? What I've tried and didn't work GameView() .frame(maxWidth: .infinity, maxHeight: .infinity) GeometryReader { geometry in GameView() .frame(maxWidth: geometry.size.width, maxHeight: geometry.size.height) } GameView() .clipped() GameView() .layoutPriority(1) GameView() .scaledToFit() GameView() .minimumScaleFactor(0.01) GameView() .scaledToFill() .minimumScaleFactor(0.5) I'm not using UIScreen.main.bounds.width because I'm trying to build a multi-platform app.
Topic: UI Frameworks SubTopic: SwiftUI
Replies
0
Boosts
0
Views
95
Activity
Jul ’25
Tipkit for VisionOS (TabView, etc.)
I am trying to create a user flow where I can guide the user how to navigate through my app. I want to add a tip on a TabView that indicates user to navigate to a specific tab. I have seen this work with iOS properly but I am a little lost as VisionOS is not responding the same for .popoverTip etc. Any guidance is appreciated!
Replies
0
Boosts
0
Views
212
Activity
Jul ’25
How can I build a custom `PickerStyle` in SwiftUI?
I am trying to create a radio group picker in SwiftUI, similar to this: https://www.neobrutalism.dev/docs/radio-group I already have a working view based version here: https://github.com/rational-kunal/NeoBrutalism/blob/main/Sources/NeoBrutalism/Components/Radio/Radio.swift Now I want to replace it with a more concise/swifty way of Picker with PickerStyle API: However, I can't find any official documentation or examples showing how to implement PickerStyle. Is it possible to create my own PickerStyle? If not, what’s the recommended alternative to achieve a radio‑group look while still using Picker? struct NBRadioGroupPickerStyle: PickerStyle { static func _makeView<SelectionValue>(value: _GraphValue<_PickerValue<NBRadioGroupPickerStyle, SelectionValue>>, inputs: _ViewInputs) -> _ViewOutputs where SelectionValue : Hashable { <#code#> } static func _makeViewList<SelectionValue>(value: _GraphValue<_PickerValue<NBRadioGroupPickerStyle, SelectionValue>>, inputs: _ViewListInputs) -> _ViewListOutputs where SelectionValue : Hashable { <#code#> } } Crossposting: https://forums.swift.org/t/how-can-i-build-a-custom-pickerstyle-in-swiftui/80755
Replies
0
Boosts
0
Views
191
Activity
Jun ’25
How to have different colors in Charts with AreaMark
I would like to have different fill colors in my chart. What I want to achieve is that if the values drop below 0 the fill color should be red. If they are above the fill color should be red. My code looks as follows: import SwiftUI import Charts struct DataPoint: Identifiable {     let id: UUID = UUID()     let x: Int     let y: Int } struct AlternatingChartView: View {          enum Gradients {         static let greenGradient = LinearGradient(gradient: Gradient(colors: [.green, .white]), startPoint: .top, endPoint: .bottom)         static let blueGradient = LinearGradient(gradient: Gradient(colors: [.white, .blue]), startPoint: .top, endPoint: .bottom)     }          let data: [DataPoint] = [         DataPoint(x: 1, y: 10),         DataPoint(x: 2, y: -5),         DataPoint(x: 3, y: 20),         DataPoint(x: 4, y: -8),         DataPoint(x: 5, y: 15),     ]               var body: some View {         Chart {             ForEach(data) { data in                 AreaMark(                     x: .value("Data Point", data.x),                     y: .value("amount", data.y))                 .interpolationMethod(.catmullRom)                 .foregroundStyle(data.y < 0 ? Color.red : Color.green)                                  LineMark(                 x: .value("Data Point", data.x),                 y: .value("amount", data.y))                 .interpolationMethod(.catmullRom)                 .foregroundStyle(Color.black)                 .lineStyle(StrokeStyle.init(lineWidth: 4))                              }         }         .frame(height: 200)     } } #Preview {     AlternatingChartView() } The result looks like this: I also tried using foregroundStyle(by:) and chartForegroundStyleScale(_:) but the result was, that two separate areas had been drawn. One for the below and one for the above zero datapoints. So, what would be the right approach to have two different fill colors?
Replies
0
Boosts
0
Views
138
Activity
Jun ’25
Display a broader track of a user on ios app with Mapkit.
Hello I'm currently building a feature within an ios app using SwiftUI and Mapkit to record the gps cordinates of a user as they move and render the track on the map. the idea is not really to have a "track" but to have a visual representation of the area the user sees while they are moving around. I need this width/breadth to be relative to the map and not the screen, such that when I zoom in and out of the map, the size will adjust automatically.
Replies
0
Boosts
0
Views
74
Activity
May ’25