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

White flash using manageSubscriptionsSheet in SwiftUI
In SwiftUI I am using the manageSubscriptionsSheet modifier to open the iOS subscription screen. When this is presented it immediately flashes a white view and then animated the subscription screen up from the bottom, it looks pretty bad. The view I am calling manageSubscriptionsSheet on is presented in a sheet, so maybe trying to present the subscriptions view as well is causing the visual glitch. Any way to not have this white flashing view when opening the subscription screen?
0
0
161
Oct ’25
How to detect modifier keys with hardware keyboard in SwiftUI (iOS)?
Hi everyone, In UIKit, I can detect which key and modifier keys are pressed from an external hardware keyboard using the pressesBegan method in a UIResponder: override func pressesBegan(_ presses: Set<UIPress>, with event: UIPressesEvent?) { for press in presses { if let key = press.key { print("Key: \(key.charactersIgnoringModifiers ?? "")") print("Modifiers: \(key.modifierFlags)") } } } I am now working in SwiftUI (iOS), and I couldn’t find a direct equivalent for pressesBegan. What is the recommended way in SwiftUI to detect modifier keys + key presses from an external keyboard? Is there a built-in API, or should I always wrap a UIKit view/controller for this purpose? Thanks in advance!
0
0
72
Sep ’25
ToolbarItems under tabView BottomBar on iOS26
The iOS with TabView places the .bottomBar toolbar items under the TabView items and does not raise them on top of them. iPadOS (when resized to a smaller width where the TabView places to the bottomBar) and previous iOS18 on iOS and iPadOS works correctly. Reported (FB20447249)
Topic: UI Frameworks SubTopic: SwiftUI
0
1
77
Sep ’25
empty push driven live activity
my dynamic island UI is triggering as empty when i send my curl, this is a pushToStart run push driven live activity and when i send my curl this is what appears, despite be being able to render the UI through a local push no problem, here is my curl. curl -v \ -H "apns-topic: MuscleMemory.KimchiLabs.com.push-type.liveactivity" \ -H "apns-push-type: liveactivity" \ -H "apns-priority: 10" \ -H "Content-Type: application/json" \ -H "authorization: bearer eyJhbGciOiJFUzI1NiIsImtpZCI6IjI4MjVTNjNEV0IifQ.eyJpc3MiOiJMOTZYUlBCSzQ2IiwiaWF0IjoxNzU4ODU2MDkyfQ.i83VbgROsxEzdgr512iQkVsp0FjHIoHq2L6IB2aL1fImJgX-XM6TM5frNnVyfva7haMd9fDGjO2D_wfCq8WnBg" \ --data '{ "aps": { "timestamp": '"$now"', "event": "start", "content-state": { "plain_text": "hello world", "userContentPage": ["hello world"] }, "attributes-type": "KimchiKit.DynamicRepAttributes", "attributes": { "activityID": "12345" }, "alert": { "title": "Workout started", "body": "We’ll show your reps on the Lock Screen.", "sound": "default" } } }' \ --http2 https://api.sandbox.push.apple.com/3/device/80d50a03472634d9381b729deec58a3e250ea0006b7acd7c2d6ef19e553dcdb010eb1434ff9a6907380f6ed3e9276d57d58f3cda3ac9fc3bea67abae116601a63ec77a34174fd271c4151ec898abae30 and heres my content state which resides in a shared module @available(iOS 17.0, *) public struct DynamicRepAttributes: ActivityAttributes, Codable { public struct ContentState: Codable, Hashable { public var plainText: String public var userContentPage: [String] public enum CodingKeys: String, CodingKey { case plainText = "plain_text" case userContentPage } public init(plainText: String, userContentPage: [String]) { self.plainText = plainText self.userContentPage = userContentPage } } public var activityID: String public init(activityID: String) { self.activityID = activityID } } Ive also alr verified my attributes type is correct, have been stuck on this issue would really appreciate the help
0
0
116
Sep ’25
SCStreamUpdateFrameContentRect X coordinate always returns 48 instead of expected 0
SCStreamUpdateFrameContentRect X coordinate always returns 48 instead of expected 0 Environment Device: MacBook Pro 13-inch macOS: Sequoia 15.6.1 Xcode: 16.4 Framework: Screen Capture Kit Issue Description I'm experiencing an unexpected behavior with Screen Capture Kit where the SCStreamUpdateFrameContentRect X coordinate consistently returns 48 instead of the expected 0. Code Context I'm using SCContentSharingPicker to capture screen content and implementing the SCStreamOutput protocol to receive frame data. In my stream(_:didOutputSampleBuffer:of:) method, I'm extracting the content rect information from the sample buffer attachments: func stream(_ stream: SCStream, didOutputSampleBuffer sampleBuffer: CMSampleBuffer, of type: SCStreamOutputType) { switch type { case .screen: guard let attachmentsArray = CMSampleBufferGetSampleAttachmentsArray(sampleBuffer, createIfNecessary: false) as? [[SCStreamFrameInfo: Any]] else { return } guard let attachments = attachmentsArray.first else { return } if !attachments.keys.contains(.contentRect) { return } print(attachments) // X coordinate always shows 48 /* , __C.SCStreamFrameInfo(_rawValue: SCStreamUpdateFrameContentRect): { Height = 540; Width = 864; X = 48; <<-- unexpected offset Y = 0; }] */ return // ... other cases } } Expected vs Actual Behavior Expected: X coordinate should be 0 (indicating the content starts at the left edge of the screen) Actual: X coordinate is consistently 48 Visual verification: When I display the captured screen content, it appears correctly without any offset, suggesting the actual content should indeed start at X=0 Additional Information The picker is configured with .singleDisplay mode I'm excluding the current app's bundle ID from capture The captured content visually appears correct, only the reported coordinates seem off Main ViewModel Class import Foundation import ScreenCaptureKit import SwiftUICore class VM: NSObject, ObservableObject, SCContentSharingPickerObserver, SCStreamDelegate, SCStreamOutput { @State var isRecording = false // Error handling delegate func stream(_ stream: SCStream, didStopWithError error: Error) { DispatchQueue.main.async { self.isRecording = false } } var picker: SCContentSharingPicker? func createPicker() -> SCContentSharingPicker { if let p = picker { return p } let picker = SCContentSharingPicker.shared picker.add(self) picker.isActive = true SCContentSharingPicker.shared.present(using: .display) return picker } var stream: SCStream? let videoSampleBufferQueue = DispatchQueue(label: "com.example.apple-samplecode.VideoSampleBufferQueue") // observer call back for picker func contentSharingPicker(_ picker: SCContentSharingPicker, didUpdateWith filter: SCContentFilter, for stream: SCStream?) { if let stream = stream { stream.updateContentFilter(filter) } else { let config = SCStreamConfiguration() config.capturesAudio = false config.captureMicrophone = false config.captureResolution = .automatic config.captureDynamicRange = .SDR config.showMouseClicks = false config.showsCursor = false // Set the frame rate for screen capture config.minimumFrameInterval = CMTime(value: 1, timescale: 5) // 10 FPS self.stream = SCStream(filter: filter, configuration: config, delegate: self) do { try self.stream?.addStreamOutput(self, type: .screen, sampleHandlerQueue: self.videoSampleBufferQueue) } catch { print("\(error)") } self.stream?.updateContentFilter(filter) DispatchQueue.main.async { self.stream?.startCapture() } } } func contentSharingPicker(_ picker: SCContentSharingPicker, didCancelFor stream: SCStream?) {} func contentSharingPickerStartDidFailWithError(_ error: any Error) { print(error) } func stream(_ stream: SCStream, didOutputSampleBuffer sampleBuffer: CMSampleBuffer, of type: SCStreamOutputType) { switch type { case .screen: guard let attachmentsArray = CMSampleBufferGetSampleAttachmentsArray(sampleBuffer, createIfNecessary: false) as? [[SCStreamFrameInfo: Any]] else { return } guard let attachments = attachmentsArray.first else { return } if !attachments.keys.contains(.contentRect) { return } print(attachments) return case .audio: return case .microphone: return @unknown default: return } } func outputVideoEffectDidStart(for stream: SCStream) { print("outputVideoEffectDidStart") } func outputVideoEffectDidStop(for stream: SCStream) { print("outputVideoEffectDidStop") } func streamDidBecomeActive(_ stream: SCStream) { print("streamDidBecomeActive") } func streamDidBecomeInactive(_ stream: SCStream) { print("streamDidBecomeInactive") } }
0
0
82
Sep ’25
SwiftUI TextField does not update its displayed text when I transform input inside a custom Binding
I’m trying to transform user keyboard input in a TextField so that, for example, whenever the user types the letter "a" it is stored and shown as the Greek letter "α". I created a custom Binding to intercept and modify the typed text before saving it to my observable model. Here’s a simplified version of my code: import SwiftUI class User: ObservableObject { @Published var username: String = "" } struct ContentView: View { @ObservedObject var user = User() var usernameBinding: Binding<String> { Binding( get: { user.username }, set: { newValue in // Replace all "a" with "α" user.username = newValue.replacingOccurrences(of: "a", with: "α") } ) } var body: some View { TextField("Username", text: usernameBinding) .padding() .onChange(of: user.username) { newValue in print("username changed to:", newValue) } } } When I type "a", I can see in the console that the onChange handler prints the transformed string ("α"), and the model (user.username) is updated. However, the TextField on screen still shows the original "a" instead of updating to "α" immediately. I expected the text field to update its displayed value whenever the bound property changes (since username is @Published on an ObservableObject), but that doesn’t seem to happen when I modify the text in the binding’s set closure. Is this a known limitation of SwiftUI TextField? Is there a better way to transform user input so the field shows the transformed text based on some processing? Any advice or explanation would be appreciated.
0
0
91
Sep ’25
Trigger save of a FileDocument in a DocumentGroup?
I have a DocumentGroup working with a FileDocument, and that's fine. However, when someone creates a new document I want them to have to immediately save it. This is the behavior on ipadOS and iOS from what I can understand (you select where before the file is created). There seems to be no way to do this on macOS? I basically want to have someone: create a new document enter some basic data hit "create" which saves the file then lets the user start editing it (1), (2), and (4) are done and fairly trivial. (3) seems impossible, though...? This really only needs to support macOS but any pointers would be appreciated.
0
0
288
Apr ’25
Showing space .navigationTitle leads to unexpected results.
I wanted to set navigationTitle value to space symbol on my iOS app (Swift 6, iOS 26.0) (so that navigationBar opens in large mode initially before the actual value is being fetched). In my view I used this: .navigationTitle(" ") And on device I got unexpectedly two quote symbols: Not sure if there is space in between, and the symbols look like opening and closing quote (both quotes in code I think are the same symbols) - so probably it's not part of my code is visible in UI as one might think... . Is this a bug? Or undocumented feature?
0
1
125
Sep ’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
192
Jun ’25
Nested NavigationSplitView has unexpected layout shift inside a TabView
I have initialized a new SwiftUI project for iOS. I wrapped the default NavigationSplitView from SwiftData inside a TabView and ran into the following issue: On an iPad (Air, 13 inch, iPadOs 26), the button to open/close the sidebar shifts downwards while opening or closing the sidebar. When the animation finishes, the button jumps back to the original position. Here's the code I used inside my ContentView: var body: some View { TabView { Tab("Kategorien", systemImage: "circle.fill") { NavigationSplitView { List { ForEach(items) { item in NavigationLink { Text("Item at \(item.timestamp, format: Date.FormatStyle(date: .numeric, time: .standard))") } label: { Text(item.timestamp, format: Date.FormatStyle(date: .numeric, time: .standard)) } } .onDelete(perform: deleteItems) } .toolbar { ToolbarItem(placement: .navigationBarTrailing) { EditButton() } ToolbarItem { Button(action: addItem) { Label("Add Item", systemImage: "plus") } } } } detail: { Text("Select an item") } } Tab("Alle Bücher", systemImage: "circle.fill") { Text("Alle Bücher") } } }
Topic: UI Frameworks SubTopic: SwiftUI
0
0
71
Sep ’25
Sorting of FetchResults in TableView broken in xcode 26
Previously, I sorted my FetchResult in a TableView like this: @FetchRequest( sortDescriptors: [SortDescriptor(\.rechnungsDatum, order: .forward)], predicate: NSPredicate(format: "betragEingang == nil OR betragEingang == 0") ) private var verguetungsantraege: FetchedResults&lt;VerguetungsAntraege&gt; ... body ... Table(of:VerguetungsAntraege.self, sortOrder: $verguetungsantraege.sortDescriptors) { TableColumn("date", value:\.rechnungsDatum) { item in Text(Formatters.dateFormatter.string(from: item.rechnungsDatum ?? Date()) ) } .width(120) TableColumn("rechNrKurz", value:\.rechnungsNummer) { item in Text(item.rechnungsNummer ?? "") } .width(120) TableColumn("betrag", value:\.totalSum ) { Text(Formatters.currencyFormatter.string(from: $0.totalSum as NSNumber) ?? "kein Wert") } .width(120) TableColumn("klient") { Text(db.getKlientNameByUUID(id: $0.klient ?? UUID(), moc: moc)) } } rows: { ForEach(Array(verguetungsantraege)) { antrag in TableRow(antrag) } } There seem to be changes here in Xcode 26. In any case, I always get the error message in each line with TableColumn("title", value: \.sortingField) Ambiguous use of 'init(_:value:content:)' Does anyone have any idea what's changed? Unfortunately, the documentation doesn't provide any information.
0
0
176
Jun ’25
SwiftUI TextField with lineLimit inside Form does not respect lineLimit.
macos 26, xcode 26, ios 26. Everytime when you add new line at some point (like after 10-20 lines) the TextField will ignore the lineLimit and start changing the height. The problem related to Form but not Scroll. Maybe it can be reproduced in other scroll-based views. Bug report opened. Any siggestions? struct Test: View { @State var text = "" var body: some View { Form { Section { TextField("", text: $text, axis: .vertical) .lineLimit(3) .background(Color.green) } } } } @main struct TestApp: App { var body: some Scene { WindowGroup { Test() } } }
0
0
77
Sep ’25
Alert Closures Not Firing + Navigation Animations Broken
Hi, I hope you are doing well. We have been running up against an issue in our application which despite our best efforts we cannot seem to solve. After a certain point of use (of which we cannot seem to isolate a trigger), something internally with the way SwiftUI handles animation transactions seems to be breaking. This results in the following behavior that we (and our users) are noticing: Alerts/Sheets/NavigationPath changes lose all animations Closures associated with buttons no longer fire at all. The alert disappears, but with no animation and any action associated with the button selected does nothing. This results in an infinite loop of triggering an alert, clicking on an alert action, and the alert dismissing without the corresponding action ever occurring. We have tried moving the navigationPath out of a view model (Observable) and into a @State variable on the view in case it was an issue with view pre-rendering due to path changes, but this did not improve our case. We hoisted the state and the alert presentation out of all subviews and onto the root view of our navigation destination (as this happens on a sub-page of the application) as well, and while did this seem to minimize occurrences it did not fully resolve it. The app structure of our watch app is as follows: We have a NavigationStack at the root level which wraps a TabView, containing 3 pages. Selecting a button triggers a navigation destination, presenting a detail view. The detail view is a ZStack which switches on a property contained in an @State Observable view model scoped to the detail view. The ZStack can contain one of 5 subviews, derived from a viewState enum with associated values (all of which are equatable, and by extension viewState is also an equatable type as well). One of the subviews receives a binding, which on button trigger updates the binding and thus the view containing the ZStack presents the alert. Sometimes, when this happens, the animations break, and then are subsequently broken for the remainder of the lifetime of the app until it is force-closed (not backgrounded, but a full force-close). NavigationStack { TabView { Tab1 Tab2 // triggers navigationDestination Tab3 } .navigationDestination(for:) { DestinationView() // the view containing the ZStack + Alert } } STEPS TO REPRODUCE Unfortunately we have not been able to ascertain exactly what is causing this issue as we cannot reproduce it in a sandbox environment, only when moving through the view flow associated with our code. Any debugging ideas or recommendations would be greatly appreciated, as we have already tried _printChanges and do not notice any erroneous view redraws.
Topic: UI Frameworks SubTopic: SwiftUI
0
0
88
Sep ’25
SwiftUI DocumentGroup blocks "Create Document" button when opening a document in conflict state
In a SwiftUI DocumentGroup, the "Create Document" button remains permanently disabled when attempting to open a document that is in a conflict state (e.g., due to simultaneous edits across devices). As a result, the user cannot create new documents, and the app becomes stuck. On macOS, the expected conflict resolution dialog appears, and the app continues to function normally. On iOS, however, the "Create Document" button stays disabled indefinitely. This behavior occurs consistently in a default SwiftUI document-based app. Steps to Reproduce: Create a new SwiftUI document-based project in Xcode; Setup iCloud Storage in Signing & Capabilities; Create an empty document and place it in a conflict state (e.g., save it simultaneously from two devices); Attempt to open the conflicted document on an iPhone or iPad; Expected Result: The user should be able to resolve the conflict and continue working; The "Create Document" button should remain functional; Actual Result: The "Create Document" button is disabled permanently; The app cannot create new documents until restarted; Environment; iOS 18, iOS 26 (latest tested); Xcode Version 16.4 (16F6) Reproduced on iPhone and iPad; Works as expected on macOS; This appears to be a blocking issue in SwiftUI’s DocumentGroup on iOS. FB20203775
0
0
139
Sep ’25
The @Environment(\.dismiss) value in SwiftUI for macOS does not dismiss a sheet presented by an NSWindowController.
I'm wondering what the correct, or recommended, way is to dismiss a SwiftUI that is being presented as a sheet hosted by an NSHostingController. The usual technique of invoking @Environment(\.dismiss) does not appear to work. Consider the code below. An NSWindowController is attempting to display a SwiftUI SettingsView as a sheet. The sheet is correctly presented, but the SettingsView is unable to dismiss itself. I am able to make it work by passing a closure into SettingsView that calls back to the NSWindowController but it's rather convoluted because SettingsView doesn't know the view controller that's hosting it until after SettingsView has been created, which means "finding" that view controller in the window controller to dismiss is more involved than it should be. Is there a better strategy to leverage here? final class MyViewController: NSViewController { @IBAction func buttonClicked(_ sender: NSButton) { if let presenter = window?.contentViewController { presenter.presentAsSheet(NSHostingController(rootView: SettingsView())) } } } struct SettingsView: View { @Environment(\.dismiss) private var dismiss var body: some View { VStack { Button("Cancel", role: .cancel) { dismiss() // This call does not dismiss the sheet. } .keyboardShortcut(.cancelAction) } } } Thank you. macOS 15.4.1 (24E263), Xcode 16.3 (16E140)
0
0
97
Apr ’25
Why does SwiftUI Text(date, style: .relative) show the same duration for different dates?
I’m using SwiftUI’s Text(_:style:) with the .relative style to show how long ago a date occurred. According to the docs: A style displaying a date as relative to now. I expected it to show the precise difference between a past date and the current date. However, I noticed that two dates that are 3 days apart both display the same relative string under certain conditions. Code snippet to reproduce- (using GMT time zone and the system calendar) IMPORTANT: To reproduce this, set your Mac’s system clock to 8 September 2025, 3:00 AM. SwiftUI’s relative style uses the current system time as its reference point, so changing the clock is necessary to see the behavior. Settings Mac is set to Central European Time zone (but this behaviour was also reproduced by one of my app's users in the US.) Mac OS Sequoia 15.5 XCode 16.4 tested on an iOS Simulator and a real iPhone both running iOS 18.5 struct TestDateView: View { var body: some View { // 8. July 10AM to 8. September 3AM = Shows 2 months 2 days let startDate1: Date = Calendar.current.date(from: .init(calendar: .current, timeZone: .gmt, year: 2025, month: 7, day: 8, hour: 10, minute: 0, second: 0))! // 5. July 10AM to 8. September 3AM = Shows 2 months 2 days let startDate2: Date = Calendar.current.date(from: .init(calendar: .current, timeZone: .gmt, year: 2025, month: 7, day: 5, hour: 10, minute: 0, second: 0))! // IMPORTANT!: Need to set MAC's clock to 8. September 3:00 AM to reproduce this bug VStack { Text(startDate1, style: .relative) Text(startDate2, style: .relative) } } } How exactly does the .relative style work internally? Is it expected that different dates can collapse into the same result like this, or is there a better way to use .relative to get more precise results? PS: I know about DateComponents and DateFormatter for exact calculations, but I’d like to understand this approach since it auto-updates natively with no timers or publishers.
0
0
108
Sep ’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
69
Apr ’25
iOS 26 Beta 9 dark/light traits behaviour
I want to check if this behaviour is legit in iOS 26 Beta: We have an admittedly stranger setup where a child view controller acts as a TabBar and is a UIHostingController so that we can use SwiftUI for the tab bar items. One of the tab pages has a scrollview whose content (imagine a chat view) might go from a lighter aspect to darker colors and back when scrolling. When we scroll to predominantly dark bubbles, the trait of the tabBar changes to dark mode. The function traitCollectionDidChange() on the UIHostingController is called ! but only for the tabBar controller. I know that in iOS there is some blending going on at the tabBar level when scrolling, but changing just one view + subviews to dark mode, automatically, instead of user triggered? It might be some optimisation if the view is considered opaque? But then I would expect to not change anything visually, if opaque. Is this expected behaviour on iOS 26? And if so, can we disable it? But just this blending/ trait changing, and keep the user triggered trait changes.
Topic: UI Frameworks SubTopic: SwiftUI
0
0
207
Sep ’25
timeline method is not being called for AppIntentTimelineProvider implementation on iOS 17 only
I have a widget that runs well on iOS 18. It is configurable and implements AppIntentTimelineProvider on the Provider. On iOS 17 it will call the placeholder method 7 times and not call the timeline method. The configuration intent implements WidgetConfigurationIntent. I've looked through the console logs and saw "ApplicationExtension record not found" but I'm not sure where to go from there. Why would the same widget work fine on iOS 18 and not 17? If I implement TimelineProvider and use a StaticConfiguration it works on iOS 17. Any help / guidance would be appreciated.
0
0
121
Jun ’25
White flash using manageSubscriptionsSheet in SwiftUI
In SwiftUI I am using the manageSubscriptionsSheet modifier to open the iOS subscription screen. When this is presented it immediately flashes a white view and then animated the subscription screen up from the bottom, it looks pretty bad. The view I am calling manageSubscriptionsSheet on is presented in a sheet, so maybe trying to present the subscriptions view as well is causing the visual glitch. Any way to not have this white flashing view when opening the subscription screen?
Replies
0
Boosts
0
Views
161
Activity
Oct ’25
How to detect modifier keys with hardware keyboard in SwiftUI (iOS)?
Hi everyone, In UIKit, I can detect which key and modifier keys are pressed from an external hardware keyboard using the pressesBegan method in a UIResponder: override func pressesBegan(_ presses: Set<UIPress>, with event: UIPressesEvent?) { for press in presses { if let key = press.key { print("Key: \(key.charactersIgnoringModifiers ?? "")") print("Modifiers: \(key.modifierFlags)") } } } I am now working in SwiftUI (iOS), and I couldn’t find a direct equivalent for pressesBegan. What is the recommended way in SwiftUI to detect modifier keys + key presses from an external keyboard? Is there a built-in API, or should I always wrap a UIKit view/controller for this purpose? Thanks in advance!
Replies
0
Boosts
0
Views
72
Activity
Sep ’25
ToolbarItems under tabView BottomBar on iOS26
The iOS with TabView places the .bottomBar toolbar items under the TabView items and does not raise them on top of them. iPadOS (when resized to a smaller width where the TabView places to the bottomBar) and previous iOS18 on iOS and iPadOS works correctly. Reported (FB20447249)
Topic: UI Frameworks SubTopic: SwiftUI
Replies
0
Boosts
1
Views
77
Activity
Sep ’25
empty push driven live activity
my dynamic island UI is triggering as empty when i send my curl, this is a pushToStart run push driven live activity and when i send my curl this is what appears, despite be being able to render the UI through a local push no problem, here is my curl. curl -v \ -H "apns-topic: MuscleMemory.KimchiLabs.com.push-type.liveactivity" \ -H "apns-push-type: liveactivity" \ -H "apns-priority: 10" \ -H "Content-Type: application/json" \ -H "authorization: bearer eyJhbGciOiJFUzI1NiIsImtpZCI6IjI4MjVTNjNEV0IifQ.eyJpc3MiOiJMOTZYUlBCSzQ2IiwiaWF0IjoxNzU4ODU2MDkyfQ.i83VbgROsxEzdgr512iQkVsp0FjHIoHq2L6IB2aL1fImJgX-XM6TM5frNnVyfva7haMd9fDGjO2D_wfCq8WnBg" \ --data '{ "aps": { "timestamp": '"$now"', "event": "start", "content-state": { "plain_text": "hello world", "userContentPage": ["hello world"] }, "attributes-type": "KimchiKit.DynamicRepAttributes", "attributes": { "activityID": "12345" }, "alert": { "title": "Workout started", "body": "We’ll show your reps on the Lock Screen.", "sound": "default" } } }' \ --http2 https://api.sandbox.push.apple.com/3/device/80d50a03472634d9381b729deec58a3e250ea0006b7acd7c2d6ef19e553dcdb010eb1434ff9a6907380f6ed3e9276d57d58f3cda3ac9fc3bea67abae116601a63ec77a34174fd271c4151ec898abae30 and heres my content state which resides in a shared module @available(iOS 17.0, *) public struct DynamicRepAttributes: ActivityAttributes, Codable { public struct ContentState: Codable, Hashable { public var plainText: String public var userContentPage: [String] public enum CodingKeys: String, CodingKey { case plainText = "plain_text" case userContentPage } public init(plainText: String, userContentPage: [String]) { self.plainText = plainText self.userContentPage = userContentPage } } public var activityID: String public init(activityID: String) { self.activityID = activityID } } Ive also alr verified my attributes type is correct, have been stuck on this issue would really appreciate the help
Replies
0
Boosts
0
Views
116
Activity
Sep ’25
SwiftUI PhotoPicker always warning in swift6.2
When I migrate to swift6.2, the photopicker always giving the warning like below: Call to main actor-isolated initializer 'xxxfunction' in a synchronous nonisolated context it's so weird,because no matter it's a viewbuilder or a struct view,it can't fix the warning.
Replies
0
Boosts
0
Views
108
Activity
Oct ’25
SCStreamUpdateFrameContentRect X coordinate always returns 48 instead of expected 0
SCStreamUpdateFrameContentRect X coordinate always returns 48 instead of expected 0 Environment Device: MacBook Pro 13-inch macOS: Sequoia 15.6.1 Xcode: 16.4 Framework: Screen Capture Kit Issue Description I'm experiencing an unexpected behavior with Screen Capture Kit where the SCStreamUpdateFrameContentRect X coordinate consistently returns 48 instead of the expected 0. Code Context I'm using SCContentSharingPicker to capture screen content and implementing the SCStreamOutput protocol to receive frame data. In my stream(_:didOutputSampleBuffer:of:) method, I'm extracting the content rect information from the sample buffer attachments: func stream(_ stream: SCStream, didOutputSampleBuffer sampleBuffer: CMSampleBuffer, of type: SCStreamOutputType) { switch type { case .screen: guard let attachmentsArray = CMSampleBufferGetSampleAttachmentsArray(sampleBuffer, createIfNecessary: false) as? [[SCStreamFrameInfo: Any]] else { return } guard let attachments = attachmentsArray.first else { return } if !attachments.keys.contains(.contentRect) { return } print(attachments) // X coordinate always shows 48 /* , __C.SCStreamFrameInfo(_rawValue: SCStreamUpdateFrameContentRect): { Height = 540; Width = 864; X = 48; <<-- unexpected offset Y = 0; }] */ return // ... other cases } } Expected vs Actual Behavior Expected: X coordinate should be 0 (indicating the content starts at the left edge of the screen) Actual: X coordinate is consistently 48 Visual verification: When I display the captured screen content, it appears correctly without any offset, suggesting the actual content should indeed start at X=0 Additional Information The picker is configured with .singleDisplay mode I'm excluding the current app's bundle ID from capture The captured content visually appears correct, only the reported coordinates seem off Main ViewModel Class import Foundation import ScreenCaptureKit import SwiftUICore class VM: NSObject, ObservableObject, SCContentSharingPickerObserver, SCStreamDelegate, SCStreamOutput { @State var isRecording = false // Error handling delegate func stream(_ stream: SCStream, didStopWithError error: Error) { DispatchQueue.main.async { self.isRecording = false } } var picker: SCContentSharingPicker? func createPicker() -> SCContentSharingPicker { if let p = picker { return p } let picker = SCContentSharingPicker.shared picker.add(self) picker.isActive = true SCContentSharingPicker.shared.present(using: .display) return picker } var stream: SCStream? let videoSampleBufferQueue = DispatchQueue(label: "com.example.apple-samplecode.VideoSampleBufferQueue") // observer call back for picker func contentSharingPicker(_ picker: SCContentSharingPicker, didUpdateWith filter: SCContentFilter, for stream: SCStream?) { if let stream = stream { stream.updateContentFilter(filter) } else { let config = SCStreamConfiguration() config.capturesAudio = false config.captureMicrophone = false config.captureResolution = .automatic config.captureDynamicRange = .SDR config.showMouseClicks = false config.showsCursor = false // Set the frame rate for screen capture config.minimumFrameInterval = CMTime(value: 1, timescale: 5) // 10 FPS self.stream = SCStream(filter: filter, configuration: config, delegate: self) do { try self.stream?.addStreamOutput(self, type: .screen, sampleHandlerQueue: self.videoSampleBufferQueue) } catch { print("\(error)") } self.stream?.updateContentFilter(filter) DispatchQueue.main.async { self.stream?.startCapture() } } } func contentSharingPicker(_ picker: SCContentSharingPicker, didCancelFor stream: SCStream?) {} func contentSharingPickerStartDidFailWithError(_ error: any Error) { print(error) } func stream(_ stream: SCStream, didOutputSampleBuffer sampleBuffer: CMSampleBuffer, of type: SCStreamOutputType) { switch type { case .screen: guard let attachmentsArray = CMSampleBufferGetSampleAttachmentsArray(sampleBuffer, createIfNecessary: false) as? [[SCStreamFrameInfo: Any]] else { return } guard let attachments = attachmentsArray.first else { return } if !attachments.keys.contains(.contentRect) { return } print(attachments) return case .audio: return case .microphone: return @unknown default: return } } func outputVideoEffectDidStart(for stream: SCStream) { print("outputVideoEffectDidStart") } func outputVideoEffectDidStop(for stream: SCStream) { print("outputVideoEffectDidStop") } func streamDidBecomeActive(_ stream: SCStream) { print("streamDidBecomeActive") } func streamDidBecomeInactive(_ stream: SCStream) { print("streamDidBecomeInactive") } }
Replies
0
Boosts
0
Views
82
Activity
Sep ’25
SwiftUI TextField does not update its displayed text when I transform input inside a custom Binding
I’m trying to transform user keyboard input in a TextField so that, for example, whenever the user types the letter "a" it is stored and shown as the Greek letter "α". I created a custom Binding to intercept and modify the typed text before saving it to my observable model. Here’s a simplified version of my code: import SwiftUI class User: ObservableObject { @Published var username: String = "" } struct ContentView: View { @ObservedObject var user = User() var usernameBinding: Binding<String> { Binding( get: { user.username }, set: { newValue in // Replace all "a" with "α" user.username = newValue.replacingOccurrences(of: "a", with: "α") } ) } var body: some View { TextField("Username", text: usernameBinding) .padding() .onChange(of: user.username) { newValue in print("username changed to:", newValue) } } } When I type "a", I can see in the console that the onChange handler prints the transformed string ("α"), and the model (user.username) is updated. However, the TextField on screen still shows the original "a" instead of updating to "α" immediately. I expected the text field to update its displayed value whenever the bound property changes (since username is @Published on an ObservableObject), but that doesn’t seem to happen when I modify the text in the binding’s set closure. Is this a known limitation of SwiftUI TextField? Is there a better way to transform user input so the field shows the transformed text based on some processing? Any advice or explanation would be appreciated.
Replies
0
Boosts
0
Views
91
Activity
Sep ’25
Trigger save of a FileDocument in a DocumentGroup?
I have a DocumentGroup working with a FileDocument, and that's fine. However, when someone creates a new document I want them to have to immediately save it. This is the behavior on ipadOS and iOS from what I can understand (you select where before the file is created). There seems to be no way to do this on macOS? I basically want to have someone: create a new document enter some basic data hit "create" which saves the file then lets the user start editing it (1), (2), and (4) are done and fairly trivial. (3) seems impossible, though...? This really only needs to support macOS but any pointers would be appreciated.
Replies
0
Boosts
0
Views
288
Activity
Apr ’25
Showing space .navigationTitle leads to unexpected results.
I wanted to set navigationTitle value to space symbol on my iOS app (Swift 6, iOS 26.0) (so that navigationBar opens in large mode initially before the actual value is being fetched). In my view I used this: .navigationTitle(" ") And on device I got unexpectedly two quote symbols: Not sure if there is space in between, and the symbols look like opening and closing quote (both quotes in code I think are the same symbols) - so probably it's not part of my code is visible in UI as one might think... . Is this a bug? Or undocumented feature?
Replies
0
Boosts
1
Views
125
Activity
Sep ’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
192
Activity
Jun ’25
Nested NavigationSplitView has unexpected layout shift inside a TabView
I have initialized a new SwiftUI project for iOS. I wrapped the default NavigationSplitView from SwiftData inside a TabView and ran into the following issue: On an iPad (Air, 13 inch, iPadOs 26), the button to open/close the sidebar shifts downwards while opening or closing the sidebar. When the animation finishes, the button jumps back to the original position. Here's the code I used inside my ContentView: var body: some View { TabView { Tab("Kategorien", systemImage: "circle.fill") { NavigationSplitView { List { ForEach(items) { item in NavigationLink { Text("Item at \(item.timestamp, format: Date.FormatStyle(date: .numeric, time: .standard))") } label: { Text(item.timestamp, format: Date.FormatStyle(date: .numeric, time: .standard)) } } .onDelete(perform: deleteItems) } .toolbar { ToolbarItem(placement: .navigationBarTrailing) { EditButton() } ToolbarItem { Button(action: addItem) { Label("Add Item", systemImage: "plus") } } } } detail: { Text("Select an item") } } Tab("Alle Bücher", systemImage: "circle.fill") { Text("Alle Bücher") } } }
Topic: UI Frameworks SubTopic: SwiftUI
Replies
0
Boosts
0
Views
71
Activity
Sep ’25
Sorting of FetchResults in TableView broken in xcode 26
Previously, I sorted my FetchResult in a TableView like this: @FetchRequest( sortDescriptors: [SortDescriptor(\.rechnungsDatum, order: .forward)], predicate: NSPredicate(format: "betragEingang == nil OR betragEingang == 0") ) private var verguetungsantraege: FetchedResults&lt;VerguetungsAntraege&gt; ... body ... Table(of:VerguetungsAntraege.self, sortOrder: $verguetungsantraege.sortDescriptors) { TableColumn("date", value:\.rechnungsDatum) { item in Text(Formatters.dateFormatter.string(from: item.rechnungsDatum ?? Date()) ) } .width(120) TableColumn("rechNrKurz", value:\.rechnungsNummer) { item in Text(item.rechnungsNummer ?? "") } .width(120) TableColumn("betrag", value:\.totalSum ) { Text(Formatters.currencyFormatter.string(from: $0.totalSum as NSNumber) ?? "kein Wert") } .width(120) TableColumn("klient") { Text(db.getKlientNameByUUID(id: $0.klient ?? UUID(), moc: moc)) } } rows: { ForEach(Array(verguetungsantraege)) { antrag in TableRow(antrag) } } There seem to be changes here in Xcode 26. In any case, I always get the error message in each line with TableColumn("title", value: \.sortingField) Ambiguous use of 'init(_:value:content:)' Does anyone have any idea what's changed? Unfortunately, the documentation doesn't provide any information.
Replies
0
Boosts
0
Views
176
Activity
Jun ’25
SwiftUI TextField with lineLimit inside Form does not respect lineLimit.
macos 26, xcode 26, ios 26. Everytime when you add new line at some point (like after 10-20 lines) the TextField will ignore the lineLimit and start changing the height. The problem related to Form but not Scroll. Maybe it can be reproduced in other scroll-based views. Bug report opened. Any siggestions? struct Test: View { @State var text = "" var body: some View { Form { Section { TextField("", text: $text, axis: .vertical) .lineLimit(3) .background(Color.green) } } } } @main struct TestApp: App { var body: some Scene { WindowGroup { Test() } } }
Replies
0
Boosts
0
Views
77
Activity
Sep ’25
Alert Closures Not Firing + Navigation Animations Broken
Hi, I hope you are doing well. We have been running up against an issue in our application which despite our best efforts we cannot seem to solve. After a certain point of use (of which we cannot seem to isolate a trigger), something internally with the way SwiftUI handles animation transactions seems to be breaking. This results in the following behavior that we (and our users) are noticing: Alerts/Sheets/NavigationPath changes lose all animations Closures associated with buttons no longer fire at all. The alert disappears, but with no animation and any action associated with the button selected does nothing. This results in an infinite loop of triggering an alert, clicking on an alert action, and the alert dismissing without the corresponding action ever occurring. We have tried moving the navigationPath out of a view model (Observable) and into a @State variable on the view in case it was an issue with view pre-rendering due to path changes, but this did not improve our case. We hoisted the state and the alert presentation out of all subviews and onto the root view of our navigation destination (as this happens on a sub-page of the application) as well, and while did this seem to minimize occurrences it did not fully resolve it. The app structure of our watch app is as follows: We have a NavigationStack at the root level which wraps a TabView, containing 3 pages. Selecting a button triggers a navigation destination, presenting a detail view. The detail view is a ZStack which switches on a property contained in an @State Observable view model scoped to the detail view. The ZStack can contain one of 5 subviews, derived from a viewState enum with associated values (all of which are equatable, and by extension viewState is also an equatable type as well). One of the subviews receives a binding, which on button trigger updates the binding and thus the view containing the ZStack presents the alert. Sometimes, when this happens, the animations break, and then are subsequently broken for the remainder of the lifetime of the app until it is force-closed (not backgrounded, but a full force-close). NavigationStack { TabView { Tab1 Tab2 // triggers navigationDestination Tab3 } .navigationDestination(for:) { DestinationView() // the view containing the ZStack + Alert } } STEPS TO REPRODUCE Unfortunately we have not been able to ascertain exactly what is causing this issue as we cannot reproduce it in a sandbox environment, only when moving through the view flow associated with our code. Any debugging ideas or recommendations would be greatly appreciated, as we have already tried _printChanges and do not notice any erroneous view redraws.
Topic: UI Frameworks SubTopic: SwiftUI
Replies
0
Boosts
0
Views
88
Activity
Sep ’25
SwiftUI DocumentGroup blocks "Create Document" button when opening a document in conflict state
In a SwiftUI DocumentGroup, the "Create Document" button remains permanently disabled when attempting to open a document that is in a conflict state (e.g., due to simultaneous edits across devices). As a result, the user cannot create new documents, and the app becomes stuck. On macOS, the expected conflict resolution dialog appears, and the app continues to function normally. On iOS, however, the "Create Document" button stays disabled indefinitely. This behavior occurs consistently in a default SwiftUI document-based app. Steps to Reproduce: Create a new SwiftUI document-based project in Xcode; Setup iCloud Storage in Signing & Capabilities; Create an empty document and place it in a conflict state (e.g., save it simultaneously from two devices); Attempt to open the conflicted document on an iPhone or iPad; Expected Result: The user should be able to resolve the conflict and continue working; The "Create Document" button should remain functional; Actual Result: The "Create Document" button is disabled permanently; The app cannot create new documents until restarted; Environment; iOS 18, iOS 26 (latest tested); Xcode Version 16.4 (16F6) Reproduced on iPhone and iPad; Works as expected on macOS; This appears to be a blocking issue in SwiftUI’s DocumentGroup on iOS. FB20203775
Replies
0
Boosts
0
Views
139
Activity
Sep ’25
The @Environment(\.dismiss) value in SwiftUI for macOS does not dismiss a sheet presented by an NSWindowController.
I'm wondering what the correct, or recommended, way is to dismiss a SwiftUI that is being presented as a sheet hosted by an NSHostingController. The usual technique of invoking @Environment(\.dismiss) does not appear to work. Consider the code below. An NSWindowController is attempting to display a SwiftUI SettingsView as a sheet. The sheet is correctly presented, but the SettingsView is unable to dismiss itself. I am able to make it work by passing a closure into SettingsView that calls back to the NSWindowController but it's rather convoluted because SettingsView doesn't know the view controller that's hosting it until after SettingsView has been created, which means "finding" that view controller in the window controller to dismiss is more involved than it should be. Is there a better strategy to leverage here? final class MyViewController: NSViewController { @IBAction func buttonClicked(_ sender: NSButton) { if let presenter = window?.contentViewController { presenter.presentAsSheet(NSHostingController(rootView: SettingsView())) } } } struct SettingsView: View { @Environment(\.dismiss) private var dismiss var body: some View { VStack { Button("Cancel", role: .cancel) { dismiss() // This call does not dismiss the sheet. } .keyboardShortcut(.cancelAction) } } } Thank you. macOS 15.4.1 (24E263), Xcode 16.3 (16E140)
Replies
0
Boosts
0
Views
97
Activity
Apr ’25
Why does SwiftUI Text(date, style: .relative) show the same duration for different dates?
I’m using SwiftUI’s Text(_:style:) with the .relative style to show how long ago a date occurred. According to the docs: A style displaying a date as relative to now. I expected it to show the precise difference between a past date and the current date. However, I noticed that two dates that are 3 days apart both display the same relative string under certain conditions. Code snippet to reproduce- (using GMT time zone and the system calendar) IMPORTANT: To reproduce this, set your Mac’s system clock to 8 September 2025, 3:00 AM. SwiftUI’s relative style uses the current system time as its reference point, so changing the clock is necessary to see the behavior. Settings Mac is set to Central European Time zone (but this behaviour was also reproduced by one of my app's users in the US.) Mac OS Sequoia 15.5 XCode 16.4 tested on an iOS Simulator and a real iPhone both running iOS 18.5 struct TestDateView: View { var body: some View { // 8. July 10AM to 8. September 3AM = Shows 2 months 2 days let startDate1: Date = Calendar.current.date(from: .init(calendar: .current, timeZone: .gmt, year: 2025, month: 7, day: 8, hour: 10, minute: 0, second: 0))! // 5. July 10AM to 8. September 3AM = Shows 2 months 2 days let startDate2: Date = Calendar.current.date(from: .init(calendar: .current, timeZone: .gmt, year: 2025, month: 7, day: 5, hour: 10, minute: 0, second: 0))! // IMPORTANT!: Need to set MAC's clock to 8. September 3:00 AM to reproduce this bug VStack { Text(startDate1, style: .relative) Text(startDate2, style: .relative) } } } How exactly does the .relative style work internally? Is it expected that different dates can collapse into the same result like this, or is there a better way to use .relative to get more precise results? PS: I know about DateComponents and DateFormatter for exact calculations, but I’d like to understand this approach since it auto-updates natively with no timers or publishers.
Replies
0
Boosts
0
Views
108
Activity
Sep ’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
69
Activity
Apr ’25
iOS 26 Beta 9 dark/light traits behaviour
I want to check if this behaviour is legit in iOS 26 Beta: We have an admittedly stranger setup where a child view controller acts as a TabBar and is a UIHostingController so that we can use SwiftUI for the tab bar items. One of the tab pages has a scrollview whose content (imagine a chat view) might go from a lighter aspect to darker colors and back when scrolling. When we scroll to predominantly dark bubbles, the trait of the tabBar changes to dark mode. The function traitCollectionDidChange() on the UIHostingController is called ! but only for the tabBar controller. I know that in iOS there is some blending going on at the tabBar level when scrolling, but changing just one view + subviews to dark mode, automatically, instead of user triggered? It might be some optimisation if the view is considered opaque? But then I would expect to not change anything visually, if opaque. Is this expected behaviour on iOS 26? And if so, can we disable it? But just this blending/ trait changing, and keep the user triggered trait changes.
Topic: UI Frameworks SubTopic: SwiftUI
Replies
0
Boosts
0
Views
207
Activity
Sep ’25
timeline method is not being called for AppIntentTimelineProvider implementation on iOS 17 only
I have a widget that runs well on iOS 18. It is configurable and implements AppIntentTimelineProvider on the Provider. On iOS 17 it will call the placeholder method 7 times and not call the timeline method. The configuration intent implements WidgetConfigurationIntent. I've looked through the console logs and saw "ApplicationExtension record not found" but I'm not sure where to go from there. Why would the same widget work fine on iOS 18 and not 17? If I implement TimelineProvider and use a StaticConfiguration it works on iOS 17. Any help / guidance would be appreciated.
Replies
0
Boosts
0
Views
121
Activity
Jun ’25