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

SwiftUI Documentation

Post

Replies

Boosts

Views

Activity

.searchable bug with new navigationTransitions
When using the new .navigationTransition feature, when using .searchable at the same time result in the search bar disappearing when dismissing the view you've trasition to, has anyone else experienced this or found any workarounds? Here is an example that make the issue always occur. @State private var searchText: String = "" @Namespace private var namespace let things: [String] = ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirdteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen", "twenty"] var body: some View { NavigationStack { ScrollView { LazyVStack(spacing: 20) { ForEach(things, id: \.self) { thing in NavigationLink(){ SwiftUIView(thing: thing, name: namespace) }label: { Text(thing) } .matchedTransitionSource(id: thing, in: namespace) } } } .searchable(text: $searchText) .navigationTitle("My List") .navigationBarTitleDisplayMode(.inline) } } } struct SwiftUIView: View { var thing: String var name: Namespace.ID var body: some View { Text(thing) .navigationTransition(.zoom(sourceID: thing, in: name)) } } After running the code you end up with this: And after clicking an element and dismissing it your get this:
2
0
131
1w
NavigationSplitView issues in iOS 18 and 18.1
Hello, In our current project we are using NavigationSplitView in the following way: var body: some View { NavigationSplitView( sidebar: { ListView() }, detail: { DetailsView() } ) .navigationBarHidden(true) .navigationSplitViewStyle(.automatic) .introspectSplitViewController { splitViewController in splitViewController.preferredDisplayMode = .oneOverSecondary splitViewController.maximumPrimaryColumnWidth = 500 splitViewController.preferredPrimaryColumnWidthFraction = 1 } } } And in iPhone the DetailsView() is pushed using the navigationDestination modifier: .navigationDestination(isPresented: $isShowingDetailsScreen) { DetailsView() .navigationBarHidden(true) } where isShowingDetailsScreen is updated through a button click: Button() { self.isShowingDetailsScreen = true } This works perfectly in iOS versions prior to 18. However starting from this version the button click no longer presents the view desired. Below is what happening in the latest iOS versions: iOS 18: This mechanism is broken altogether, it does not work at all. iOS 18.1: This mechanism is partially broken, when clicking on the button the DetailsView is not presented, however since the page also contains other reactive views, any time one of them is changed through a state change after clicking on that button, the DetailsView is presented. Does anyone faced an issue like this with the new iOS and if so is there any workaround for now? Because this seems to be a bug caused by changes in SwiftUI and shouldn't persist for long.
2
0
151
1w
After interacting with a button in the live activity, the Control widget and home screen widget did not update.
I have a button on a live activity, and I want to end the live activity and update the Control Center widgets and home screen widgets after clicking this button. So, in the perform() method of the button's LiveActivityIntent, I called the methods ControlCenter.shared.reloadAllControls() and WidgetCenter.shared.reloadAllTimelines(), but they didn't work. Home screen widgets and Control Center widgets do not refresh, resulting in a poor user experience.
1
0
111
1w
iOS 18 navigationBar color scheme not working
Hello, I'm encountering an issue with toolbarColorScheme in iOS 18. In a simple example, toolbarColorScheme works fine when triggered in onAppear. However, after navigating to a different view (e.g., following a link, such as link 234), and then returning, the toolbarColorScheme seems to be ignored. Could anyone help me resolve this issue? struct TestNavigationBarColor: View { var body: some View { NavigationStack { List { Text("123") NavigationLink(value: 1) { Text("234") } } .toolbarColorScheme(.dark, for: .navigationBar) .toolbarBackground(.visible, for: .navigationBar) .navigationTitle("Title1") .navigationDestination(for: Int.self) {_ in List { Text("Nested screen") } .navigationTitle("Title2") } } } }
1
0
158
1w
iOS 18 SwiftUI navigation bar problem
Okay I know, fill a bug... but here is a super simple app that will demostrate that the navigation bar chnages from Dark scheme to light scheme when you tap back after it goes to the second view. import SwiftUI struct ContentView: View { var body: some View { NavigationStack { NavigationLink { Text("Tap back and notice the navigation title changes to black text instead of white") .toolbarBackground(.visible, for: .navigationBar) .toolbarBackground(Color.orange, for: .navigationBar) .toolbarColorScheme(.dark, for: .navigationBar) } label: { VStack { Text("First page is the sweetest") } .padding() } .navigationTitle("First Page") .toolbarBackground(.visible, for: .navigationBar) .toolbarBackground(Color.orange, for: .navigationBar) .toolbarColorScheme(.dark, for: .navigationBar) } } } #Preview { ContentView() }
5
5
895
2w
Xcode 15 console logging of system messages
Background I have a SwiftUI app that uses OSLog and the new Logger framework. In my SwiftUI views, I would like to use something like Self._logChanges() to help debug issues. After some trial and error, I can see the messages appear in the System console log for the app I am debugging using the com.apple.SwiftUI subsystem. Problem I'd like to see those same messages directly in Xcode's console window so I can filter them as needed. How do I do that? Thanks! -Patrick
3
0
1.5k
Feb ’24
SwiftUI Gestures prevent scrolling with iOS 18
I added gesture support to my app that supports iOS 16 and 17 and have never had issues with it. However, when I compiled my app with Xcode 16 I immediately noticed a problem with the app when I ran it in the simulator. I couldn't scroll up or down. I figured out it’s because of my gesture support. My gesture support is pretty simple. let myDragGesture = DragGesture() .onChanged { gesture in self.offset = gesture.translation } .onEnded { _ in if self.offset.width > threshold { ...some logic } else if self.offset.width < -threshold { ...some other logic } logitUI.debug("drag gesture width was \(self.offset.width)") self.offset = .zero } If I pass nil to .gesture instead of myDragGesture then scrolling starts working again. Here’s some example output when I’m trying to scroll down. These messages do NOT appear when I run my app on an iOS 16/17 simulator with Xcode 15. drag gesture width was 5.333328 drag gesture width was -15.333344 drag gesture width was -3.000000 drag gesture width was -24.333328 drag gesture width was -30.666656 I opened FB14205678 about this.
9
13
1.5k
Jul ’24
External Display with SwiftUI in 2024
What is current best-practice for supporting an external display in a SwiftUI iOS app in 2024? (I'm only interested in iOS 17 and/or iOS 18) The only docs I found require abandoning the SwiftUI App structure and "switching back to a full UIKit App Delegate". Is this still the only option? Are there any complete examples on how to accomplish this? Also is testing external displays with Simulator at all reliable? All experiences I read about say that it never works. Thanks in advance.
0
0
110
2w
Widget link broken by `.desaturated` image rendering mode
Using desaturated mode on an image in a widget will break any links or buttons that use the image as their 'label'. Using the following will just open the app as if there was no link at all - therefore just using the fallback userActivity handler, or any .widgetURL() urls provided. Link(destination: URL(string: "bug://never-works")!) { Image("puppy") .widgetAccentedRenderingMode(.desaturated) } The same goes for buttons: Button(intent: MyDemoIntent()) { Image("puppy") .widgetAccentedRenderingMode(.desaturated) } I've tried hacky solutions like putting the link behind the image using a ZStack, and disabling hit testing on the image, but they don't work. Anything else to try? Logged as Feedback #15152620.
2
1
128
2w
No containerBackground content on Widget in iOS 18 tinted home screen style
The widget I have create for iOS 17 uses the containerBackground to display an image in the background. This works fine. But when I set the home screen to the iOS 18 tinted option the background disappears. I want the background to stay because it contains an image of that is meaningful to the user. I use the following code: @ViewBuilder var body: some View { if let memory = entry.memory, let uiImage = memory.image { Group { if entry.showCaption { memoryBody(with: memory) } else { Color.white.opacity(0.0000000001) } } .foregroundStyle(.white) .widgetBackground( Image(uiImage: uiImage) .resizable() .scaledToFill() ) } else if let memory = entry.memory { memoryBody(with: memory) .widgetBackground(Color.gray) } else { noMemoryBody() } } extension View { func widgetBackground(_ backgroundView: some View) -> some View { if #available(iOSApplicationExtension 17.0, *) { return containerBackground(for: .widget) { backgroundView } } else { return background(backgroundView) } } }
4
1
877
Jun ’24
what's wrong with `ToolbarItemGroup(placement: .keyboard)` inside `TavView`?
Why is there inconstancy of appearing the keyboard tool bar Item with tab view? Try to go to second tab and focus the field. Sometimes it does not appear (in my more complex project it does not appear >90% times). import SwiftUI struct MainTabView: View { var body: some View { TabView { FirstTabView() .tabItem { Label("Tab 1", systemImage: "house") } SecondTabView() .tabItem { Label("Tab 2", systemImage: "star") } } } } struct FirstTabView: View { @State private var text = "" var body: some View { NavigationStack { VStack { TextField("Enter something 1", text: $text) .textFieldStyle(RoundedBorderTextFieldStyle()) .padding() } .toolbar { ToolbarItemGroup(placement: .keyboard) { Button("Done") { UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil) } } } } } } struct SecondTabView: View { @State private var text = "" var body: some View { NavigationStack { VStack { TextField("Enter something 2", text: $text) .textFieldStyle(RoundedBorderTextFieldStyle()) .padding() } .toolbar { ToolbarItemGroup(placement: .keyboard) { Button("Done") { UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil) } } } } } } #Preview { MainTabView() }
0
1
114
2w
iOS 18 - Toolbar keyboard placement within TabView, NavigationSplitView
Hello, After a fair amount of time of trial and error, I have seemingly discovered a bug in iOS 18 with .toolBar with placement:. keyboard) Feedback: FB15205988 Xcode Version: 16.0 (16A242d) iOS Version: 18.0 (22A3351) I'd appreciate help to see if I'm missing something here. What's happening? When using .toolBar with (placement: .keyboard), within a NavigationSplitView detail:, encompassed in a TabView, the .toolBar view does not appear above the keyboard. Within the code, the usage of .toolBar is within ShakeDetail.swift. When commenting out the TabView within ShakeTabView.swift, or running on iOS 17.5, the .toolbar appears. Would greatly appreciate help if someone knows a workaround, or a misunderstanding here of course! Code Shake.swift import Foundation import SwiftUI struct Shake: Equatable, Identifiable, Hashable { var name: String let id = UUID() static var example = Shake(name: "Banana") static var many: [Shake] { return [ Shake(name: "Apple"), Shake(name: "Banana"), Shake(name: "Cherry"), Shake(name: "Berry"), ] } } ShakeDetail.swift import SwiftUI struct ShakeDetail: View { @State var shake: Shake = Shake(name: "") var body: some View { List { TextField("dsf", text: $shake.name, prompt: Text("Enter your favorite shake")) } .scrollDismissesKeyboard(.interactively) .toolbar { ToolbarItem(placement: .keyboard) { HStack(alignment: .center) { Text(shake.name) .font(.title3) .foregroundColor(.red) } } } .toolbarColorScheme(.dark, for: .navigationBar) .toolbarBackground( Color.purple, for: .navigationBar ) .toolbarBackground(.visible, for: .navigationBar) } } #Preview { ShakeDetail() } ShakeListView.swift struct ShakeListView: View { @Binding var shakes: [Shake] @Binding var selectedShake: Shake? var body: some View { List(selection: $selectedShake) { ForEach(shakes) { shake in NavigationLink(value: shake) { Text(shake.name) .font(.system(.title2, design: .rounded)) .foregroundStyle(.primary) } } } .navigationTitle("Shakes") } } #Preview { @Previewable @State var shakes: [Shake] = Shake.many @Previewable @State var selectedShake: Shake? ZStack { ShakeListView(shakes: $shakes, selectedShake: $selectedShake) } } ShakeSplitView.swift import SwiftUI import OSLog public struct ShakeSplitView: View { @State var selectedShake: Shake? @State var shakes = Shake.many @State private var columnVisibility = NavigationSplitViewVisibility.doubleColumn public init(isShowingFavorites: Bool = false, columnVisibility: SwiftUI.NavigationSplitViewVisibility = NavigationSplitViewVisibility.doubleColumn) { self.columnVisibility = columnVisibility } public var body: some View { NavigationSplitView(columnVisibility: $columnVisibility) { ShakeListView(shakes: $shakes, selectedShake: $selectedShake) } detail: { if let selectedShake { // Add shake detail ShakeDetail(shake: selectedShake) } else { Label("Please select a shake", systemImage: "arrow.backward.circle") .foregroundColor(.purple) .font(.system(.title2, design: .rounded)) } } .navigationSplitViewStyle(.balanced) } } struct FormulaSplitView_Previews: PreviewProvider { static var previews: some View { ShakeSplitView() } } ShakeTabView.swift import SwiftUI struct ShakeTabView: View { var body: some View { /* TabView breaks the ToolbarItem(placement: .keyboard) */ TabView { ShakeSplitView() .tabItem { Image(systemName: "carrot.fill") Text("Shakes") } } } } #Preview { ShakeTabView() }
4
0
309
2w
watchOS SwiftUI background task not working
I'm attempting to create a standalone watchOS app that fetches the prayer timings of my local mosque in JSON format via an API call. I want the app to fetch the prayer timings in the background, but only once per day, at the start of the day (when prayer timings change, i.e., midnight). I'm trying to implement this using SwiftUI's backgroundTask modifier as explained in the docs and in this WWDC22 video. I made sure to enable the Background Modes capability, and this is what my app's Info.plist looks like: However, I've been unable to get it to work. I would appreciate any assistance I can get and feedback for improvements I can make, even with the Info.plist if anything is incorrect about it. Thank you! This is what I have so far: // PrayerTimesCompanionApp.swift // PrayerTimesCompanion Watch App import SwiftUI import WatchKit @main struct PrayerTimesCompanion_Watch_AppApp: App { var body: some Scene { WindowGroup { ContentView() } .backgroundTask(.appRefresh("TIMINGS_REFRESH")) { print("Found matching task") scheduleNextBackgroundRefresh() } } } // Schedule the next background refresh func scheduleNextBackgroundRefresh() { let today = Calendar.current.startOfDay(for: .now) if let tomorrow = Calendar.current.date(byAdding: .day, value: 1, to: today) { WKApplication.shared().scheduleBackgroundRefresh(withPreferredDate: tomorrow, userInfo: "TIMINGS_REFRESH" as NSSecureCoding & NSObjectProtocol) { error in if error != nil { fatalError("*** An error occurred while scheduling the background refresh task. ***") } print("*** Scheduled! ***") } } } // ContentView.swift // PrayerTimesCompanion Watch App import SwiftUI struct ContentView: View { @StateObject var prayerTimeModel = PrayerTimesModel() var body: some View { List { VStack { VStack(spacing: 15) { // Table Header HStack { Text("Prayer") .bold() .frame(maxWidth: .infinity, alignment: .leading) // Align to the left Text("Iqamah") .bold() .frame(maxWidth: .infinity, alignment: .trailing) // Align to the right } .padding() // Table Rows (5 prayers) ForEach(prayerTimeModel.prayerTimes.data.iqamah, id: \.date) { iqamah in rowView(prayer: "Fajr", time: iqamah.fajr) rowView(prayer: "Zuhr", time: iqamah.zuhr) rowView(prayer: "Asr", time: iqamah.asr) rowView(prayer: "Maghrib", time: iqamah.maghrib) rowView(prayer: "Isha", time: iqamah.isha) } } .padding() } .padding() .onAppear { prayerTimeModel.fetch() } } .edgesIgnoringSafeArea(.top) } func rowView(prayer: String, time: String) -> some View { HStack { Text(prayer) .frame(maxWidth: .infinity, alignment: .leading) Text(time) .frame(maxWidth: .infinity, alignment: .trailing) } } } #Preview { ContentView() } // PrayerTimesModel.swift // PrayerTimesCompanion Watch App import Foundation import SwiftUI // Main struct for the response struct PrayerTimesResponse: Codable { let status: String var data: SalahData let message: [String] } // Struct for the data section struct SalahData: Codable { var salah: [Salah] var iqamah: [Iqamah] } // Struct for Salah times struct Salah: Codable { let date: String let hijriDate: String let hijriMonth: String let day: String var fajr: String let sunrise: String var zuhr: String var asr: String var maghrib: String var isha: String enum CodingKeys: String, CodingKey { case date, hijriDate = "hijri_date", hijriMonth = "hijri_month", day, fajr, sunrise, zuhr, asr, maghrib, isha } } // Struct for Iqamah times struct Iqamah: Codable { let date: String var fajr: String var zuhr: String var asr: String var maghrib: String var isha: String let jummah1: String let jummah2: String enum CodingKeys: String, CodingKey { case date, fajr, zuhr, asr, maghrib, isha, jummah1 = "jummah1", jummah2 = "jummah2" } } class PrayerTimesModel: ObservableObject { @Published var prayerTimes: PrayerTimesResponse = PrayerTimesResponse( status: "Unknown", data: SalahData( salah: [Salah(date: "", hijriDate: "", hijriMonth: "", day: "", fajr: "", sunrise: "", zuhr: "", asr: "", maghrib: "", isha: "")], iqamah: [Iqamah(date: "", fajr: "", zuhr: "", asr: "", maghrib: "", isha: "", jummah1: "", jummah2: "")]), message: ["No data available"] ) // fetches the local mosque's prayer timings via an API call func fetch() { guard let url = URL(string: "https://masjidal.com/api/v1/time/range?masjid_id=3OA87VLp") else { return } let task = URLSession.shared.dataTask(with: url) { [self] data, _, error in guard let data = data, error == nil else { return } // Convert to JSON do { var prayerTimes = try JSONDecoder().decode(PrayerTimesResponse.self, from: data) DispatchQueue.main.async { self.prayerTimes = prayerTimes } } catch { print(error) } } task.resume() } }
0
0
263
2w
SwiftUI NavigationSplitView - Nested List Not Animating
Hi All! I've encountered a SwiftUI NavigationSplitView bug in my app that I'd appreciate help with, I've spent quite some time trying to work out a solution to this problem. I have a main list, which has either a Location or LocationGroup. When selecting a Location, the detail view is presented. When selecting a LocationGroup, a subsequent list of Locations are presented (from the group). When tapping on any of these Locations, the NavigationStack does not animate (push the view), and when tapping back from it, it jumps to the main selection. The overall goal is to be able to present within the detail: of a NavigationSplitView a NavigationStack, and to be able to push onto that stack from both the main NavigationSplitView's list, and from the detail. I created the following sample code that reproduces the issue: ContentView.swift public enum LocationSplitViewNavigationItem: Identifiable, Hashable { case location(Location) case locationGroup(LocationGroup) public var id: UUID? { switch self { case .location(let location): return location.id case .locationGroup(let locationGroup): return locationGroup.id } } } struct ContentView: View { @State private var columnVisibility = NavigationSplitViewVisibility.doubleColumn @State private var selectedNavigationItem: LocationSplitViewNavigationItem? var body: some View { NavigationSplitView(columnVisibility: $columnVisibility) { LocationListView(selectedItem: $selectedNavigationItem, locationData: LocationSampleData(locations: LocationSampleData.sampleLocations, locationGroups: LocationSampleData.sampleLocationGroups)) } detail: { if let selectedLocation = selectedNavigationItem { switch selectedLocation { case .location(let location): LocationDetailView(selectedLocation: location) case .locationGroup(let locationGroup): LocationListView(selectedItem: $selectedNavigationItem, locationData: LocationSampleData(locations: locationGroup.locations)) } } } .navigationSplitViewStyle(.balanced) } } LocationListView.swift struct LocationListView: View { @Binding public var selectedItem: LocationSplitViewNavigationItem? var locationData: LocationSampleData var body: some View { List(selection: $selectedItem) { if let locations = locationData.locations { ForEach(locations) { location in NavigationLink(value: LocationSplitViewNavigationItem.location(location)) { Text(location.name) .bold() } } } if let locationGroups = locationData.locationGroups { ForEach(locationGroups) { locationGroup in NavigationLink(value: LocationSplitViewNavigationItem.locationGroup(locationGroup)) { Text(locationGroup.name) .bold() .foregroundStyle(.red) } } } } .navigationTitle("Saturday Spots") .navigationBarTitleDisplayMode(.large) } } LocationDetailView.swift struct LocationDetailView: View { var selectedLocation: Location var body: some View { Text(selectedLocation.name) .font(.largeTitle) .bold() .foregroundStyle(LinearGradient( colors: [.teal, .indigo], startPoint: .top, endPoint: .bottom )) .toolbarBackground( Color.orange, for: .navigationBar ) .toolbarBackground(.visible, for: .navigationBar) } } Location.swift import CoreLocation struct LocationSampleData { var locations: [Location]? var locationGroups: [LocationGroup]? static let sampleLocations: [Location]? = Location.sample static let sampleLocationGroups: [LocationGroup]? = [LocationGroup.sample] } public struct Location: Hashable, Identifiable { var name: String var coordinates: CLLocationCoordinate2D var photo: String public var id = UUID() static public let sample: [Location] = [ Location(name: "Best Bagel & Coffee", coordinates: CLLocationCoordinate2D(latitude: 123, longitude: 121), photo: "asdf"), Location(name: "Absolute Bagels", coordinates: CLLocationCoordinate2D(latitude: 123, longitude: 121), photo: "asdf"), Location(name: "Tompkins Square Bagels", coordinates: CLLocationCoordinate2D(latitude: 123, longitude: 121), photo: "asdf"), Location(name: "Zabar's", coordinates: CLLocationCoordinate2D(latitude: 123, longitude: 121), photo: "asdf"), ] static public let oneSample = Location(name: "Absolute Bagels", coordinates: CLLocationCoordinate2D(latitude: 123, longitude: 121), photo: "asdf") } public struct LocationGroup: Identifiable, Hashable { var name: String var locations: [Location] public var id = UUID() static public let sample: LocationGroup = LocationGroup(name: "Bowling", locations: [ Location(name: "Frames Bowling Lounge", coordinates: CLLocationCoordinate2D(latitude: 123, longitude: 121), photo: "asdf"), Location(name: "Bowlero Chelsea Piers", coordinates: CLLocationCoordinate2D(latitude: 123, longitude: 121), photo: "asdf") ]) } extension CLLocationCoordinate2D: Hashable { public static func == (lhs: Self, rhs: Self) -> Bool { return lhs.latitude == rhs.latitude && lhs.longitude == rhs.longitude } public func hash(into hasher: inout Hasher) { hasher.combine(latitude) hasher.combine(longitude) } }
2
0
493
Aug ’24
onGeometryChange: Assertion failed: Block was expected to execute on queue
Hello! After upgrading to Xcode 16 & Swift 6 & iOS 18 I starting receiveing strange crashes. Happens randomly in different view and pointing to onGeometryChange action block. I added DispatchQueue.main.async { in hopes it will help but it didn't. HStack { ... } .onGeometryChange(for: CGSize.self, of: \.size) { value in DispatchQueue.main.async { self.width = value.width self.height = value.height } } As far as I understand, onGeometryChange is defined as nonisolated and Swift 6 enforce thread checking for the closures, SwiftUI views are always run on the main thread. Does it mean we can not use onGeometryChange safely in swiftui? BUG IN CLIENT OF LIBDISPATCH: Assertion failed: Block was expected to execute on queue [com.apple.main-thread (0x1eacdce40)] Crashed: com.apple.SwiftUI.AsyncRenderer 0 libdispatch.dylib 0x64d8 _dispatch_assert_queue_fail + 120 1 libdispatch.dylib 0x6460 _dispatch_assert_queue_fail + 194 2 libswift_Concurrency.dylib 0x62b58 <redacted> + 284 3 Grit 0x3a57cc specialized implicit closure #1 in closure #1 in PurchaseModalOld.body.getter + 4377696204 (<compiler-generated>:4377696204) 4 SwiftUI 0x5841e0 <redacted> + 60 5 SwiftUI 0x5837f8 <redacted> + 20 6 SwiftUI 0x586b5c <redacted> + 84 7 SwiftUICore 0x68846c <redacted> + 48 8 SwiftUICore 0x686dd4 <redacted> + 16 9 SwiftUICore 0x6ecc74 <redacted> + 160 10 SwiftUICore 0x686224 <redacted> + 872 11 SwiftUICore 0x685e24 $s14AttributeGraph12StatefulRuleP7SwiftUIE15withObservation2doqd__qd__yKXE_tKlF + 72 12 SwiftUI 0x95450 <redacted> + 1392 13 SwiftUI 0x7e438 <redacted> + 32 14 AttributeGraph 0x952c AG::Graph::UpdateStack::update() + 540 15 AttributeGraph 0x90f0 AG::Graph::update_attribute(AG::data::ptr<AG::Node>, unsigned int) + 424 16 AttributeGraph 0x8cc4 AG::Subgraph::update(unsigned int) + 848 17 SwiftUICore 0x9eda58 <redacted> + 348 18 SwiftUICore 0x9edf70 <redacted> + 36 19 AttributeGraph 0x148c0 AGGraphWithMainThreadHandler + 60 20 SwiftUICore 0x9e7834 $s7SwiftUI9ViewGraphC18updateOutputsAsync2atAA11DisplayListV4list_AG7VersionV7versiontSgAA4TimeV_tF + 560 21 SwiftUICore 0x9e0fc0 $s7SwiftUI16ViewRendererHostPAAE11renderAsync8interval15targetTimestampAA4TimeVSgSd_AItF + 524 22 SwiftUI 0xecfdfc <redacted> + 220 23 SwiftUI 0x55c84 <redacted> + 312 24 SwiftUI 0x55b20 <redacted> + 60 25 QuartzCore 0xc7078 <redacted> + 48 26 QuartzCore 0xc52b4 <redacted> + 884 27 QuartzCore 0xc5cb4 <redacted> + 456 28 CoreFoundation 0x555dc <redacted> + 176 29 CoreFoundation 0x55518 <redacted> + 60 30 CoreFoundation 0x55438 <redacted> + 524 31 CoreFoundation 0x54284 <redacted> + 2248 32 CoreFoundation 0x535b8 CFRunLoopRunSpecific + 572 33 Foundation 0xb6f00 <redacted> + 212 34 Foundation 0xb6dd4 <redacted> + 64 35 SwiftUI 0x38bc80 <redacted> + 792 36 SwiftUI 0x1395d0 <redacted> + 72 37 Foundation 0xc8058 <redacted> + 724 38 libsystem_pthread.dylib 0x637c _pthread_start + 136 39 libsystem_pthread.dylib 0x1494 thread_start + 8
0
0
145
2w
SwiftUI Previews broken on Swift Package with dependencies
Hello! Previously, using content from one Swift Package in the UI of another would cause preview failures. Now, with Xcode 16, this issue has been improved, and the preview feature is working, though occasional crashes still occur. I have submitted a report regarding this issue. I’ve encountered some issues while developing a SwiftUI-based application, particularly when using Xcode’s SwiftUI preview feature, which frequently crashes. My app supports both macOS and iOS. Due to the differences between the platforms, I’ve had to implement some pages using UIKit and reference a few UIKit-based open-source frameworks. For instance, I’m using the LazyPager library, which only supports iOS. During runtime, I ensure LazyPager is only compiled for iOS by using .product(name: "LazyPager", package: "LazyPager", condition: .when(platforms: [.iOS])), which works as expected. However, when I use Xcode’s SwiftUI preview mode and select macOS as the target, UIKit-related code still gets compiled, leading to a crash, with the error message indicating an issue related to LazyPager's UIKit dependencies. Since it’s not feasible to ask the maintainers of these open-source libraries to add #if canImport(UIKit) conditionals to their code, I would like to ask if there’s a better way to resolve this issue, ensuring that SwiftUI preview works properly on macOS. If you have any suggestions or solutions, I would greatly appreciate your assistance. Thank you so much for your help! import PackageDescription let package = Package( name: "ImportLibrary", platforms: [ .iOS(.v16), .macOS(.v13) ], products: [ .library( name: "ImportLibrary", targets: ["ImportLibrary"]), ], dependencies: [ .package(url: "https://github.com/gh123man/LazyPager", from: "1.1.0"), ], targets: [ .target( name: "ImportLibrary", dependencies: [ "SwiftSoup", "Kingfisher", "WaterfallGrid", .product(name: "LazyPager", package: "LazyPager", condition: .when(platforms: [.iOS])), "QuickModule" ] ), .testTarget( name: "ImportLibraryTests", dependencies: ["ImportLibrary"]), ] ) Sincerely,
Best regards
0
0
111
2w
SwiftUI keep background view stationary as main view resized
I have implemented a sample video editing timeline using SwiftUI and am facing issues. So I am breaking up the problem in chunks and posting issue each as a separate question. In the code below, I have a simple timeline using an HStack comprising of a left spacer, right spacer(represented as simple black color) and a trimmer UI in the middle. The trimmer resizes as the left and right handles are dragged. The left and right spacers also adjust in width as the trimmer handles are dragged. Problem: I want to keep the background thumbnails (implemented currently as simple Rectangles filled in different colors) in the trimmer stationary as the trimmer resizes. Currently they move along as the trimmer resizes as seen in the gif below. How do I fix it? import SwiftUI struct SampleTimeline: View { let viewWidth:CGFloat = 340 //Width of HStack container for Timeline @State var frameWidth:CGFloat = 280 //Width of trimmer var minWidth: CGFloat { 2*chevronWidth + 10 } //min Width of trimmer @State private var leftViewWidth:CGFloat = 20 @State private var rightViewWidth:CGFloat = 20 var chevronWidth:CGFloat { return 24 } var body: some View { HStack(spacing:0) { Color.black .frame(width: leftViewWidth) .frame(height: 70) HStack(spacing: 0) { Image(systemName: "chevron.compact.left") .frame(width: chevronWidth, height: 70) .background(Color.blue) .gesture( DragGesture(minimumDistance: 0) .onChanged({ value in leftViewWidth = max(leftViewWidth + value.translation.width, 0) if leftViewWidth > viewWidth - minWidth - rightViewWidth { leftViewWidth = viewWidth - minWidth - rightViewWidth } frameWidth = max(viewWidth - leftViewWidth - rightViewWidth, minWidth) }) .onEnded { value in } ) Spacer() Image(systemName: "chevron.compact.right") .frame(width: chevronWidth, height: 70) .background(Color.blue) .gesture( DragGesture(minimumDistance: 0) .onChanged({ value in rightViewWidth = max(rightViewWidth - value.translation.width, 0) if rightViewWidth > viewWidth - minWidth - leftViewWidth { rightViewWidth = viewWidth - minWidth - leftViewWidth } frameWidth = max(viewWidth - leftViewWidth - rightViewWidth, minWidth) }) .onEnded { value in } ) } .foregroundColor(.black) .font(.title3.weight(.semibold)) .background { HStack(spacing:0) { Rectangle().fill(Color.red) .frame(width: 70, height: 60) Rectangle().fill(Color.cyan) .frame(width: 70, height: 60) Rectangle().fill(Color.orange) .frame(width: 70, height: 60) Rectangle().fill(Color.brown) .frame(width: 70, height: 60) Rectangle().fill(Color.purple) .frame(width: 70, height: 60) } } .frame(width: frameWidth) .clipped() Color.black .frame(width: rightViewWidth) .frame(height: 70) } .frame(width: viewWidth, alignment: .leading) } } #Preview { SampleTimeline() }
0
0
115
2w
ShareLink not reliable, entitlement errors
I am using public struct ShareLink<Data, PreviewImage, PreviewIcon, Label> : View where Data : RandomAccessCollection, PreviewImage : Transferable, PreviewIcon : Transferable, Label : View, Data.Element : Transferable {} And it is generating entitlement errors and not working reliably ( will transfer 1-3 items, but not 4+ ; will not work a second time) Error is: Error acquiring assertion: <Error Domain=RBSServiceErrorDomain Code=1 "(originator doesn't have entitlement com.apple.runningboard.primitiveattribute AND originator doesn't have entitlement com.apple.runningboard.assertions.frontboard AND target is not running or doesn't have entitlement com.apple.runningboard.trustedtarget AND Target not hosted by originator)" UserInfo={NSLocalizedFailureReason=(originator doesn't have entitlement com.apple.runningboard.primitiveattribute AND originator doesn't have entitlement com.apple.runningboard.assertions.frontboard AND target is not running or doesn't have entitlement com.apple.runningboard.trustedtarget AND Target not hosted by originator)}> Received port for identifier response: <> with error:Error Domain=RBSServiceErrorDomain Code=1 "Client not entitled" UserInfo={RBSEntitlement=com.apple.runningboard.process-state, NSLocalizedFailureReason=Client not entitled, RBSPermanent=false} elapsedCPUTimeForFrontBoard couldn't generate a task port Received port for identifier response: <> with error:Error Domain=RBSServiceErrorDomain Code=1 "Client not entitled" UserInfo={RBSEntitlement=com.apple.runningboard.process-state, NSLocalizedFailureReason=Client not entitled, RBSPermanent=false} elapsedCPUTimeForFrontBoard couldn't generate a task port Received port for identifier response: <> with error:Error Domain=RBSServiceErrorDomain Code=1 "Client not entitled" UserInfo={RBSEntitlement=com.apple.runningboard.process-state, NSLocalizedFailureReason=Client not entitled, RBSPermanent=false} Code is import SwiftUI var images = Array<Image?>(repeating: nil , count: 200); struct ShareTestGContentView: View { let columns = [GridItem(.fixed(165)), GridItem(.fixed(165))] private let twoColumnGrid = [ GridItem(.flexible(minimum: 40), spacing: 2), GridItem(.flexible(minimum: 40), spacing: 2) ] @State var selected = Set() var body: some View { topSection() ScrollView { LazyVGrid(columns: twoColumnGrid, spacing: 2) { // columns: [GridItem(.flexible())]) { ForEach(1...100, id: \.self) { idx in var cr = ( selected.contains(idx) ? 16.0 : 0 ) var lw = ( selected.contains(idx) ? 8.0 : 0 ) VStack{ Button(action: { if selected.contains(idx) { selected.remove(idx); cr = 0.0; lw = 0.0 } else { selected.insert(idx); cr = 16.0; lw = 8.0 } } , label: { AsyncImage(url :URL(string: "https://picsum.photos/800/800?\(idx)")) { image in let _ = ( images[idx] = image.image ) image.image }.frame(width: boxHalf,height:boxHalf).drawingGroup() }) }.overlay( RoundedRectangle(cornerRadius: cr).stroke(Color.yellow, lineWidth: lw) ).drawingGroup() } } } } func topSection() -> some View { let imgarray = selected.compactMap { images[$0] } return HStack { ShareLink("",items: imgarray) { img in SharePreview("images", image: Image(systemName: "captions.bubble.fill")) } } } } #Preview { ShareTestGContentView() }
6
9
4.3k
Oct ’23
"UI unresponsiveness" warning on @main
I'm seeing a runtime warning in Xcode 14 Beta 5 that says "This method should not be called on the main thread as it may lead to UI unresponsiveness." This is happening on the @main entry point of my app. See below: The warning shown gives me no insight into what's actually going wrong. I think it may be due to some Core Location code that runs when the app first opens, but is there a way for me to get some more insight into what's causing this? Or is this possibly an Xcode 14/iOS 16 bug, and this is not an issue to worry about? I'm not getting any warnings on Xcode 13/iOS 15.
75
27
74k
Aug ’22
Select All in a NavigationListView on macOS?
There are a couple of questions in here. I want to do a basic master-detail split view, as so many SwiftUI apps do. But I want to let the user select an arbitrary subset of items in the list, select them all, and delete them (or do other operations). Select All, by default, is excruciatingly slow. I have a List view with a selection binding to a Set<PersistentIdentifier>. A ForEach inside renders the items from a SwiftData @Query. I have a couple hundred items, each with a String and Date property. The list item renders the String and nothing else. I click on an item, hit Command-A, and the app locks up for several seconds while it messes with the selection. It never highlights all the items, but sometimes highlights one (usually different from the one I clicked on).I have an .onChange(of: self.selection) in there to debug the selection. It is called many, many times (2-3 times per second, very slowly), and print the selection count, which starts at 135, and goes down by one, to about 103. If I scroll the list, the selection onChange gets called a bunch more times. Sometimes you see the selection highlights change. My SwiftUI view hierarchy looks like this: NavigationSplitView OrdersList struct OrdersList : View { var body: some View { List(selection: self.$selection) { ForEach(self.orders) { order in NavigationLink { Text("Order ID: \(order.vendorOrderID ?? "<none>")") } label: { Text("Order ID: \(order.vendorOrderID ?? "<none>")") } } .onDelete(perform: self.deleteOrders) .onChange(of: self.selection) { print("Selection changed: \(self.selection.count)") } } } func deleteOrders(offsets: IndexSet) { withAnimation { for index in offsets { self.modelContext.delete(self.orders[index]) } } } @State var selection = Set<PersistentIdentifier>() @Query var orders : [Order] @Environment(\.modelContext) var modelContext } If I use the mouse to select a single item, it behaves as expected. The item is selected, the onChange gets called, and if I choose Edit->Delete, the onDelete handler is called. If I use the mouse to shift-select multiple items, the behavior is similar to Select All above, but the selection Set count starts at the number of items I selected, and then is slowly whittled down to 0 or 1, with some random item being selected. I’d like for the Edit->Delete command to work with a keystroke (delete). How can I set the shortcut on an existing menu item without having to reimplement its behavior?
0
0
118
2w