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

Posts under SwiftUI tag

200 Posts

Post

Replies

Boosts

Views

Activity

Can build my app but not Archive
Apologies that this is probably a simple problem. I've started from a sample code provided by Apple and changed it quite significantly. However, I'm not able to Archive the app. The original visionOS sample code has the same issue, so hopefully someone will be able to spot the problem: https://developer.apple.com/documentation/visionos/creating-stereoscopic-image-in-visionos The problems shown in the log are: Undefined symbol: _main Linker command failed with exit code 1 (use -v to see invocation) The first error seems to say that there's no "main" but there is indeed a @main in the EntryPoint.swift file. Any ideas? I have archived other apps (built from scratch) successfully, but clearly there's something different about this sample code. Many thanks!
7
1
587
Jan ’25
How to remove top space of principal ToolbarItem in sidebarAdaptable TabView
When creating a principal ToolbarItem in a sidebarAdaptable TabView, unwanted space appears at the top. Here's my code: struct ContentView: View { var body: some View { TabView { Tab("Tab", systemImage: "star") { NavigationStack { Text("Hello, World!") .toolbar { ToolbarItem(placement: .principal) { Text("↑ Space") } } .navigationBarTitleDisplayMode(.inline) } } } .tabViewStyle(.sidebarAdaptable) } } I would like to know how to remove this space. Environment: Xcode 16.2.0 iOS 18.2
2
1
327
Jan ’25
Struggling to display DeviceActivityReport view in a widget
I want to add a widget to my app that will display the # of pickups the user has for the day. I have the DeviceActivityReport working in the main app but can't get it to display in the widget since it is not a supported view for widgets. Is there any workaround for getting this view to the widget? I tried converting the DeviceActivityReport view to a UI image thinking maybe that would be a way to use a widget approved view type but ImageRenderer seems to fail to render an image for the view (which is just a Text view). To summarize my questions: Is it possible to display a DeviceActivityReport in a widget? If so, what is the best practice? Is converting the DeviceActivityReport view into an image and displaying that in a widget an option? Here's my attempt to convert the DeviceActivityReport view into a UIImage: import SwiftUI import _DeviceActivity_SwiftUI struct PickupsDeviceActivityReport: View {     @State private var context: DeviceActivityReport.Context = .totalActivity     @State private var renderedImage = Image(systemName: "exclamationmark.triangle")     @Environment(\.displayScale) var displayScale     var body: some View {         renderedImage             .onAppear { render() }             .onChange(of: context) {                 _ in render()             }     }     @MainActor func render() {         let renderer = ImageRenderer(content: DeviceActivityReport(context))         renderer.scale = displayScale         if let uiImage = renderer.uiImage {             renderedImage = Image(uiImage: uiImage)         }     } } Help is appreciated. Thank you.
3
3
1.4k
Jan ’25
How to remove margins around built-in views?
I want to have my own background and foreground colors for some views and I am having a bit of trouble. I cannot figure out how to remove the margins around some built-in views. One example is below. The ScrollView portion is always black or white, depending on whether I am I dark mode or not. I've added various colors and borders to see what is going on below. I've also tried adding the modifiers to the Scroll View rather than the TextEditor and it doesn't work at all. If I don't have the .frame modifier on the ScrollView, the TextEditor moves to the top of its frame for some reason. I've played with .contentMargins, .edgeInsets, etc. with no luck How do I get the TextEditor to fill the entire ScrollView without the margin? Thanks! import SwiftUI struct TextEditorView: View { @Binding var editString: String var numberOfLines: Int var lineHeight: CGFloat { UIFont.preferredFont(forTextStyle: .body).lineHeight } var viewHeight: CGFloat { lineHeight * CGFloat(numberOfLines) + 8 } var body: some View { ScrollView([.vertical], showsIndicators: true) { TextEditor(text: $editString) .border(Color.red, width: 5) .foregroundStyle(.yellow) .background(.blue) .frame(minHeight:viewHeight, maxHeight: viewHeight) .scrollContentBackground(.hidden) } .frame(minHeight:viewHeight, maxHeight: viewHeight) } }
0
0
194
Jan ’25
Unwanted "More" button in tabView when selected tab is in 5th position and beyond
Hello SwiftUI devs, I would like to remove the "More" button that appears in the top left of the screen whenever the selected tab of a tab view is in 5th position and beyond. It ruins the layout. struct ContentView: View { private let tabs = (1...10).map { "\($0)" } @State private var selectedTab: String = "5" var body: some View { TabView(selection: $selectedTab) { ForEach(tabs, id: \.self) { tab in Text("Tab \(tab)") .tabItem { Label("Tab \(tab)", systemImage: "star") } .toolbar(.hidden, for: .tabBar) } } } } At first glance, one easy fix would be to rearrange the tabs list in the ForEach loop, putting the selected tab at the first position. This does the trick BUT we lose the states of the views, which is out of the question in my use-case. Getting rid of the tab view and handling the logic with a simple Switch paired with a state restoration mechanism using SceneStorage or SwiftData is probably possible but sounds like a white elephant compared to finding a solution to remove that "More" button. Thank you
1
1
605
Jan ’25
How do I pass a binding to a focus state?
In a SwiftUI lab, I was asking about setting the focus state down a view hierarchy. The answer I got was to pass the focus state down the views as a binding. Conceptually, that made sense, so I moved on to other questions. But now that I am trying to implement it, I am having problems. In the parent view, I have something like this: @FocusState private var focusElement: UUID? Then I am setting a property like this in the child view: @Binding var focusedId: UUID? When I try to create the detail view, I'm trying this: DetailView(focusedId: $focusElement) But this doesn't work. The error I get is: Cannot convert value of type 'FocusState<UUID?>.Binding' to expected argument type 'Binding<UUID?>' What is the right way to pass down the focus state to a child view so that it can update back up to the parent view? I am trying to update from one child view, and have a TextField in a sibling view get focus.
2
0
13k
Jan ’25
Problem with connecting the workout data to a SwiftUI View.
Hello. I am building an app that shows my walk workouts and in the detail view I want to show the route I took while walking, similar to that of the Apple Fitness App. There is a problem though, I cannot seem to understand how to connect the @State property workoutLocations array that would be used to draw the route on the map with what I get from the query. The task does successfully fetches the data but then when I try to use it later in a do-catch block nothing happens. What am I missing here? import SwiftUI import MapKit import HealthKit struct DetailView: View { @Environment(HealthKitManager.self) var healthKitManager let workout: HKWorkout @State private var workoutLocations: [CLLocation] = [] var body: some View { ScrollView { //... } .task { guard let store = self.healthKitManager.healthStore else { fatalError("healthStore is nil. App is in invalid state.") } let walkingObjectQuery = HKQuery.predicateForObjects(from: workout) let routeQuery = HKAnchoredObjectQueryDescriptor(predicates: [.workoutRoute(walkingObjectQuery)], anchor: nil) let queryResults = routeQuery.results(for: store) let task = Task { var workoutRouteLocations: [CLLocation] = [] for try await result in queryResults { let routeSamples = result.addedSamples for routeSample in routeSamples { let routeQueryDescriptor = HKWorkoutRouteQueryDescriptor(routeSample) let locations = routeQueryDescriptor.results(for: store) for try await location in locations { workoutRouteLocations.append(location) print(workoutRouteLocations.count) // this prints out the number of locations in the sample. } } } return workoutRouteLocations } do { print(try await task.value.count) // this prints nothing. Therefore if I try to update workoutLocations array from here it would do nothing as well // workoutLocations = try await task.value therefore does nothing and the array just doesn't get populated with the results of the task } catch { print(error) } } } }
2
0
828
Jan ’25
Do not have permission to open the file
In macOS, I am encountering an issue where the system API fails to grant permission to open a file despite enabling the necessary Read/Write permissions within the SandBox. Could you please elucidate the reasons behind this behavior? Thanks! func finderOpenFileSystem(at path: String) { let fileURL = URL(fileURLWithPath: path) guard FileManager.default.fileExists(atPath: path) else { print("Error: File does not exist at path: \(path)") return } let success = NSWorkspace.shared.open(fileURL) if success { print("File opened successfully: \(fileURL)") } else { print("Error: Failed to open file: \(fileURL)") } }
1
0
476
Jan ’25
Xcode unable to find custom info.plist file
Hello, New to swift ui and xcode. I am building a mobil app that will need bluetooth capabilities. When I make my custom info.plist file and set "Generate info.plist file" to No, it states it cannot find my file. Then when I set that to "Yes" it gives me an error stating that there are multiple versions of the file. In my editor I cant seem to set a path to it either. Any help would be greatly appreciated. this is the result when the the section is set to No Cannot code sign because the target does not have an Info.plist file and one is not being generated automatically. Apply an Info.plist file to the target using the INFOPLIST_FILE build setting or generate one automatically by setting the GENERATE_INFOPLIST_FILE build setting to YES (recommended). this is when its set to yes: Multiple commands produce '/Users/thatcherdeyoework/Library/Developer/Xcode/DerivedData/SwiftUI-weather-etzagqgbgkjotzenbomwvkhjfhzt/Build/Products/Debug-iphoneos/SwiftUI-weather.app/Info.plist'
2
0
397
Jan ’25
Fatal error: Duplicate keys of type 'AnyHashable' were found in a Dictionary
I get the following fatal error when the user clicks Save in AddProductionView. Fatal error: Duplicate keys of type 'AnyHashable' were found in a Dictionary. This usually means either that the type violates Hashable's requirements, or that members of such a dictionary were mutated after insertion. As far as I’m aware, SwiftData automatically makes its models conform to Hashable, so this shouldn’t be a problem. I think it has something to do with the picker, but for the life of me I can’t see what. This error occurs about 75% of the time when Save is clicked. I'm using Xcode 16.2 and iPhone SE 2nd Gen. Any help would be greatly appreciated… Here is my code: import SwiftUI import SwiftData @main struct MyApp: App { var body: some Scene { WindowGroup { ContentView() .modelContainer(for: Character.self, isAutosaveEnabled: false) } } } @Model final class Character { var name: String var production: Production var myCharacter: Bool init(name: String, production: Production, myCharacter: Bool = false) { self.name = name self.production = production self.myCharacter = myCharacter } } @Model final class Production { var name: String init(name: String) { self.name = name } } struct ContentView: View { @State private var showingSheet = false var body: some View { Button("Add", systemImage: "plus") { showingSheet.toggle() } .sheet(isPresented: $showingSheet) { AddProductionView() } } } struct AddProductionView: View { @Environment(\.dismiss) private var dismiss @Environment(\.modelContext) var modelContext @State var production = Production(name: "") @Query var characters: [Character] @State private var characterName: String = "" @State private var selectedCharacter: Character? var filteredCharacters: [Character] { characters.filter { $0.production == production } } var body: some View { NavigationStack { Form { Section("Details") { TextField("Title", text: $production.name) } Section("Characters") { List(filteredCharacters) { character in Text(character.name) } HStack { TextField("Character", text: $characterName) Button("Add") { let newCharacter = Character(name: characterName, production: production) modelContext.insert(newCharacter) characterName = "" } .disabled(characterName.isEmpty) } if !filteredCharacters.isEmpty { Picker("Select your role", selection: $selectedCharacter) { Text("Select") .tag(nil as Character?) ForEach(filteredCharacters) { character in Text(character.name) .tag(character as Character?) } } .pickerStyle(.menu) } } } .toolbar { Button("Save") { //Fatal error: Duplicate keys of type 'AnyHashable' were found in a Dictionary. This usually means either that the type violates Hashable's requirements, or that members of such a dictionary were mutated after insertion. if let selectedCharacter = selectedCharacter { selectedCharacter.myCharacter = true } modelContext.insert(production) do { try modelContext.save() } catch { print("Failed to save context: \(error)") } dismiss() } .disabled(production.name.isEmpty || selectedCharacter == nil) } } } }
2
0
843
Jan ’25
Not able to save with SwiftData. "The file “default.store” couldn’t be opened."
I get this message when trying to save my Models. CoreData: error: SQLCore dispatchRequest: exception handling request: <NSSQLSaveChangesRequestContext: 0x303034540> , I/O error for database at /var/mobile/Containers/Data/Application/726ECA8C-6C67-4BFE-89E7-AFD8A83CAA5D/Library/Application Support/default.store. SQLite error code:1, 'no such table: ZCALENDARMODEL' with userInfo of { NSFilePath = "/var/mobile/Containers/Data/Application/726ECA8C-6C67-4BFE-89E7-AFD8A83CAA5D/Library/Application Support/default.store"; NSSQLiteErrorDomain = 1; } SwiftData.DefaultStore save failed with error: Error Domain=NSCocoaErrorDomain Code=256 "The file “default.store” couldn’t be opened." UserInfo={NSFilePath=/var/mobile/Containers/Data/Application/726ECA8C-6C67-4BFE-89E7-AFD8A83CAA5D/Library/Application Support/default.store, NSSQLiteErrorDomain=1} The App has Recipes and Calendars and the user can select a Recipe for each Calendar day. The recipe should not be referenced, it should be saved by SwiftData along with the Calendar. import SwiftUI import SwiftData enum CalendarSource: String, Codable { case created case imported } @Model class CalendarModel: Identifiable, Codable { var id: UUID = UUID() var name: String var startDate: Date var endDate: Date var recipes: [String: RecipeData] = [:] var thumbnailData: Data? var source: CalendarSource? // Computed Properties var daysBetween: Int { let days = Calendar.current.dateComponents([.day], from: startDate.midnight, to: endDate.midnight).day ?? 0 return days + 1 } var allDates: [Date] { startDate.midnight.allDates(upTo: endDate.midnight) } var thumbnailImage: Image? { if let data = thumbnailData, let uiImage = UIImage(data: data) { return Image(uiImage: uiImage) } else { return nil } } // Initializer init(name: String, startDate: Date, endDate: Date, thumbnailData: Data? = nil, source: CalendarSource? = .created) { self.name = name self.startDate = startDate self.endDate = endDate self.thumbnailData = thumbnailData self.source = source } // Convenience initializer to create a copy of an existing calendar static func copy(from calendar: CalendarModel) -> CalendarModel { let copiedCalendar = CalendarModel( name: calendar.name, startDate: calendar.startDate, endDate: calendar.endDate, thumbnailData: calendar.thumbnailData, source: calendar.source ) // Copy recipes copiedCalendar.recipes = calendar.recipes.mapValues { $0 } return copiedCalendar } // Codable Conformance private enum CodingKeys: String, CodingKey { case id, name, startDate, endDate, recipes, thumbnailData, source } required init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) id = try container.decode(UUID.self, forKey: .id) name = try container.decode(String.self, forKey: .name) startDate = try container.decode(Date.self, forKey: .startDate) endDate = try container.decode(Date.self, forKey: .endDate) recipes = try container.decode([String: RecipeData].self, forKey: .recipes) thumbnailData = try container.decodeIfPresent(Data.self, forKey: .thumbnailData) source = try container.decodeIfPresent(CalendarSource.self, forKey: .source) } func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(id, forKey: .id) try container.encode(name, forKey: .name) try container.encode(startDate, forKey: .startDate) try container.encode(endDate, forKey: .endDate) try container.encode(recipes, forKey: .recipes) try container.encode(thumbnailData, forKey: .thumbnailData) try container.encode(source, forKey: .source) } } import SwiftUI struct RecipeData: Codable, Identifiable { var id: UUID = UUID() var name: String var ingredients: String var steps: String var thumbnailData: Data? // Computed property to convert thumbnail data to a SwiftUI Image var thumbnailImage: Image? { if let data = thumbnailData, let uiImage = UIImage(data: data) { return Image(uiImage: uiImage) } else { return nil // No image } } init(recipe: RecipeModel) { self.name = recipe.name self.ingredients = recipe.ingredients self.steps = recipe.steps self.thumbnailData = recipe.thumbnailData } } import SwiftUI import SwiftData @Model class RecipeModel: Identifiable, Codable { var id: UUID = UUID() var name: String var ingredients: String var steps: String var thumbnailData: Data? // Store the image data for the thumbnail static let fallbackSymbols = ["book.pages.fill", "carrot.fill", "fork.knife", "stove.fill"] // Computed property to convert thumbnail data to a SwiftUI Image var thumbnailImage: Image? { if let data = thumbnailData, let uiImage = UIImage(data: data) { return Image(uiImage: uiImage) } else { return nil // No image } } // MARK: - Initializer init(name: String, ingredients: String = "", steps: String = "", thumbnailData: Data? = nil) { self.name = name self.ingredients = ingredients self.steps = steps self.thumbnailData = thumbnailData } // MARK: - Copy Function func copy() -> RecipeModel { RecipeModel( name: self.name, ingredients: self.ingredients, steps: self.steps, thumbnailData: self.thumbnailData ) } // MARK: - Codable Conformance private enum CodingKeys: String, CodingKey { case id, name, ingredients, steps, thumbnailData } required init(from decoder: Decoder) throws { ... } func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(id, forKey: .id) try container.encode(name, forKey: .name) try container.encode(ingredients, forKey: .ingredients) try container.encode(steps, forKey: .steps) try container.encode(thumbnailData, forKey: .thumbnailData) } }
1
0
908
Jan ’25
SwiftData Relationship Delete Not Working (SwiftData/PersistentModel.swift:359)
SwiftData delete isn't working, when I attempt to delete a model, my app crashes and I get the following error: SwiftData/PersistentModel.swift:359: Fatal error: Cannot remove My_App.Model2 from relationship Relationship - name: model2, options: [], valueType: Model2, destination: Model2, inverseName: models3, inverseKeypath: Optional(\Model2.models3) on My_App.Model3 because an appropriate default value is not configured. I get that it's saying I don't have a default value, but why do I need one? Isn't @Relationship .cascade automatically deleting the associated models? And onto of that, why is the error occurring within the do block, shouldn't it be caught by the catch, and printed? I have put together a sample project below. import SwiftUI import SwiftData @main struct MyApp: App { var body: some Scene { WindowGroup { ContentView() .modelContainer(for: Model3.self) } } } @Model class Model1 { var name: String @Relationship(deleteRule: .cascade, inverse: \Model2.model1) var models2: [Model2] = [] init(name: String) { self.name = name } } @Model class Model2 { var name: String var model1: Model1 @Relationship(deleteRule: .cascade, inverse: \Model3.model2) var models3: [Model3] = [] init(name: String, model1: Model1) { self.name = name self.model1 = model1 } } @Model class Model3 { var name: String var model2: Model2 init(name: String, model2: Model2) { self.name = name self.model2 = model2 } } struct ContentView: View { @Query var models1: [Model1] @Environment(\.modelContext) var modelContext var body: some View { NavigationStack { List(models1) { model1 in Text(model1.name) .swipeActions { Button("Delete", systemImage: "trash", role: .destructive) { modelContext.delete(model1) do { try modelContext.save() //SwiftData/PersistentModel.swift:359: Fatal error: Cannot remove My_App.Model2 from relationship Relationship - name: model2, options: [], valueType: Model2, destination: Model2, inverseName: models3, inverseKeypath: Optional(\Model2.models3) on My_App.Model3 because an appropriate default value is not configured. } catch { print(error.localizedDescription) } } } } .toolbar { Button("Insert", systemImage: "plus") { modelContext.insert(Model3(name: "model3", model2: Model2(name: "model2", model1: Model1(name: "model1")))) } } } } }
1
0
1.1k
Jan ’25
How to Visualize Data in a DataFrame Using Charts
I want to visualize the data stored in a DataFrame using various charts (barmark, sectormark, linemark, etc.). My questions are as follows: Can a DataFrame be used directly within a chart? If so, could you provide a simple example? If it cannot be used directly, what is the correct way to use it? Could you provide an example? Thank you for your help. Best regards.
0
1
386
Jan ’25
wrong value on the first buttonClick
When I run this code, and click on one of both 'currentZin' in the first screen that comes up with the view WordView, I see the content of the .preview value I used to initialize currentVerse (Verse= .preview) and not the values of the currentVerse that is in the Button action. When I leave the WordView-sheet and click again the WordView shows the good result. I looks that on the first click the currentVerse = verse in the Button is not executed. If Ido not initialize it, it has a nil value. Can Anyone explain what happens and how to solve it. struct HymnVerses: View { var hymn:Hymn @State private var currentZin: Int = 2 @State private var isLatin: Bool = true @State private var isMasked: Bool = false @State private var isTranslation: Bool = true @State private var currentSentence: String = "" @State private var showWordView: Bool = false @State private var currentVerse: Verse = .preview // Deze calculated property wordt op voorhand berekend. // Hierdoor blijft de referentie naar het origineel bestaan // wanneer ik currentVerse bereken. Daarvoor geraakte ik ze altijd kwijt. private var filteredVerses: [Verse] { hymn.verses.filter { $0.zin &lt;= currentZin } } var body: some View { List { ForEach(filteredVerses) { verse in VStack(alignment: .leading) { Button { currentVerse = verse showWordView = true } label: { Text("\(verse.zin). \(currentSentence(for: verse))") .font(.headline) } } } .onAppear { currentVerse = filteredVerses.first! } }.sheet(isPresented: $showWordView, content: { WordView(vers: currentVerse, showWordView: $showWordView) }) .toolbar { ToolbarItem(placement: .bottomBar) { Button(isLatin ? "Dutch" : "Latin") { isLatin.toggle() } } ToolbarItem(placement: .bottomBar) { Button(isMasked ? "Unmask" : "Mask") { isMasked.toggle() } } ToolbarItem(placement: .bottomBar) { Button("Restart") { currentZin = 1 } } ToolbarItem(placement: .bottomBar) { Button("Next") { if currentZin &lt; hymn.verses.count { currentZin += 1 } } } } } func maskLetters(in sentence: String, with mask: Character = "*") -&gt; String { return sentence.map { char in if char.isLetter { return String(mask) } else { return String(char) } }.joined() } private func currentSentence(for verse: Verse) -&gt; String { var temp: String { return isLatin ? verse.latijn : verse.nederlands } if isMasked { return maskLetters(in: temp) } else { return temp } } } #Preview { /// the navigationStack is nodig omdat anders de toolbar niet zichtbaar is met #Preview NavigationStack { let allTexts = AllTexts() HymnVerses(hymn: .preview).environment(allTexts) } }
3
0
204
Jan ’25
OCR does not work
Hi, I'm working with a very simple app that tries to read a coordinates card and past the data into diferent fields. The card's layout is COLUMNS from 1-10, ROWs from A-J and a two digit number for each cell. In my app, I have field for each of those cells (A1, A2...). I want that OCR to read that card and paste the info but I just cant. I have two problems. The camera won't close. It remains open until I press the button SAVE (this is not good because a user could take 3, 4, 5... pictures of the same card with, maybe, different results, and then? Which is the good one?). Then, after I press save, I can see the OCR kinda works ( the console prints all the date read) but the info is not pasted at all. Any idea? I know is hard to know what's wrong but I've tried chatgpt and all it does... just doesn't work This is the code from the scanview import SwiftUI import Vision import VisionKit struct ScanCardView: UIViewControllerRepresentable { @Binding var scannedCoordinates: [String: String] var useLettersForColumns: Bool var numberOfColumns: Int var numberOfRows: Int @Environment(.presentationMode) var presentationMode func makeUIViewController(context: Context) -&gt; VNDocumentCameraViewController { let scannerVC = VNDocumentCameraViewController() scannerVC.delegate = context.coordinator return scannerVC } func updateUIViewController(_ uiViewController: VNDocumentCameraViewController, context: Context) {} func makeCoordinator() -&gt; Coordinator { return Coordinator(self) } class Coordinator: NSObject, VNDocumentCameraViewControllerDelegate { let parent: ScanCardView init(_ parent: ScanCardView) { self.parent = parent } func documentCameraViewController(_ controller: VNDocumentCameraViewController, didFinishWith scan: VNDocumentCameraScan) { print("Escaneo completado, procesando imagen...") guard scan.pageCount &gt; 0, let image = scan.imageOfPage(at: 0).cgImage else { print("No se pudo obtener la imagen del escaneo.") controller.dismiss(animated: true, completion: nil) return } recognizeText(from: image) DispatchQueue.main.async { print("Finalizando proceso OCR y cerrando la cámara.") controller.dismiss(animated: true, completion: nil) } } func documentCameraViewControllerDidCancel(_ controller: VNDocumentCameraViewController) { print("Escaneo cancelado por el usuario.") controller.dismiss(animated: true, completion: nil) } func documentCameraViewController(_ controller: VNDocumentCameraViewController, didFailWithError error: Error) { print("Error en el escaneo: \(error.localizedDescription)") controller.dismiss(animated: true, completion: nil) } private func recognizeText(from image: CGImage) { let request = VNRecognizeTextRequest { (request, error) in guard let observations = request.results as? [VNRecognizedTextObservation], error == nil else { print("Error en el reconocimiento de texto: \(String(describing: error?.localizedDescription))") DispatchQueue.main.async { self.parent.presentationMode.wrappedValue.dismiss() } return } let recognizedStrings = observations.compactMap { observation in observation.topCandidates(1).first?.string } print("Texto reconocido: \(recognizedStrings)") let filteredCoordinates = self.filterValidCoordinates(from: recognizedStrings) DispatchQueue.main.async { print("Coordenadas detectadas después de filtrar: \(filteredCoordinates)") self.parent.scannedCoordinates = filteredCoordinates } } request.recognitionLevel = .accurate let handler = VNImageRequestHandler(cgImage: image, options: [:]) DispatchQueue.global(qos: .userInitiated).async { do { try handler.perform([request]) print("OCR completado y datos procesados.") } catch { print("Error al realizar la solicitud de OCR: \(error.localizedDescription)") } } } private func filterValidCoordinates(from strings: [String]) -&gt; [String: String] { var result: [String: String] = [:] print("Texto antes de filtrar: \(strings)") for string in strings { let trimmedString = string.replacingOccurrences(of: " ", with: "") if parent.useLettersForColumns { let pattern = "^[A-J]\\d{1,2}$" // Letras de A-J seguidas de 1 o 2 dígitos if trimmedString.range(of: pattern, options: .regularExpression) != nil { print("Coordenada válida detectada (letras): \(trimmedString)") result[trimmedString] = "Valor" // Asignación de prueba } } else { let pattern = "^[1-9]\\d{0,1}$" // Solo números, de 1 a 99 if trimmedString.range(of: pattern, options: .regularExpression) != nil { print("Coordenada válida detectada (números): \(trimmedString)") result[trimmedString] = "Valor" } } } print("Coordenadas finales después de filtrar: \(result)") return result } } }
0
0
555
Jan ’25
How to drag drop to reorder items in a horizontal scroll view?
Hi, I thought that drag drop reorder should be very easy with SwiftUI, but apparently I was wrong (unless I'm missing something). It seems to me that SwiftUI's drag-drop reorder is only easy for List, which supports .onMove modifier. However, for UI like Grid, a horizontal ScrollView with items in a HStack, I don't see any easy approach to implement this. For example, ScrollView(.horizontal) { HStack { ForEach(items) { ItemView(item) } } } Does anyone know what's the best way to implement drag drop reorder for this horizontal scroll view?
4
0
585
Jan ’25