Provide views, controls, and layout structures for declaring your app's user interface using SwiftUI.

Posts under SwiftUI tag

200 Posts
Sort by:

Post

Replies

Boosts

Views

Activity

App crashed when switching between Annotation Tab and Group Tab with TabView init(selection:content:)
This app will not crash when switching between these two tabs with TabView init(content:) import SwiftUI import SwiftData struct ContentView: View { @StateObject private var highlightManager = HighlightManager.shared @State private var selectedTab: Int = 0 var body: some View { TabView(selection: $selectedTab) { MapView() .tabItem { Label("Map", systemImage: "map") } .tag(0) // Annotation Tab AnnotationList() .tabItem { Label("Annotation", systemImage: "mappin.and.ellipse") } .tag(1) // Group Tab PeopleList() .tabItem { Label("Group", systemImage: "person.and.person") } .tag(2) } .tutorialOverlay() // Apply the overlay to the root view .environmentObject(highlightManager) .toolbar { ToolbarItem(placement: .confirmationAction) { NavigationLink("Help") { NavigationStack { HelpView(selectedTab: selectedTab) } } } } } }
1
0
61
Jul ’25
SwiftUI scroll position targeting buggy with viewAligned scrollTargetBehavior
I have a discrete scrubber implementation (range 0-100) using ScrollView in SwiftUI that fails on the end points. For instance, scrolling it all the way to bottom shows a value of 87 instead of 100. Or if scrolling down by tapping + button incrementally till it reaches the end, it will show the correct value of 100 when it reaches the end. But now, tapping minus button doesn't scrolls the scrubber back till minus button is clicked thrice. I understand this has only to do with scroll target behaviour of .viewAligned but don't understand what exactly is the issue, or if its a bug in SwiftUI. import SwiftUI struct VerticalScrubber: View { var config: ScrubberConfig @Binding var value: CGFloat @State private var scrollPosition: Int? var body: some View { GeometryReader { geometry in let verticalPadding = geometry.size.height / 2 - 8 ZStack(alignment: .trailing) { ScrollView(.vertical, showsIndicators: false) { VStack(spacing: config.spacing) { ForEach(0...(config.steps * config.count), id: \.self) { index in horizontalTickMark(for: index) .id(index) } } .frame(width: 80) .scrollTargetLayout() .safeAreaPadding(.vertical, verticalPadding) } .scrollTargetBehavior(.viewAligned) .scrollPosition(id: $scrollPosition, anchor: .top) Capsule() .frame(width: 32, height: 3) .foregroundColor(.accentColor) .shadow(color: .accentColor.opacity(0.3), radius: 3, x: 0, y: 1) } .frame(width: 100) .onAppear { DispatchQueue.main.async { scrollPosition = Int(value * CGFloat(config.steps)) } } .onChange(of: value, { oldValue, newValue in let newIndex = Int(newValue * CGFloat(config.steps)) print("New index \(newIndex)") if scrollPosition != newIndex { withAnimation { scrollPosition = newIndex print("\(scrollPosition)") } } }) .onChange(of: scrollPosition, { oldIndex, newIndex in guard let pos = newIndex else { return } let newValue = CGFloat(pos) / CGFloat(config.steps) if abs(value - newValue) > 0.001 { value = newValue } }) } } private func horizontalTickMark(for index: Int) -> some View { let isMajorTick = index % config.steps == 0 let tickValue = index / config.steps return HStack(spacing: 8) { Rectangle() .fill(isMajorTick ? Color.accentColor : Color.gray.opacity(0.5)) .frame(width: isMajorTick ? 24 : 12, height: isMajorTick ? 2 : 1) if isMajorTick { Text("\(tickValue * 5)") .font(.system(size: 12, weight: .medium)) .foregroundColor(.primary) .fixedSize() } } .frame(maxWidth: .infinity, alignment: .trailing) .padding(.trailing, 8) } } #Preview("Vertical Scrubber") { struct VerticalScrubberPreview: View { @State private var value: CGFloat = 0 private let config = ScrubberConfig(count: 20, steps: 5, spacing: 8) var body: some View { VStack { Text("Vertical Scrubber (0–100 in steps of 5)") .font(.title2) .padding() HStack(spacing: 30) { VerticalScrubber(config: config, value: $value) .frame(width: 120, height: 300) .background(Color(.systemBackground)) .border(Color.gray.opacity(0.3)) VStack { Text("Current Value:") .font(.headline) Text("\(value * 5, specifier: "%.0f")") .font(.system(size: 36, weight: .bold)) .padding() HStack { Button("−5") { let newValue = max(0, value - 1) if value != newValue { value = newValue UISelectionFeedbackGenerator().selectionChanged() } print("Value \(newValue), \(value)") } .disabled(value <= 0) Button("+5") { let newValue = min(CGFloat(config.count), value + 1) if value != newValue { value = newValue UISelectionFeedbackGenerator().selectionChanged() } print("Value \(newValue), \(value)") } .disabled(value >= CGFloat(config.count)) } .buttonStyle(.bordered) } } Spacer() } .padding() } } return VerticalScrubberPreview() }
3
0
144
Jul ’25
Xcode Crash on View Hierarchy debugger for mixed UIKit / SwiftUI app
For a large / older iOS app project, we have noticed the the view hierarchy debugger works fine for our UIKit screens, but runs into the following crasher whenever we try to launch the view hierarchy debugger on a UIHostingVC screen with SwiftUI content: Unable to capture the view hierarchy "AppName" encountered an unexpected error when processing the request for a view hierarchy snapshot. -- The operation couldn’t be completed. Log Title: Data source expression execution failure. Log Details: error evaluating expression “(BOOL)[[(Class)objc_getClass("DebugHierarchyTargetHub") sharedHub] performRequestInPlaceWithRequestInBase64:@"..."]”: error: Execution was interrupted, reason: EXC_BAD_ACCESS (code=2, address=0x16b23bff8). Has anyone successfully resolved the underlying issue in this crasher? Tried all the typical recommendations for a clean build, clear derived data, use the "Debug -> View Debugging" menu - all with no resolution. Reported using Feedback Assistant: FB18514200 Thanks
1
0
133
Jul ’25
Detecting When App Token Is Removed Due to Category Selection in FamilyActivityPicker
I'm working with the Screen Time API (FamilyActivityPicker) in SwiftUI and need help with a specific scenario. I'm using the FamilyActivityPicker to let users select apps and categories to block. I save the previous selection (both applicationTokens and categoryTokens) locally. When the user updates their selection, I compare the new selection with the saved one to determine which apps or categories were removed. However, I’m trying to handle a specific case: when an individual app token is removed from the selection because its entire category was selected instead. In this situation, even though the app is no longer in applicationTokens, it's still blocked due to its category being included in categoryTokens. Since I need to show users which apps were actually removed, I want to avoid listing apps that are still indirectly blocked via a selected category. I’ve created a mapping between ApplicationToken and FamilyActivityCategoryToken to check whether a removed app is still covered by a selected category before displaying it. Is there any way to check this using the current Screen Time APIs, or does the system not give access to the relationship between apps and their categories? Any help or suggestions would mean a lot!
2
1
141
Jul ’25
Incompatibility of matchedTransitionSource and sharedBackgroundVisibility
Take a look at following sample code. verify the shapes of two toolbar buttons. remove .matchedTransitionSource(id: 1, in: navigationNamespace) for one button. verify the toolbar button shape is changed to normal circle shape The combination usage of matchedTransitionSource and sharedBackgroundVisibility leads to unexpected display result. Removing any of these two view modifier restores the correct display. None of the view modifiers indicates it will crop the button shape. struct ContentView: View { @Namespace var navigationNamespace var body: some View { NavigationStack { ZStack { Color.gray } .ignoresSafeArea() .toolbar { ToolbarItem(placement: .topBarLeading) { Button { } label: { Image(systemName: "person") .font(.title3) .foregroundStyle(Color.accentColor) .frame(width: 50, height: 50) .glassEffect( .regular.interactive(), in: .circle ) } .matchedTransitionSource(id: 1, in: navigationNamespace) } .sharedBackgroundVisibility(.hidden) ToolbarItem(placement: .topBarTrailing) { Button { } label: { Image(systemName: "square.and.pencil") .font(.title3) .foregroundStyle(Color.accentColor) .frame(width: 50, height: 50) .glassEffect( .regular.interactive(), in: .circle ) } .matchedTransitionSource(id: 1, in: navigationNamespace) } .sharedBackgroundVisibility(.hidden) } } } } #Preview { ContentView() }
1
0
130
Jul ’25
Tap area for focusing element during voice over is not correct
I have two overlay views on each side of a horizontal scroll. The overlay views are helper arrow buttons that can be used to scroll quickly. This issue occurs when I use either ZStack or .overlay modifier for layout. I am using accessibilitySortPriority modifier to maintain this reading order. Left Overlay View Horizontal Scroll Items Right Overlay View When voiceover is on and i do a single tap on views, the focus shifts to particular view as expected. But for the trailing overlay view, the focus does not shift to it as expected. Instead, the focus goes to the scroll item behind it.
0
0
23
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
167
Jul ’25
PHPickerViewController Not Offering public.hevc UTI for a Known HEVC Video
I'm working on an app where a user needs to select a video from their Photos library, and I need to get the original, unmodified HEVC (H.265) data stream to preserve its encoding. The Problem I have confirmed that my source videos are HEVC. I can record a new video with my iPhone 15 Pro Max camera set to "High Efficiency," export the "Unmodified Original" from Photos on my Mac, and verify that the codec is MPEG-H Part2/HEVC (H.265). However, when I select that exact same video in my app using PHPickerViewController, the itemProvider does not list public.hevc as an available type identifier. This forces me to fall back to a generic movie type, which results in the system providing me with a transcoded H.264 version of the video. Here is the debug output from my app after selecting a known HEVC video: ⚠️ 'public.hevc' not found. Falling back to generic movie type (likely H.264). What I've Tried My code explicitly checks for the public.hevc identifier in the registeredTypeIdentifiers array. Since it's not found, my HEVC-specific logic is never triggered. Here is a minimal version of my PHPickerViewControllerDelegate implementation: import UniformTypeIdentifiers // ... inside the Coordinator class ... func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) { picker.dismiss(animated: true) guard let result = results.first else { return } let itemProvider = result.itemProvider let hevcIdentifier = "public.hevc" let identifiers = itemProvider.registeredTypeIdentifiers print("Available formats from itemProvider: \(identifiers)") if identifiers.contains(hevcIdentifier) { print("✅ HEVC format found, requesting raw data...") itemProvider.loadDataRepresentation(forTypeIdentifier: hevcIdentifier) { (data, error) in // ... process H.265 data ... } } else { print("⚠️ 'public.hevc' not found. Falling back to generic movie type (likely H.264).") itemProvider.loadFileRepresentation(forTypeIdentifier: UTType.movie.identifier) { url, error in // ... process H.264 fallback ... } } } My Environment Device: iPhone 15 Pro Max iOS Version: iOS 18.5 Xcode Version: 16.2 My Questions Are there specific conditions (e.g., the video being HDR/Dolby Vision, Cinematic, or stored in iCloud) under which PHPickerViewController's itemProvider would intentionally not offer the public.hevc type identifier, even for an HEVC video? What is the definitive, recommended API sequence to guarantee that I receive the original, unmodified data stream for a video asset, ensuring that no transcoding to H.264 occurs during the process? Any insight into why public.hevc might be missing from the registeredTypeIdentifiers for a known HEVC asset would be greatly appreciated. Thank you.
3
0
95
Jul ’25
toolbarForegroundStyle has no effect on navigation title
On Apple Watch, I have used toolbarForegroundStyle view modifier to change the color of the navigation title programmatically to offer theming support for users. In watchOS 26 it no longer seem to have any effect. For example with .toolbarForegroundStyle(.blue, for: .navigationBar) the title color still uses the AccentColor from the Assets catalog. Is there any other setup required to get this working, or is it a bug? Filed a feedback FB18527395
2
0
113
Jul ’25
Dynamic Presentation Sheet Heights
In my application, I have NavigationStack presented as a sheet, and I intend to dynamically adjust its height while pushing views within it. I'm utilizing a global observable variable to manage the height and everything works fine except that the height changes abruptly without any animation. It abruptly transitions from one height to another. The issue can be reproduced using the following code: #Preview { @Previewable @State var height: CGFloat = 200 Text("Parent View") .sheet(isPresented: .constant(true)) { NavigationStack { Form { NavigationLink("Button") { RoundedRectangle(cornerRadius: 20) .fill(Color.blue) .frame(height: 200) .navigationTitle("Child") .onAppear { withAnimation { height = 300 } } } } .navigationTitle("Parent") .navigationBarTitleDisplayMode(.inline) .presentationDetents([.height(height)]) .onAppear { withAnimation { height = 150 } } } } }
3
0
84
Jul ’25
FKA Accessibility focus seems broken in SwiftUI
There are several ways we are supposed to be able to control a11y (accessibility) focus in FKA (Full Keyboard Access) mode. We should be able to set up an @AccessibilityFocusState variable that contains an enum for the different views that we want to receive a11y focus. That works from VO (VoiceOver) but not from FKA mode. See this sample project on Github: https://stackoverflow.com/questions/79067665/how-to-manage-accessibilityfocusstate-for-swiftui-accessibility-keyboard Similarly, we are supposed to be able to use accessibilitySortPriority to control the order that views are selected when a user using FKA tabs between views. That also works from VO but not from FKA mode. In the sample code below, the `.accessibilitySortPriority() ViewModifiers cause VO to change to a non-standard order when you swipe between views, but it has no effect in FKA mode. Is there a way to either set the a11y focus or change the order in which the views are selected that actually works in SwiftUI when the user is in FKA mode? Code that should cause FKA to tab between text fields in a custom order: struct ContentView: View { @State private var val1: String = "val 1" @State private var val2: String = "val 2" @State private var val3: String = "val 3" @State private var val4: String = "val 4" var body: some View { VStack { TextField("Value 1", text: $val1) .accessibilitySortPriority(3) VStack { TextField("Value 2", text: $val2) .accessibilitySortPriority(1) } HStack { TextField("Value 3", text: $val3) .accessibilitySortPriority(2) TextField("Value 4", text: $val4) .accessibilitySortPriority(4) } } .padding() } }```
4
0
168
Jul ’25
SwiftUI Transaction completion handler is being called unexpectedly
Unexpected SwiftUI Transaction Behavior This minimal example demonstrates an unexpected behavior in SwiftUI's Transaction API: var transaction = Transaction(animation: .none) transaction.addAnimationCompletion { print("This should not be called!") } The Issue The completion handler is called immediately after creation, even though the transaction was never used in any SwiftUI animation context (like withTransaction or other animation-related APIs). Expected vs Actual Behavior Expected: The completion handler should only be called after the transaction is actually used in a SwiftUI animation. Actual: The completion handler is called right after creation, regardless of whether the transaction is used or not. Current Workaround To avoid this, I'm forced to implement defensive programming: only creating transactions with completion handlers at the exact moment they're going to be used. This adds unnecessary complexity and goes against the intuitive usage of the Transactions API.
2
0
67
Jun ’25
tabViewBottomAccessory inline functionality missing?
Summary As presented in the SwiftUI WWDC video, the new tabViewBottomAccessory should allow for unique contents for .inline. This is what was presented as being used for the Apple Music miniplayer. However, the functionality seems to be either missing or unintuitive. As seen in the photos attached, not only does .inline functionality not seem to do anything, but the inline accessory also has misaligned elements that cannot be fixed by conditionally modifying the contents. Build Target iOS 26.0 Details This problem recurs on physical devices, simulators, and Xcode previews. Here is a view I've constructed for use as a tabViewBottomAccessory: struct FitnessToolbarAccessory: View { @Environment(\.tabViewBottomAccessoryPlacement) var placement var body: some View { if (placement == .inline) { Text("hello") } else { HStack { HStack { Image(systemName: "dumbbell.fill") VStack(alignment: .leading) { Text("Active Workout") Text("Push Day - Chest") .font(.system(size: 13)) } Spacer() Image(systemName: "pause.fill") } .padding() } } } } Here is the result, working as expected in expanded mode: And here is the result in inline mode after minimizing the tabViewBottomAccessory: The content of this inline accessory is clearly incorrect, as it was specified to contain a Text view containing "hello". Additionally, the contents seem to have some incorrect alignment. This occurs regardless of the contents of the accessory, even plain text.
1
1
104
Jun ’25
Replacement for ToolbarItems with .bottomBar placement in iOS 26 TabView?
Prior to iOS 26, ToolbarItems with .bottomBar placement were convenient for tab-specific frequent actions. With iOS 26’s new tab layering now obscuring such ToolbarItems, it’s unclear whether .tabViewBottomAccessory is the intended replacement or if another pattern (like persistent floating buttons) is encouraged instead. What’s the recommended way to support quick, tab-specific actions under the new system? I’ve tried conditionally rendering a .tabViewBottomAccessory based on the active tab, but this causes a crash, which I’ve reported as FB18479195.
4
2
258
Jul ’25
Crash when conditionally rendering .tabViewBottomAccessory with TabView(selection:) in SwiftUI on iOS 26
Summary When using .tabViewBottomAccessory in SwiftUI and conditionally rendering it based on the selected tab, the app crashes with a NSInternalInconsistencyException related to _bottomAccessory.displayStyle. Steps to Reproduce Create a SwiftUI TabView using a @SceneStorage selectedTab binding. Render a .tabViewBottomAccessory with conditional visibility tied to selectedTab == .storage. Switch between tabs. Return to the tab that conditionally shows the accessory (e.g., “Storage”). Expected Behavior SwiftUI should correctly add, remove, or show/hide the bottom accessory view without crashing. Actual Behavior The app crashes with the following error: Environment iOS version: iOS 26 seed 2 (23A5276f) Xcode: 26 Swift: 6.2 Device: iPhone 12 Pro I have opened a bug report with the FB number: FB18479195 Code Sample import SwiftUI struct ContentView: View { enum TabContent: String { case storage case recipe case profile case addItem } @SceneStorage("selectedTab") private var selectedTab: TabContent = .storage var body: some View { TabView(selection: $selectedTab) { Tab( "Storage", systemImage: "refrigerator", value: TabContent.storage ) { StorageView() } Tab( "Cook", systemImage: "frying.pan", value: TabContent.recipe ) { RecipeView() } Tab( "Profile", systemImage: "person", value: TabContent.profile ) { ProfileView() } } .tabBarMinimizeBehavior(.onScrollDown) .tabViewBottomAccessory { if selectedTab == .storage { Button(action: { }) { Label("Add Item", systemImage: "plus") } } } } }
3
1
259
Jun ’25
No more simulators showing in Xcode
I sometimes use Xcode 14.2. Recently, I have an issue with simulators: on some SwiftUI project, the simulator list is empty. I created a new project. I see the complete list of simulators, but when running for a simulator, it fails with following diag; Same error with UIKit project. Details Unable to boot the Simulator. Domain: NSPOSIXErrorDomain Code: 60 Failure Reason: launchd failed to respond. User Info: { DVTErrorCreationDateKey = "2025-06-29 06:16:35 +0000"; IDERunOperationFailingWorker = "_IDEInstalliPhoneSimulatorWorker"; Session = "com.apple.CoreSimulator.SimDevice.134EC197-BA6B-45DF-B5B2-61A1D4F14863"; } -- Failed to start launchd_sim: could not bind to session, launchd_sim may have crashed or quit responding Domain: com.apple.SimLaunchHostService.RequestError Code: 4 -- Analytics Event: com.apple.dt.IDERunOperationWorkerFinished : { "device_model" = "iPhone15,2"; "device_osBuild" = "16.2 (20C52)"; "device_platform" = "com.apple.platform.iphonesimulator"; "launchSession_schemeCommand" = Run; "launchSession_state" = 1; "launchSession_targetArch" = "x86_64"; "operation_duration_ms" = 8341; "operation_errorCode" = 60; "operation_errorDomain" = NSPOSIXErrorDomain; "operation_errorWorker" = "_IDEInstalliPhoneSimulatorWorker"; "operation_name" = IDERunOperationWorkerGroup; "param_consoleMode" = 0; "param_debugger_attachToExtensions" = 0; "param_debugger_attachToXPC" = 1; "param_debugger_type" = 3; "param_destination_isProxy" = 0; "param_destination_platform" = "com.apple.platform.iphonesimulator"; "param_diag_MainThreadChecker_stopOnIssue" = 0; "param_diag_MallocStackLogging_enableDuringAttach" = 0; "param_diag_MallocStackLogging_enableForXPC" = 1; "param_diag_allowLocationSimulation" = 1; "param_diag_checker_tpc_enable" = 1; "param_diag_gpu_frameCapture_enable" = 0; "param_diag_gpu_shaderValidation_enable" = 0; "param_diag_gpu_validation_enable" = 0; "param_diag_memoryGraphOnResourceException" = 0; "param_diag_queueDebugging_enable" = 1; "param_diag_runtimeProfile_generate" = 0; "param_diag_sanitizer_asan_enable" = 0; "param_diag_sanitizer_tsan_enable" = 0; "param_diag_sanitizer_tsan_stopOnIssue" = 0; "param_diag_sanitizer_ubsan_stopOnIssue" = 0; "param_diag_showNonLocalizedStrings" = 0; "param_diag_viewDebugging_enabled" = 1; "param_diag_viewDebugging_insertDylibOnLaunch" = 1; "param_install_style" = 0; "param_launcher_UID" = 2; "param_launcher_allowDeviceSensorReplayData" = 0; "param_launcher_kind" = 0; "param_launcher_style" = 0; "param_launcher_substyle" = 0; "param_runnable_appExtensionHostRunMode" = 0; "param_runnable_productType" = "com.apple.product-type.application"; "param_runnable_type" = 2; "param_testing_launchedForTesting" = 0; "param_testing_suppressSimulatorApp" = 0; "param_testing_usingCLI" = 0; "sdk_canonicalName" = "iphonesimulator16.2"; "sdk_osVersion" = "16.2"; "sdk_variant" = iphonesimulator; } -- System Information macOS Version 12.7.1 (Build 21G920) Xcode 14.2 (21534) (Build 14C18) Timestamp: 2025-06-29T08:16:35+02:00 I filed a bug report: FB18475006
1
0
148
Jun ’25
ImagePresentationComponent .spatialStereoImmersive mode not rendering in WindowGroup context
Platform: visionOS 2.6 Framework: RealityKit, SwiftUIComponent: ImagePresentationComponent I’m working with the new ImagePresentationComponent from visionOS 26 and hitting a rendering limitation when switching to .spatialStereoImmersive viewing mode within a WindowGroup context. This is what I’m seeing: Pure immersive space: ImagePresentationComponent with .spatialStereoImmersive mode works perfectly in a standalone ImmersiveSpace Mode switching API: All mode transitions work correctly (logs confirm the component updates) Spatial content: .spatialStereo mode renders correctly in both window and immersive contexts. This is where it’s breaking for me: Window context: When the same RealityView + ImagePresentationComponent is placed inside a WindowGroup (even when that window is floating in a mixed immersive space), switching to .spatialStereoImmersive mode shows no visual change The API calls succeed, state updates correctly, but the immersive content doesn’t render. Apple’s Spatial Gallery demonstrates exactly what I’m trying to achieve: Spatial photos displayed in a window with what feels like horizontal scroll view using system window control bar, etc. Tapping a spatial photo smoothly transitions it to immersive mode in-place. The immersive content appears to “grow” from the original window position by just changing IPC viewing modes. This proves the functionality should be possible, but I can’t determine the correct configuration. So, my question to is: Is there a specific RealityView or WindowGroup configuration required to enable immersive content rendering from window contexts that you know of? Are there bounds/clipping settings that need to be configured to allow immersive content to “break out” of window constraints? Does .spatialStereoImmersive require a specific rendering context that’s not available in windowed RealityView instances? How do you think Apple’s SG app achieves this functionality? For a little more context: All viewing modes are available: [.mono, .spatialStereo, .spatialStereoImmersive] The spatial photos are valid and work correctly in pure immersive space Mixed immersive space is active when testing window context No errors or warnings in console beyond the successful mode switching logs I’m getting Any insights into the proper configuration for window-hosted immersive content
1
1
141
4w
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
168
Jun ’25