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

SwiftUI Documentation

Posts under SwiftUI tag

2,336 Posts
Sort by:
Post not yet marked as solved
0 Replies
110 Views
My goal is to create Apples activity ring sparkle effect. So I found Paul Hudson's Vortex library. There is already a spark effect, but I don't know how to create a custom one that fits my needs. I'm still quite new to SwiftUI animations. Does someone have an idea how to do it? VortexView(createSparkle()) { Circle() .fill(.white) .frame(width: 16) .tag("circle") } func createSparkle() -> VortexSystem { let system = VortexSystem(tags: ["circle"]) system.birthRate = 150 system.emissionDuration = 0.2 system.idleDuration = 0.5 system.lifespan = 1.5 system.speed = 1.5 system.speedVariation = 0.2 system.angle = .degrees(330) system.angleRange = .degrees(30) system.acceleration = [0, 3] system.dampingFactor = 4 system.colors = .ramp(.white, .yellow, .yellow.opacity(0)) system.size = 0.1 system.sizeVariation = 0.1 system.stretchFactor = 8 return system } Vortex project: https://github.com/twostraws/Vortex
Posted
by iRIG.
Last updated
.
Post not yet marked as solved
0 Replies
134 Views
I have a peculiar situation, where the first time I present a sheet from a Section that has the header: set, the sheet disappears by itself the first time it is presented. @State private var show = false // … List { Section { Text("foo") } header: { Text("bar") } .sheet(isPresented: $show) { Text("baz") } // just to enable Button("toggle") { show = true } } In Xcode I get this warning when I present the sheet (taken from our live app): Attempt to present <_TtGC7SwiftUI29PresentationHostingControllerVS_7AnyView_: 0x10a819e00> on <_TtGC7SwiftUI19UIHostingControllerGVS_15ModifiedContentVS_7AnyViewVS_12RootModifier__: 0x10a020600> (from <_TtGC7SwiftUI32NavigationStackHostingControllerVS_7AnyView_: 0x10a0cba00>) while a presentation is in progress. Tested on iOS 17.4.1, iPadOS 17.4.0 (Simulator), Xcode 15.3 Previews.  Circumstances The circumstances are as following: a Section has to be in a List, and have content:, and header: or footer: set to something, and have the .sheet(…) set on the section itself. The problem does not occur with these sections: Section { Text("…") } Section { } footer: { Text("…") } Section { Text("…") } header: { } … but the following views have the sheet disappear the first time it is presented: Section { Text("…") } header: { Text("…") } Section { Text("…") } footer: { Text("…") } Section { Text("…") } header: { Text("…") } footer: { Text("…") } Is this a known issue, and are there any known workarounds to present from a Section? My best guess is to move the .sheet(…) to the parent container, but I'll have to restructure part of my code quite a bit to do so 😕
Posted
by vladimirs.
Last updated
.
Post not yet marked as solved
1 Replies
83 Views
My ".navigationTitle" is on my physical iPhone 14 and Simulator iPhone 15 not displayed, on Xcode Preview Screen is it displayed perfect. Why is it and what can i do that is displayed on my iPhone 14.
Posted Last updated
.
Post not yet marked as solved
0 Replies
82 Views
SwiftUI's PhotoPicker doesn't fit into the screen when I place it on a popover and click on it to select a photo. The relevant code I use: .popover( isPresented: $showAttachments ) { VStack(alignment: .leading, spacing: 20) { // ... PhotosPicker(selection: $photos) { HStack { Image(systemName: "photo") Text("Media") } } } } It seems like the photo picker is positioned relative to the popover position and I can't find any configuration options regarding to its' positioning. How to position the PhotoPicker correctly?
Posted Last updated
.
Post not yet marked as solved
1 Replies
478 Views
I'm using NavigationLink(value:label:) and .navigationDestination(for:destination:) in my SwiftUI watchOS app. However navigating in the app causes the system to emit the following errors to the console: <NavigationHostingControllerCache>: MISS at depth 1 in free stack [NavigationHostingControllerCache_UIKit] <_TtGC7SwiftUI32NavigationStackHostingControllerVS_7AnyView_: 0x125015000> containment skipped because sourceNavigationController or destination were nil or sourceNavigationController was equal to destination [NavigationHostingControllerCache_UIKit] Eject called for index: depth 1 in free stack Library: SwiftUI, Subsystem: com.apple.SwiftUI , Category: Invalid Configuration The navigation itself does work fine. I'm wondering there's something I can do to fix it or if this is an internal issue of the SwiftUI framework and cannot be addressed by me? (i.e. I can ignore this)
Posted Last updated
.
Post not yet marked as solved
0 Replies
90 Views
i'm struct dynamic island detail content dynamicIsland: { context in DynamicIsland { expandedContent(context: context) } compactLeading: { .... } compactTrailing: { ... } i want show different content based on context. private func expandedContent(context: ActivityViewContext<xxxx>)->DynamicIslandExpandedContent<some View> { if (context.state.style == 0) { return expandedControlContent1(context: context) } else if (context.state.style == 1) { return expandedControlContent2(context: context) } else { return expandedControlContent3(context: context) } } compiles error Function declares an opaque return type 'some View', but the return statements in its body do not have matching underlying types
Posted
by Highmore.
Last updated
.
Post not yet marked as solved
0 Replies
91 Views
Here is the view in which it works struct MileageHistoryView: View { let vehicle: Vehicle init(for vehicle: Vehicle) { self.vehicle = vehicle } @Environment(\.modelContext) private var context @Environment(\.editMode) private var editMode var sorted: [Mileage] { guard let history = vehicle.mileageHistory else { return [] } return history.sorted(by: { $0.timestamp > $1.timestamp }) } var body: some View { List { ForEach(sorted) { mileage in MileageListItem(mileage, editing: Binding(get: {editMode?.wrappedValue.isEditing ?? false}, set: {_ in })) } .onDelete(perform: deleteMileage) .deleteDisabled(editMode?.wrappedValue.isEditing ?? false ? false : true) } .id(editMode?.wrappedValue.isEditing) .navigationTitle("Mileage History") .scrollContentBackground(.hidden) .toolbar { ToolbarItem(placement: .topBarTrailing, content: { EditButton() }) } } } Here is the other view where it doesn't work. In this view, it seems like when the EditButton is pressed, no change is happening with the editMode so deleteDisabled() is always set to true. struct VehiclesView: View { @Environment(\.modelContext) private var context @Environment(\.editMode) private var editMode // Local @Query private var vehicles: [Vehicle] @State private var addVehicle = false @AppStorage("vehicle-edit-alert") private var showEditAlert = true @State private var editAlert = false @State private var editShown = false var body: some View { NavigationStack { List { ForEach(vehicles) { vehicle in NavigationLink(destination: VehicleView(vehicle), label: { VehicleListItem(vehicle) }) } .onDelete(perform: deleteVehicle) .deleteDisabled(self.editMode?.wrappedValue.isEditing ?? false ? false : true) } .id(self.editMode?.wrappedValue.isEditing) .scrollContentBackground(.hidden) .navigationTitle("Vehicles") .toolbar { ToolbarItem(placement: .topBarLeading, content: { if showEditAlert && !editShown { Button("Edit") { editAlert = true } } else { EditButton() } }) ToolbarItem(placement: .topBarTrailing, content: { Button(action: { addVehicle.toggle() }, label: { Image(systemName: "plus") }) .accessibilityHint("Opens the view to add a Vehicle") }) } .fullScreenCover(isPresented: $addVehicle, content: { VehicleEditor() }) } .scrollIndicators(.hidden) } } When EditButton() is used in the second view the list item is grayed out, but the buttons to delete aren't there. Does anybody know why this is happening?
Posted
by Xavier-k.
Last updated
.
Post not yet marked as solved
2 Replies
142 Views
We've been working on a SwiftUI app that randomly crashes with an exception. When navigating from one view to another, a rare exception is thrown, maybe every 1 / 200 times or so: <SwiftUI.UIKitNavigationController: 0x109888400> is pushing the same view controller instance (<_TtGC7SwiftUI32NavigationStackHostingControllerVS_7AnyView_: 0x10792d400>) more than once which is not supported and is most likely an error in the application : com.<companyName>.<appName> We haven't coded anything to directly push an instance of a view controller outside of what SwiftUI is doing. It seems to happen when the user taps on a NavigationLink view. It happens both in simulator and on device. Does anyone know what might cause this?
Posted
by GBecker.
Last updated
.
Post not yet marked as solved
0 Replies
96 Views
Dear Community, I have a use case where I have to present multiple sheets of different, non-resizable heights from a View. It seems like when multiple .presentationDetents() are specified and you control the current detent with selection:, SwiftUI always allows the user to resize the sheet, even if .presentationDragIndicator(.hidden) is set. In my use case, however, I wouldn't like to let the user do so, because this would result in a small view presented on a large sheet with lot of empty space around. Specifying just one presentationDetent and changing it or its height programmatically doesn't seem to work: the change does not reflect immediately, even if the view in the sheet is given a new id() every time. The only thing I could come up with is a custom detent as follows: import SwiftUI public class DynamicDetent: CustomPresentationDetent { static var height: CGFloat = 80 public static func height(in context: Context) -> CGFloat? { return height } } extension PresentationDetent { static let dynamic = Self.custom(DynamicDetent.self) } As the height() functon is being called every time the sheet is being displayed, setting DynamicDetent.height before displaying a new sheet works. Is there any other, less hacky way to achieve the same result?
Posted Last updated
.
Post not yet marked as solved
0 Replies
90 Views
Hello all, if I enable the .chartScrollableAxes(.horizontal) and .chartXVisibleDomain(length: length) for a chart view to zoom in the screenshot of the view misses the graphs. I use this extension: `extension View { @MainActor func snapshot() { let renderer = ImageRenderer(content: self) if let exportImage = renderer.nsImage { let pasteboard = NSPasteboard.general pasteboard.clearContents() pasteboard.writeObjects([exportImage]) } } }` The screenshot is taken with: Button("Snap") { let view = ChartView(text: $statusText, length: $chartLength) .padding() .frame(width: 1500, height: 500) view.snapshot() } If I omit .chartScrollableAxes(.horizontal) the snapshot is ok and the graphs are visible in the image but then a zoom is not possible and the whole range is shown. Any ideas?
Posted
by Zettifour.
Last updated
.
Post not yet marked as solved
0 Replies
87 Views
Hello, I have a question. I have a LookAroundPreview, that loads correctly a scene, and when I tap on it, it natively shows a view I can navigate in, and that I can close. All that is ok. However, when I want to display that same LookAroundPreview in a fullScreenCover (because my app needs it for navigation purposes), it directly shows the navigatable View with the closeButton. That I don't want. Is there an option to pass, that I missed? Is this a bug of the LookAroundPreview? Or is this wanted by Apple devs? Thank you very much for your help, Sincerely import SwiftUI struct ContentView: View { @State private var displayFullScreen = false //AppleLookAroundView is just a wrapper around native LookAroundPreview, that loads a NYC coordinate var body: some View { VStack { AppleLookAroundView() Spacer() Button("Display fullScreen cover") { displayFullScreen = true } Spacer() } .fullScreenCover(isPresented: $displayFullScreen) { VStack { AppleLookAroundView() Text("⬆ It somehow detects it is in a fullScreenCover and unwantingly change its display") } } } } import SwiftUI import MapKit import CoreLocation struct AppleLookAroundView: View { @State private var scene: MKLookAroundScene? let coordinate = CLLocationCoordinate2D(latitude: 40.651238394229324, longitude: -73.96432239237737) var body: some View { LookAroundPreview(scene: $scene, allowsNavigation: true, badgePosition: .bottomTrailing) .task { do { scene = try await fetchScene(for: coordinate) } catch { print("Couldn't fetch scene") } } .frame(height: 300) } private func fetchScene(for coordinate: CLLocationCoordinate2D) async throws -> MKLookAroundScene? { let lookAroundScene = MKLookAroundSceneRequest(coordinate: coordinate) let scene = try await lookAroundScene.scene return scene } } ![]("https://developer.apple.com/forums/content/attachment/a10a7701-dd8c-4d83-9a03-848cf0373417" "title=Capture d’écran 2024-04-24 à 12.56.46.png;width=898;height=1860") `` ![]("https://developer.apple.com/forums/content/attachment/d54f7fe1-aac8-4280-ab97-663f0bdd440f" "title=Capture d’écran 2024-04-24 à 12.56.34.png;width=924;height=1882") `
Posted Last updated
.
Post not yet marked as solved
0 Replies
76 Views
The regular case. Open a sheet by clicking a button. Next close the sheet using a Cancel button on it. The isPresented state variable is changed immediately, but while the dismissing animation isn't totally finished it's impossible to click the Button on the main parent screen and call the sheet presentation again. As I understand UIKit works differently and lets us click the Button but just calls a new modal view exactly after the previous animation is finished struct MyView: View { @State private var isPresented = false public var body: some View { VStack { Button(action: { isPresented = true }, label: { Text("Button") }) Spacer() } .sheet(isPresented: $isPresented) { sheetContent } } var sheetContent: some View { VStack { Text("Cancel") .onTapGesture { isPresented = false } Spacer() } } } @Apple Could you please fix it in SwiftUI?
Posted Last updated
.
Post not yet marked as solved
0 Replies
83 Views
Condition: We have an existing app that runs on iPhone and iPad. We want to make it compatible with macOS, along with it we want to leverage some of the macOS native components. We achieved this using macCatalyst, but now we want to build common components using swiftUI for both macOS and iOS platforms. Challenge: Using SwiftUI view for mac development Approach 1: We created a Mac bundle that contained Mac specific views (using Appkit views). This approach worked fine for creating and using components that are specific to macOS. Now while developing and using SwiftUI views in mac bundle we face following error -> (NSHostingViewController symbol not found). Approach 2: We tried creating a separate Mac app and make it part of MacCatalyst app. In this approach we were able to show NSStatusBar and add text using SwiftUI view. But the status bar appearance is inconsistent, sometimes NSStatusBar icon appears but other times it just won't appear. Can anyone help with the right approach for this scenarios
Posted Last updated
.
Post not yet marked as solved
2 Replies
390 Views
I Implement a 'SubscriptionStoreView' using 'groupID' into a project (iOS is targeting 17.2 and macOS is targeting 14.1).Build/run the application locally (both production and development environments will work fine), however once the application is live on the AppStore in AppStoreConnect, SubscriptionStoreView no longer shows products and only shows 'Subscription Unavailable' and 'The subscription is unavailable in the current storefront.' - this message is shown live in production for both iOS and macOS targets. There is no log messages shown in the Console that indicate anything going wrong with StoreKit 2, but I haven't made any changes to my code and noticed this first start appearing about 5 days ago. I expect the subscription store to be visible to all users and for my products to display. My application is live on both the iOS and macOS AppStores, it passed App Review and I have users who have previously been able to subscribe and use my application, I have not pushed any new changes, so something has changed in StoreKit2 which is causing unexpected behaviour and for this error message to display. As 'SubscriptionStoreView' is a view provided by Apple, I'm really not sure on the pathway forward other than going back to StoreKit1 which I really don't want to do. Is there any further error information that can be provided on what might be causing this and how I can fix it? (I have created a feedback ticket FB13658521)
Posted
by Lukesrad.
Last updated
.
Post not yet marked as solved
1 Replies
88 Views
Hi everyone, I'm trying to make use of a background actor in my SwiftUI project. Inserting data works with the ModelContainer's mainContext. Another context in a ModelActor, however, fails to write into the same database. I verify the results by opening the SQLite file on the file system. While the mainContext.insert call does indeed insert a row into the table, the ModelActor's context fails to do so. There is no error or message received in the ModelActor. The property autosaveEnabled is set to true. I wrote a sample project to reproduce the issue in isolation. It consists of a single source file that introduces the Model ToDo, the ToDoView, initializes the ModelContainer and ModelActor. Please find the source code below. Is there any mistake in my approach? import SwiftUI import SwiftData @Model final class ToDo { let title: String init(title: String) { self.title = title } } @main struct testSwiftDataApp: App { @State var modelContainer: ModelContainer @State var backgroundData: BackgroundDataActor init() { let modelContainer: ModelContainer = try! ModelContainer(for: ToDo.self) self.modelContainer = modelContainer self.backgroundData = BackgroundDataActor( modelContainer: modelContainer ) } var body: some Scene { WindowGroup { ToDoView(backgroundData: self.backgroundData) .modelContainer(modelContainer) } } } struct ToDoView: View { @Environment(\.modelContext) var modelContext @Query var todos: [ToDo] let backgroundData: BackgroundDataActor var modelContainer: ModelContainer { self.modelContext.container } var body: some View { VStack { Text("Add ToDo") TextField( "", text: .constant( "URL to database: " + "\(self.modelContainer.configurations.first!.url)" ) ) // This action will be invoked on the ModelActor's context Button { Task { let todo = ToDo(title: "Step 1") await self.backgroundData.store( id: todo.persistentModelID ) } } label: { Text("Create ToDo in background") } // This action will be invoked on the mainContext Button { Task { let todo = ToDo(title: "Step 2") self.modelContainer.mainContext.insert(todo) } } label: { Text("Create ToDo in foreground") } // Show the query results VStack { Text("Available ToDos") ForEach(self.todos) { Text($0.title) } } } } } @ModelActor actor BackgroundDataActor: ModelActor { func store(id: PersistentIdentifier) { print("Trying to save") print("Is auto save enabled: \(self.modelContext.autosaveEnabled)") if let dbo = self[id, as: ToDo.self] { self.modelContext.insert(dbo) try! self.modelContext.save() print("Saved into database") } } }
Posted
by anmarb.
Last updated
.
Post not yet marked as solved
1 Replies
142 Views
I prepare an app to migrate from ObservableObject to Observable, from EnvironmentObject to Environment(MyClass.self) and so so forth. That works OK, very simple. But, that forces to run on macOS 14 or more recent. So I would like to have it conditionally, such as: if macOS 14 available @Environment(ActiveConfiguration.self) var activeConfiguration: ActiveConfiguration otherwise @EnvironmentObject var activeConfiguration: ActiveConfiguration The same for the class declaration: if macOS 14 available @Observable class ActiveConfiguration { var config = Configuration() } otherwise class ActiveConfiguration : ObservableObject { @Published var config = Configuration() } Is there a way to achieve this (I understand it is not possible through extensions of Macros, as we can do for modifiers) ? Could I define 2 classes for ActiveConfiguration, but then what about @Environment ?
Posted
by Claude31.
Last updated
.
Post not yet marked as solved
3 Replies
170 Views
On my shop and content views of my app, I have a shopping cart SF symbol that I've modified with a conditional to show the number of items in the cart if the number of items is above zero. However, whenever I change tabs and back again, that icon disappears even though there should be an item in the cart. I have a video of the error, but I have no idea how to post it. Here is some of the code, let me know if you need to see more of it: CartManager.swift import Foundation import SwiftUI @Observable class CartManager { /*private(set)*/ var products: [Product] = [] private(set) var total: Int = 0 private(set) var numberofproducts: Int = 0 func count() -> Int { numberofproducts = products.count return numberofproducts } func addToCart(product: Product) { products.append(product) total += product.price numberofproducts = products.count } func removeFromCart(product: Product) { products = products.filter { $0.id != product.id } total -= product.price numberofproducts = products.count } } ShopPage.swift import SwiftUI struct ShopPage: View { @Environment(CartManager.self) private var cartManager var columns = [GridItem(.adaptive(minimum: 135), spacing: 0)] @State private var searchText = "" let items = ["LazyHeadphoneBean", "ProperBean", "BabyBean", "RoyalBean", "SpringBean", "beanbunny", "CapBean"] var filteredItems: [Bean] { guard searchText.isEmpty else { return beans } return beans.filter { $0.imageName.localizedCaseInsensitiveContains(searchText) } } var body: some View { NavigationStack { ZStack(alignment: .top) { Color.white .ignoresSafeArea(edges: .all) VStack { AppBar() .environment(cartManager) ScrollView() { LazyVGrid(columns: columns, spacing: 20) { ForEach(productList, id: \.id) { product in NavigationLink { beanDetail(product: product) .environment(cartManager) } label: { ProductCardView(product: product) .environment(cartManager) } } } } } .navigationBarDrawer(displayMode: .always)) } } .environment(cartManager) } var searchResults: [String] { if searchText.isEmpty { return items } else { return items.filter { $0.contains(searchText)} } } } #Preview { ShopPage() .environment(CartManager()) } struct AppBar: View { @Environment(CartManager.self) private var cartManager var body: some View { NavigationStack { VStack (alignment: .leading){ HStack { Spacer() NavigationLink(destination: CartView() .environment(cartManager) ) { CartButton(numberOfProducts: cartManager.products.count) } } Text("Shop for Beans") .font(.largeTitle .bold()) } } .padding() .environment(CartManager()) } } CartButton.swift import SwiftUI struct CartButton: View { var numberOfProducts: Int var body: some View { ZStack(alignment: .topTrailing) { Image(systemName: "cart.fill") .foregroundStyle(.black) .padding(5) if numberOfProducts > 0 { Text("\(numberOfProducts)") .font(.caption2).bold() .foregroundStyle(.white) .frame(width: 15, height: 15) .background(Color(hue: 1.0, saturation: 0.89, brightness: 0.835)) .clipShape(RoundedRectangle(cornerRadius: 50)) } } } } #Preview { CartButton(/*numberOfProducts: 1*/numberOfProducts: 1) }
Posted
by KittyCat.
Last updated
.
Post not yet marked as solved
0 Replies
142 Views
Hello, I have been working on SwiftData since a month now and i found very weird that every time i update a data inside a SwiftData model my app became very slow. I used the instrument if something was wrong, and i see memory increasing without releasing. My app have a list with check and unchecked elements (screeshot below). I just press check and unchecked 15 times and my memory start from 149mb to 361mb (screenshots below). For the code i have this model. final class Milestone: Identifiable { // ********************************************************************* // MARK: - Properties @Transient var id = UUID() @Attribute(.unique) var uuid: UUID var text: String var goalId: UUID var isFinish: Bool var createdAt: Date var updatedAt: Date var goal: Goal? init(from todoTaskResponse: TodoTaskResponse) { self.uuid = todoTaskResponse.id self.text = todoTaskResponse.text self.goalId = todoTaskResponse.goalId self.isFinish = todoTaskResponse.isFinish self.createdAt = todoTaskResponse.createdAt self.updatedAt = todoTaskResponse.updatedAt } init(uuid: UUID, text: String, goalId: UUID, isFinish: Bool, createdAt: Date, updatedAt: Date, goal: Goal? = nil) { self.uuid = uuid self.text = text self.goalId = goalId self.isFinish = isFinish self.createdAt = createdAt self.updatedAt = updatedAt self.goal = goal } } For the list i have var milestonesView: some View { ForEach(milestones) { milestone in MilestoneRowView(task: milestone) { milestone.isFinish.toggle() } .listRowBackground(Color.backgroundComponent) } .onDelete(perform: deleteMilestone) } And this is the cell struct MilestoneRowView: View { // ********************************************************************* // MARK: - Properties var task: Milestone var action: () -> Void init(task: Milestone, action: @escaping () -> Void) { self.task = task self.action = action } var body: some View { Button { action() } label: { HStack(alignment: .center, spacing: 8) { Image(systemName: task.isFinish ? "checkmark.circle.fill" : "circle") .font(.title2) .padding(3) .contentShape(.rect) .foregroundStyle(task.isFinish ? .gray : .primary) .contentTransition(.symbolEffect(.replace)) Text(task.text) .strikethrough(task.isFinish) .foregroundStyle(task.isFinish ? .gray : .primary) } .foregroundStyle(Color.backgroundComponent) } .animation(.snappy, value: task.isFinish) } } Does someone have a idea? Thanks
Posted
by agalpin.
Last updated
.
Post not yet marked as solved
0 Replies
118 Views
Hello. I have the following question. I call the nextBatch() method on MusicItemCollection to get the next collection of artist albums. Here is my method: func allAlbums2(artist: Artist) async throws -> [Album] { var allAlbums: [Album] = [] artist.albums?.forEach { allAlbums.append($0) } guard let albums = artist.albums else { return [] } var albumsCollection = albums while albumsCollection.hasNextBatch { let response = try await albumsCollection.nextBatch() if let response { albumsCollection = response var albums = [Album]() albumsCollection.forEach({ albums.append($0)}) allAlbums.append(contentsOf: albums) } } return allAlbums } The problem is as follows. Sometimes it happens that some albums not in nextBatch are not returned (I noticed one, I didn't check the others). This happens once every 50-100 requests. The number of batches is returned the same when the album is skipped. The same albums are returned in the batch where the album was missed. I have a question, do I have a problem with multi-threading or something else or is it a problem in the API. The file contains prints of the returned batches. One with a missing album, the other without a missing one. There are about 3000 lines in the file. I will be grateful for a hint or an answer. Thank you! Here link to file: https://files.fm/u/nj4r5wgyg3
Posted
by 20a.
Last updated
.
Post not yet marked as solved
1 Replies
93 Views
Hello Apple Developer Forum, I'm reaching out because I've encountered an issue with my app's implementation involving the ScrollView and the digitalCrown, and I'm hoping to find some guidance or assistance from the community. Currently, I'm developing an app where users can navigate through dates using the digitalCrown to change the "$scrollAmount", which then dynamically updates the ScrollView with events corresponding to that date. However, I've run into a problem where the ScrollView is being inadvertently scrolled by the digitalCrown every time it's initiated. Ideally, I would like to disable the digitalCrown's interaction with the ScrollView altogether, so that the ScrollView is only scrolled using touch inputs and not by the digitalCrown. I've tried several approaches to achieve this, but haven't had much success so far. Could anyone please provide some guidance or suggestions on how I can effectively disable the digitalCrown's interaction with the ScrollView while still allowing touch-based scrolling? Any help or insights into this matter would be greatly appreciated. Thank you very much in advance for your time and assistance. Best regards, Example code: var body: some View { NavigationView { VStack { HStack{ Text("\(formattedDate(for: scrollAmount, format: lineOne))") .onTapGesture { scrollAmount = 0.0 } } ScrollView{ ForEach(viewModel.events, id: \.event) { viewModelItem in let event = viewModelItem.event VStack { HStack { Text(event.title) } } } } .scrollDisabled(true) } } .focusable(isFocused) .digitalCrownRotation( detent: $scrollAmount, from: -365.0, through: 365.0, by: 1.0, sensitivity: .low, isContinuous: false, isHapticFeedbackEnabled: true) .onChange(of: scrollAmount) { let roundedValue = round(scrollAmount) scrollAmount = roundedValue viewModel.fetchEvents(for: scrollAmount) } } }
Posted
by wurx.
Last updated
.