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

SwiftUI Documentation

Post

Replies

Boosts

Views

Activity

iOS 18 changes the order of Document-based SwiftUI document reading and view loading?
It looks like iOS 18 app changed the way document-based SwiftUI apps function in a way that breaks our app. Previously, a ReferenceFileDocument would run its init(configuration:) function before any SwiftUI views would load. Now, it runs it after SwiftUI views load and their onAppear modifiers run. Because we use a reference-type data model, our views reference a different object than the one loaded from our document's content. Much of our app's functionality is broken, and file saving doesn't work (because the data model writing to disk isn't connected to the views) I filed a bug report, but this seems like a wild change that should affect more than just us. It wasn't happening earlier in the iOS betas. It feels like it only got added in the last beta, but I'm not sure. Has anyone else run into this, or have any guidance for how best to deal with this?
2
2
134
2w
Problems trying to call reloadAllTimelines() multiple times from an AppIntent
My app focuses on a particular day and in the app I have arrow buttons that let you switch to the next or previous day. When one of them is pressed I call WidgetCenter.shared.reloadAllTimelines(). Almost immediately, regardless of how many times they are pressed, I will usually see my widgets immediately update to reflect the new day. I thought it would be nice to extend this functionality to Lock Screen controls. I had the AppIntent the Lock Screen buttons use call some of the same code that the arrow buttons in my app do, which includes a call to WidgetCenter.shared.reloadAllTimelines(). In the simulator it seemed to work great. I could see my Lock Screen widgets update almost immediately to focus on the new day. However, when I tried it on an actual device it was a much different story. Usually the first button press will update the widgets but after that it can be much, much longer before the Lock Screen widgets eventually refresh. It makes sense that the system is probably throttling my requests but is there a way to prevent this so that my Lock Screen controls operate the same way as buttons in my app?
0
0
104
2w
VoiceOver ignoring a data series when there are multiple ones
I can't figure out if I've found a VoiceOver problem with Swift Charts or if I'm doing something incorrectly. I have a loop within a loop showing 2 sets of data in the same chart. If I touch a month then VO correctly says there are two data series. But if I keep swiping down only data from the first series is read. ChatGPT said try referencing the outer loop and sure enough that worked if it done in BOTH the label and value. It sounds really awkward though. For example, "High 89 degrees F High October". Below the "bad" chart only says something such as "92 degrees F October" when swiping down. The "good" chart will read the high and low temperature data. VStack { headerText("BAD") Chart { ForEach(processedMonthlyInput) { oneMonth in ForEach(oneMonth.temperatures, id: \.month) { element in LineMark( x: .value("Month", element.month, unit: .month), y: .value("Temperature", element.tempVal.converted(to: .fahrenheit).value) ) .accessibilityLabel("\(element.month.formatted(.dateTime.month(.wide)))") .accessibilityValue(Text("\(element.tempVal.converted(to: tempUnit).formatted(.measurement(width: .abbreviated, numberFormatStyle: .number.precision(.fractionLength(0)))))")) } .symbol(by: .value("Type", oneMonth.theType)) .foregroundStyle(by: .value("Type", oneMonth.theType)) .interpolationMethod(.catmullRom) } } .frame(maxHeight: paddingAmount) .padding(.horizontal) headerText("GOOD") Chart { ForEach(processedMonthlyInput) { oneMonth in ForEach(oneMonth.temperatures, id: \.month) { element in LineMark( x: .value("Month", element.month, unit: .month), y: .value("Temperature", element.tempVal.converted(to: .fahrenheit).value) ) .accessibilityLabel("\(oneMonth.theType) \(element.month.formatted(.dateTime.month(.wide)))") .accessibilityValue(Text("\(oneMonth.theType) \(element.tempVal.converted(to: tempUnit).formatted(.measurement(width: .abbreviated, numberFormatStyle: .number.precision(.fractionLength(0)))))")) } .symbol(by: .value("Type", oneMonth.theType)) .foregroundStyle(by: .value("Type", oneMonth.theType)) .interpolationMethod(.catmullRom) } } .frame(maxHeight: paddingAmount) .padding(.horizontal) }
0
0
107
2w
Using ContactAccessButton freezes the entire app
When using both the ContactsAccessButton demo project, as well as when implementing it in my own, the whole app freezes after entering a few characters and searching through contacts. I don't know if this is necessarily reproducable because it's probably related to the contacts in my contact book. Typing in "Lex" does not freeze the app, but typing in "Adam No" freezes it. I get the following console error before my app freezes and I'm forced to force quit it: #ContactsButton Failed to get service proxy: Error Domain=NSCocoaErrorDomain Code=4097 "connection to service with pid 3387 named com.apple.ContactsUI.ContactsButtonXPCService" UserInfo={NSDebugDescription=connection to service with pid 3387 named com.apple.ContactsUI.ContactsButtonXPCService} #ContactsButton Failed to get remote content: nil (got this a number of times ContactsAccessButton really doesn't seem production ready...
1
1
160
2w
Springboard crash when trying to add Control Widget
Xcode 16, iOS 18 official release. On both my phone and simulator, when I build the release build of my app, when I go to control center and select "Add a Control", springboard crashes (see attached crash log). Somehow this does not happen in debug config, with debug config (which does have a different bundle ID but everything else is the same) I'm able to add the control widget just fine. The widget code is taken directly from the Apple docs: struct WidgetTestWidgetControl: ControlWidget { static let kind: String = "com.myapp.WidgetTestWidget" var body: some ControlWidgetConfiguration { AppIntentControlConfiguration( kind: Self.kind, provider: Provider() ) { value in ControlWidgetToggle( "Start Timer", isOn: value.isRunning, action: StartTimerIntent(value.name) ) { isRunning in Label(isRunning ? "On" : "Off", systemImage: "timer") } } .displayName("Timer") .description("A an example control that runs a timer.") } } extension WidgetTestWidgetControl { struct Value { var isRunning: Bool var name: String } struct Provider: AppIntentControlValueProvider { func previewValue(configuration: TimerConfiguration) -> Value { WidgetTestWidgetControl.Value(isRunning: false, name: configuration.timerName) } func currentValue(configuration: TimerConfiguration) async throws -> Value { let isRunning = true // Check if the timer is running return WidgetTestWidgetControl.Value(isRunning: isRunning, name: configuration.timerName) } } } struct TimerConfiguration: ControlConfigurationIntent { static let title: LocalizedStringResource = "Timer Name Configuration" @Parameter(title: "Timer Name", default: "Timer") var timerName: String } struct StartTimerIntent: SetValueIntent { static let title: LocalizedStringResource = "Start a timer" @Parameter(title: "Timer Name") var name: String @Parameter(title: "Timer is running") var value: Bool init() {} init(_ name: String) { self.name = name } func perform() async throws -> some IntentResult { // Start the timer… return .result() } } However in a fresh project I am able to add this widget code and it works completely fine in both debug and release. How can I fix this? This is clearly affecting many apps and is the 'fault' of the app, see these threads: https://www.reddit.com/r/ios/comments/1fiqrd7/ios_18_control_center_keeps_crashing_when_trying/ https://discussions.apple.com/thread/255759997?sortBy=rank crash-log.txt
3
1
260
2w
Apple Watch Crash - iOS 18
Hello everyone, I really need your help here :-)) iOS App. 17 and up. Widget extensions and watchOS app as well. New build for iOS 18 earlier this week. All platforms works perfect, except the Apple Watch version, which crash constantly on launch. Testing on simulator and testing devices - works perfect. Uploading to TestFlight and running on the same device - crash. The only thing I see in the crash report is StoredLocationBased.get error. It takes me to nowhere inside the project. Opened a DTS to Apple as well. Any help here will be fully appreciated. Thank you so much!
1
0
211
2w
iOS 18 .onChange(of: scenePhase) is constantly triggered
Hey all, I am facing a new issue on iOS 18 with ScenePhase and .onChange modifier. Here's roughly the code: .onChange(of: scenePhase, initial: true) { old, new in if new == .active { doStuff() } } on iOS 17 this was working as expected and triggered when eg. ap was brough from background or user navigated back to view on ios18 though this code gets triggered constatnly in my case when I eg. navigate to another screen on top of the one with that .onChange. after navigation happens, the onChange is being triggered continuosly and does not stop which causes doStuff() to be called multiple times
1
0
220
2w
Button click is not working in app intent view
App intent is a powerful framework, we can show any swiftui in the result, but button action is not working in it, I have a table of cards to show in the result and I want to implement some action when user selects each card, Button actions are not working here, what should I do
0
0
97
2w
Text with relative date - sizing bug when used in widget
When using a SwiftUI Text view with a relative date, with .minimumScaleFactor(), in a widget, the Text will always be shown at the minimum scale rather than the largest size possible. This started happening in iOS17, and is still the case in iOS18. Therefore, if for example, you wanted to have a Text, showing a relative date in a countdown, with a "minimumScaleFactor" of 0.5, it will always show at 0.5 scale, no matter how much space there is available. Text(.now, style: .relative) .font(.system(size: 80, weight: .bold, design: .rounded)) .minimumScaleFactor(0.2) ^^ will always show at 0.2 scale (in a widget) even if there's space for much more. This is only the case in widgets, not in the main app. Similarly, if you try to use "ViewThatFits" instead of "minimumScaleFactor", it will choose the smallest view, even if larger ones would fit. Screenshot demonstrates the issue - all the countdown text views should be similarly large. This is not an issue with lack of vertical spacing causing the more flexible views to shrink - it behaves the same even if there's loads of vertical space too. Maybe related, but trying to use ".fixedSize()" with a relative date Text view in a widget results in a completely blank widget. Seems like a system bug rather than anything wrong in my code - I've logged it as Feedback (#15151577) with a demo project. Has anybody else come up against these issues - any solutions?
4
0
155
2w
SwiftUI Charts and Xcode 16.1 beta 2
Please... Failed to build module 'Charts'; this SDK is not supported by the compiler (the SDK is built with 'Apple Swift version 6.0 effective-5.10 (swiftlang-6.0.0.7.41 clang-1600.0.24.1)', while this compiler is 'Apple Swift version 6.0 effective-5.10 (swiftlang-6.0.0.9.11 clang-1600.0.26.2)'). Please select a toolchain which matches the SDK. ANY WORKAROUNDS?
1
1
258
2w
SwiftUI: .textSelection(.enabled) not working in List on iOS 18
In iOS 18, textSelection(_:) not working in List. So, I can't copy text. Works on iOS 17 and earlier. Is this a bug and is there any solution? // Not Work: iOS 18 struct ContentView: View { var body: some View { List { Text("Hello World") .textSelection(.enabled) } } } // Work: iOS 18 and earlier struct ContentView: View { var body: some View { Text("Hello World") .textSelection(.enabled) } }
2
3
219
2w
.scrollPosition does not scroll smoothly when inside .navigationDestination
I filed FB15170881 about this. When using .scrollPosition on a view that is inside a .navigationDestination, scrolling the ScrollView causes the content to jump around rather than animate smoothly. The same view placed outside of the .navigationDestination scrolls smoothly as expected. To view this in action, use the example below. It's apparent on MacOS and iOS, as a Preview or run on-device. Launch it It will load to the problematic view by default. Scroll the view in the square to see the janky movement. You can also press the "back" button to go to a version of the same view that isn't nested inside a .navigationDestination. This one works smoothly as expected. import SwiftUI struct ContentView: View { let items = [0, 1, 2, 3, 4] @State private var position = ScrollPosition(idType: Int.self) @State private var showPage: Bool = true let height = 300.0 let width = 300.0 var body: some View { NavigationStack { VStack { Text("This scrolls nicely.") Text("It's at the navigation root.") demoView Spacer() Button(action: { showPage = true }) { Text("Go to broken version") } .buttonStyle(.bordered) .navigationDestination(isPresented: $showPage) { VStack { Text("This stutters when scrolling.") Text("It's in a navigationDestination.") demoView Spacer() } } Spacer() } } } @ViewBuilder var demoView: some View { let _ = Self._printChanges() ScrollView(.vertical) { LazyVStack(spacing: 0) { ForEach(items, id: \.self) { _ in Text("Scroll me") .frame(width: width, height: height) .border(.pink) } } .scrollTargetLayout() } .frame(width: width, height: height) .border(.blue) .scrollPosition($position) } } #Preview { ContentView() .modelContainer(for: Item.self, inMemory: true) }
1
0
94
2w
Customizing Tab | Side Bars
Hi, The new TabBar, SideBar combination is very nice, but I tried customizing like text sizes, icon sizes using imageScale and all dint have any effect, also shows of selected item in side bar couldn't customize it, is there any suggestions ? Kind Regards
0
0
105
2w
Customising TabView styling
The default design of TabView is 90% close to what I want. However, the icons, to my eye, lack a sufficient amount of spacing at the top, and slightly too much white space at the bottom. Is there a way to give more top padding to the icons? To move the icons down without changing the height of the TabView itself? Also, I find it weird that .labelStyle(.titleOnly) works on Tabs but .labelStyle(.iconOnly) doesn't work. Is that a bug? I had to use Image instead of Label: TabView { Tab { MailView() } label: { Image(systemName: "envelope") .padding(20) } Tab { SettingsView() } label: { Image(systemName: "gearshape") .padding(20) } }
2
0
172
Sep ’24
Reducing space between list rows
Hi, However I tried to reduce space between list rows in below code I fail, is there any way to reduce this space ? @State var flag: Bool = false var myList: [String] = ["Hello", "World", "SwiftUI"] var body: some View { VStack(alignment: .leading) { List (myList, id: \.self) { list in Text(list) .border(Color.black) .font(.system(size: 12)) // Smaller font size .frame(maxWidth: .infinity, minHeight: 20, alignment: .leading) // Reduced height .padding(.vertical, 4) // Minimal padding for vertical spacing .listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0)) // Remove insets .listRowSeparator(.hidden) // Hide separator } .listStyle(.plain) } .overlay( RoundedRectangle(cornerRadius: 10) .stroke(sysSecondary.opacity(0.4), lineWidth: 1) ) .frame(width: 220, height:260) .background(.white) .clipShape (RoundedRectangle (cornerRadius: 10)) } }
2
0
124
2w
SwiftUI Picker not trigger `onChange` first time when inside Menu in MacOS
code import SwiftUI @main struct swiftuiTestApp: App { @State private var value = "a"; var body: some Scene { WindowGroup { Menu("menu") { Picker("", selection: $value) { Text("A").tag("a") Text("B").tag("b") Text("C").tag("c") } .pickerStyle(.inline) .onChange(of: value) { oldValue, newValue in print("onChange", newValue) } } } } } on MacOS, onChange is not triggered when an option is selected for the first time, but subsequent option selections are triggered。 on MacOS, when Picker is not inside Menu, it works fine on iOS, both works fine with inside or not inside menu
6
0
287
Sep ’24
SwiftUI video editing timeline implementation
I am trying to build a video editing timeline using SwiftUI which consists of a series of trimmers (sample code for trimmer below). I plan to embed multiple of these trimmers in an HStack to make an editing timeline (HStack in turn will be embedded in a ScrollView). What I want to achieve is that if I trim end of any of these trimmers by dragging it's left/right edge, the other trimmers on timeline should move left/right to fill the gap. I understand as the view shrinks/expands during trimming, there might be a need for spacers on the edges of HStack whose widths need to be adjusted while trimming is ongoing. Right now the code I have for the trimmer uses a fixed frameWidth of the view, so the view occupies full space even if the trimming ends move. It's not clear how to modify my code below to achieve what I want. This was pretty much possible to do in UIKit by the way. import SwiftUI struct SimpleTrimmer: View { @State var frameWidth:CGFloat = 300 let minWidth: CGFloat = 30 @State private var leftOffset: CGFloat = 0 @State private var rightOffset: CGFloat = 0 @GestureState private var leftDragOffset: CGFloat = 0 @GestureState private var rightDragOffset: CGFloat = 0 private var leftAdjustment: CGFloat { // NSLog("Left offset \(leftOffset + leftDragOffset)") var adjustment = max(0, leftOffset + leftDragOffset) if frameWidth - rightOffset - adjustment - 60 < minWidth { adjustment = frameWidth - rightOffset - minWidth - 60.0 } return adjustment } private var rightAdjustment: CGFloat { var adjustment = max(0, rightOffset - rightDragOffset) if frameWidth - adjustment - leftOffset - 60 < minWidth { adjustment = frameWidth - leftOffset - 60 - minWidth } return adjustment } var body: some View { HStack(spacing: 10) { Image(systemName: "chevron.compact.left") .frame(width: 30, height: 70) .background(Color.blue) .offset(x: leftAdjustment) .gesture( DragGesture(minimumDistance: 0) .updating($leftDragOffset) { value, state, trans in state = value.translation.width } .onEnded { value in var maxLeftOffset = max(0, leftOffset + value.translation.width) if frameWidth - rightAdjustment - maxLeftOffset - 60 < minWidth { maxLeftOffset = frameWidth - rightAdjustment - minWidth - 60 } leftOffset = maxLeftOffset } ) Spacer() Image(systemName: "chevron.compact.right") .frame(width: 30, height: 70) .background(Color.blue) .offset(x: -rightAdjustment) .gesture( DragGesture(minimumDistance: 0) .updating($rightDragOffset) { value, state, trans in state = value.translation.width } .onEnded { value in var minRightOffset = max(0, rightOffset - value.translation.width) if minRightOffset < leftAdjustment - 60 - minWidth { minRightOffset = leftAdjustment - 60 - minWidth } rightOffset = minRightOffset } ) } .foregroundColor(.black) .font(.title3.weight(.semibold)) .padding(.horizontal, 7) .padding(.vertical, 3) .background { RoundedRectangle(cornerRadius: 7) .fill(.yellow) .padding(.leading, leftAdjustment) .padding(.trailing, rightAdjustment) } .frame(width: frameWidth) } } #Preview { SimpleTrimmer() }
0
0
147
2w
Getting inconsistent padding on widgets between devices and simulators
I'm trying to design a homescreen widget but I am unable to properly control the padding and sizing of various components. In the four attached screenshots you can see the huge variation in padding around the outside, the change in text colour and the spacing between the text. I've boiled it down as simple as possible and attached the view as a sample file. What I'd like to achieve is a consistent look between iPads and iPhones and ideally in the simulator too. Is there a simple way to set the padding so that all places use the same, and then scale the text so that I know that if the text fits in the simulator the same text will fit on all devices? Device iPad 8 - 17.7 iPhone 13 Pro Max - 17.7 Xcode Canvas - iPad 13" Simulator - iPad Pro sampleview.txt 13"
0
0
106
2w