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

SwiftUI Documentation

Post

Replies

Boosts

Views

Activity

SwiftUI and SwiftData projects, textField gets focus, freezes, and takes 7000 milliseconds to focus
macOS 14.5、Xcode 15.4、iPhone OS 18.0 beta Open Xcode and create a new project. Select swiftUI for Interface, Swift for Language, and Swiftdata for Storage. After creating the project, open the ContentView.swift file,write the code @State var username: String = "" TextField("info", text: $username) .textFieldStyle(.roundedBorder) .disableAutocorrection(true) .textInputAutocapitalization(.never) Run the project on iPhone. textField gets focus, freezes, and takes 7000 milliseconds to focus
0
0
22
8h
How to integrate Pencil into my application? I have encountered a problem.
我是个新手。我是UIKit的新手。我真的不知道该怎么办。我的问题是,我希望用铅笔绘制的图纸在PencilCreate中显示,但我不知道如何控制它们的交付。我需要单击HB才能跳转到铅笔视图界面。然后,铅笔视图界面中绘制的内容可以显示在PencilCreate的.border中。 导入SwiftUI 导入 PencilKit struct GrPencil:查看{ var body:一些视图{ 导航堆栈{ 画布视图() } } } struct CanvasView:UIViewRepresentable { @State var canvasView:PKCanvasView = PKCanvasView() @State var toolPicker = PKToolPicker() func makeUIView(上下文:上下文)-> PKCanvasView { canvasView.drawingPolicy = .anyInput canvasView.becomeFirstResponder() toolPicker.setVisible(true,forFirstResponder:canvasView) toolPicker.addObserver(canvasView) 返回canvasView } func updateUIView(_ uiView: PKCanvasView, context: Context) { } } #预览 { GrPencil() } 导入SwiftUI 导入 PencilKit struct PencilCreate:查看{ @State var drawing = PKDrawing() var body:一些视图{ VStack { VStack { 图像(uiImage:drawing.image(来自:drawing.bounds,比例:1)) .resizable() .框架(宽度:200,高度:120) .border(颜色.黑色) 按钮{ }标签:{ 文本(“HB”) } } } } } #预览 { PencilCreate() }
0
0
18
9h
Is it Possible to save AttributedString with image to RTF doc?
Hello, I am trying to implement an RTF document export feature on a small app. But after days of trying and failing with dozens of approaches I’m beginning to wonder if it is even possible to create an .rtf file with embedded text and images in Swift/SwiftUI. I’ve tried many variations of (A) building the text and image content with HTML, converting it to AttributedString, then exporting to RTF, and (B) building the text and image content directly with AttributedString attributes and attachments for the image — and in both cases, the images are not saved in the RTF file. I am able to create a preview of the AttributedString with formatted text and image, and able to create an RTF file with formatted text that opens with TextEdit, Pages and Word without issue; but cannot get the image to appear in the saved RTF file. I’m hoping someone here can shed some light on if this is possible and if yes, how to save the combined text and image data to an RTF file. Here is the latest variation of the code I’m using — any ideas/suggestions are appreciated 🙏🏽: import SwiftUI struct ContentView: View { @State private var showExportSheet = false @State private var rtfData: Data? @State private var isLoading = false @State private var previewAttributedString: NSAttributedString? var body: some View { VStack { Button("Export RTF with Image") { isLoading = true createRTFWithEmbeddedImage() } .disabled(isLoading) if isLoading { ProgressView() } if let previewAttributedString = previewAttributedString { VStack { Text("Preview:") .font(.headline) TextView(attributedString: previewAttributedString) .frame(minWidth: 0, maxWidth: .infinity, minHeight: 200, maxHeight: .infinity) .background(Color.gray.opacity(0.1)) } .padding() } } .sheet(isPresented: $showExportSheet) { DocumentPicker(rtfData: $rtfData) } } func createRTFWithEmbeddedImage() { let text = "This is a sample RTF document with an embedded image:" // Load the image (star.fill as a fallback) guard let image = UIImage(systemName: "star.fill") else { print("Failed to load image") isLoading = false return } // Resize the image to 100x100 pixels let resizedImage = resizeImage(image: image, targetSize: CGSize(width: 100, height: 100)) // Convert image to NSTextAttachment let attachment = NSTextAttachment() attachment.image = resizedImage // Set bounds for the image attachment.bounds = CGRect(x: 0, y: 0, width: 100, height: 100) // Create attributed string with the attachment let attributedString = NSMutableAttributedString(string: text) let attachmentString = NSAttributedString(attachment: attachment) attributedString.append(attachmentString) // Add red border around the image attributedString.addAttribute(.strokeColor, value: UIColor.red, range: NSRange(location: attributedString.length - attachmentString.length, length: attachmentString.length)) attributedString.addAttribute(.strokeWidth, value: -2.0, range: NSRange(location: attributedString.length - attachmentString.length, length: attachmentString.length)) // Set previewAttributedString for preview self.previewAttributedString = attributedString // Convert attributed string to RTF data guard let rtfData = try? attributedString.data(from: NSRange(location: 0, length: attributedString.length), documentAttributes: [.documentType: NSAttributedString.DocumentType.rtf]) else { print("Failed to create RTF data") isLoading = false return } self.rtfData = rtfData isLoading = false showExportSheet = true // Debug: Save RTF to a file in the Documents directory saveRTFToDocuments(rtfData) } func resizeImage(image: UIImage, targetSize: CGSize) -> UIImage { let size = image.size let widthRatio = targetSize.width / size.width let heightRatio = targetSize.height / size.height let newSize: CGSize if widthRatio > heightRatio { newSize = CGSize(width: size.width * heightRatio, height: size.height * heightRatio) } else { newSize = CGSize(width: size.width * widthRatio, height: size.height * widthRatio) } let rect = CGRect(origin: .zero, size: newSize) UIGraphicsBeginImageContextWithOptions(newSize, false, 1.0) image.draw(in: rect) let newImage = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return newImage ?? UIImage() } func saveRTFToDocuments(_ data: Data) { let fileManager = FileManager.default guard let documentsDirectory = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first else { print("Unable to access Documents directory") return } let fileURL = documentsDirectory.appendingPathComponent("debug_output.rtf") do { try data.write(to: fileURL) print("Debug RTF file saved to: \(fileURL.path)") } catch { print("Error saving debug RTF file: \(error)") } } } struct DocumentPicker: UIViewControllerRepresentable { @Binding var rtfData: Data? func makeUIViewController(context: Context) -> UIDocumentPickerViewController { let tempURL = FileManager.default.temporaryDirectory.appendingPathComponent("document_with_image.rtf") do { try rtfData?.write(to: tempURL) } catch { print("Error writing RTF file: \(error)") } let picker = UIDocumentPickerViewController(forExporting: [tempURL], asCopy: true) return picker } func updateUIViewController(_ uiViewController: UIDocumentPickerViewController, context: Context) {} } struct TextView: UIViewRepresentable { let attributedString: NSAttributedString func makeUIView(context: Context) -> UITextView { let textView = UITextView() textView.isEditable = false textView.attributedText = attributedString return textView } func updateUIView(_ uiView: UITextView, context: Context) { uiView.attributedText = attributedString } } Thank in advance!
0
0
43
11h
Question about preview using code in SwiftUI
Hello, I have a view which have a few controls and preview macro. I replaced preview macro with following code: struct ContentView_Preview:PreviewProvider{ static var previews: some View{ ContentView() } } after replacement, preview doesn't work properly. plz tell me how can i fix it. thanks, c00012
0
0
52
14h
SwiftUI Previews not working with Firebase in Xcode 16.0 beta
The SwiftUI previews have been working fine in Xcode 16.0 beta, but ever since I added Firebase into my app, I've been getting error with previews. CrashReportError: IshaanCord crashed IshaanCord crashed. Check ~/Library/Logs/DiagnosticReports for crash logs from your application. Process: IshaanCord[5651] Date/Time: 2024-07-04 19:29:51 +0000 Log File: <none> "Cannot preview in this file" Does anyone know how to fix this? Thank you.
0
0
63
20h
Vertical ScrollView Height and Paging Offset Issues in SwiftUI
Hi everyone, I'm currently working on an iOS app using SwiftUI, and I'm facing an issue with a vertical ScrollView. My goal is to have the ScrollView take up all the safe area space plus the top inset (with the bottom inset being an ultra-thin material) and enable paging behavior. However, I'm encountering two problems: The initial height of the ScrollView is too high (dragging the view (even without changing the page) adjusts the size). The paging offset of the ScrollView is incorrect (page views are not aligned). I’ve tried many things and combinations in desperation, including padding, safeAreaPadding, contentMargins, frame, fixedSize, containerRelativeFrame with callback, custom layout, and others, but nothing seems to work. If by any chance someone can help me find a solution, I’d greatly appreciate it. I suspect there are issues with the height defined by the ScrollView when some safe areas are ignored, leading to strange behavior when trying to set the height. It's challenging to explain everything in a simple post, so if someone from the SwiftUI team could look into this potential bug, that would be incredibly helpful. Thank you! import SwiftUI struct ScrollViewIssue: View { @State private var items: [(String, Color)] = [ ("One", .blue), ("Two", .green), ("Three", .red), ("Four", .purple) ] var body: some View { ZStack(alignment: .top) { ScrollView(.vertical) { VStack(spacing: 0) { ForEach(items, id: \.0) { item in ItemView(text: item.0, color: item.1) .containerRelativeFrame([.horizontal, .vertical]) } } } .printViewSize(id: "ScrollView") .scrollTargetBehavior(.paging) .ignoresSafeArea(edges: .top) VStack { Text("Title") .foregroundStyle(Color.white) .padding() .frame(maxWidth: .infinity) .background(Color.black.opacity(0.2)) Spacer() } } .printViewSize(id: "ZStack") .safeAreaInset(edge: .bottom) { Rectangle() .frame(width: .infinity, height: 0) .overlay(.ultraThinMaterial) } } } struct ItemView: View { let text: String let color: Color var body: some View { ZStack { RoundedRectangle(cornerRadius: 20) .fill(color.opacity(0.2)) .overlay( color, in: RoundedRectangle(cornerRadius: 20) .inset(by: 10 / 2) .stroke(lineWidth: 10) ) Text(text) } .printViewSize(id: "item") } } struct ViewSizeKey: PreferenceKey { static var defaultValue = CGSize() static func reduce(value: inout CGSize, nextValue: () -> CGSize) { value = nextValue() } } extension View { func printViewSize(id: String) -> some View { background( GeometryReader { proxy in Color.clear .preference(key: ViewSizeKey.self, value: proxy.size) } .onPreferenceChange(ViewSizeKey.self) { value in print("\(id) size:\(value)") } ) } } #Preview { ScrollViewIssue() }
1
0
47
1d
NavigationStack with NavigationPath triggers multiple init/deinit of views in stack
Hi all 👋 I've stumbled upon what I think is a bug in SwiftUI, but there might be an explanation for it, which I cannot to figure out. So here's the "bug". Perhaps any of you know it. In short I found out that .navigationDestination(for: ...) runs multiple times when you abstract the logic away from the scope of the closure, into a function that should return the desired view from the type of destination. But if you keep the logic inside the scope of the closure it only runs once per destination. The longer explanation I've setup a small example of a setup, which I'm planning on building an entire app on. Basically it's MVVVM with a coordinator pattern. I've ditched the coordinator in this example to minimize code, but the router is present and is key to how the app should work: navigation happens from a central place at the root of the app. You should be able to copy all the code into a single file and run the app, to see what happens. It's a simple app with a rootview that can navigate to either "Cookies" or "Milk". You can set an amount (to have some sort of state, that you can test is still present, when navigating back to the view) + navigate on to another view. The bug in question happens in the RootView: .navigationDestination(for: Destination.self) { destination in let _ = print("||| Destination: \(destination.rawValue)") // Method #1 // anyViewFor(destination: destination) // Method #2 // itemViewFor(destination: destination) // Method #3 // cookieViewFor(destination: destination) // Method #4 switch destination { case .cookie: let vm = CookieViewModel() CookieView(vm: vm) case .milk: let vm = MilkViewModel() MilkView(vm: vm) } } If you comment out Method 4 and comment in any of Method 1, 2, 3 you will see the issue in the console. Say you navigate from RootView -> CookieView (Set 2 cookies) -> MilkView (Set 1 glass of milk) -> CookieView, and then navigate back to RootView. Method 4 produces the following prints: ||| Router: add to navPath: 1 ||| Destination: Cookie 🍪 ||| Init ☀️: CookieViewModel, id: 960, num: 0 ||| Router: add to navPath: 2 ||| Destination: Milk 🥛 ||| Init ☀️: MilkViewModel, id: 254, num: 0 ||| Router: add to navPath: 3 ||| Destination: Cookie 🍪 ||| Init ☀️: CookieViewModel, id: 348, num: 0 ||| Router: remove from navPath: 2 ||| Deinit 🔥: CookieViewModel, id: 348, num: 0 ||| Router: remove from navPath: 1 ||| Deinit 🔥: MilkViewModel, id: 254, num: 1 ||| Router: remove from navPath: 0 ||| Deinit 🔥: CookieViewModel, id: 960, num: 2 This makes sense. The desired Views+ViewModels (we only have prints from VMs) are init'ed and deinit'ed. Method 1, 2, 3 produces the following prints: ||| Router: add to navPath: 1 ||| Destination: Cookie 🍪 ||| Init ☀️: CookieViewModel, id: 893, num: 0 ||| Router: add to navPath: 2 ||| Destination: Milk 🥛 ||| Init ☀️: MilkViewModel, id: 747, num: 0 ||| Destination: Cookie 🍪 ||| Init ☀️: CookieViewModel, id: 384, num: 0 ||| Router: add to navPath: 3 ||| Destination: Cookie 🍪 ||| Init ☀️: CookieViewModel, id: 578, num: 0 ||| Destination: Milk 🥛 ||| Init ☀️: MilkViewModel, id: 409, num: 0 ||| Destination: Cookie 🍪 ||| Init ☀️: CookieViewModel, id: 468, num: 0 ||| Deinit 🔥: CookieViewModel, id: 384, num: 0 ||| Router: remove from navPath: 2 ||| Destination: Cookie 🍪 ||| Init ☀️: CookieViewModel, id: 859, num: 0 ||| Deinit 🔥: CookieViewModel, id: 468, num: 0 ||| Destination: Milk 🥛 ||| Init ☀️: MilkViewModel, id: 250, num: 0 ||| Deinit 🔥: MilkViewModel, id: 409, num: 0 ||| Deinit 🔥: CookieViewModel, id: 578, num: 0 ||| Router: remove from navPath: 1 ||| Destination: Cookie 🍪 ||| Init ☀️: CookieViewModel, id: 211, num: 0 ||| Deinit 🔥: CookieViewModel, id: 859, num: 0 ||| Deinit 🔥: MilkViewModel, id: 250, num: 0 ||| Deinit 🔥: MilkViewModel, id: 747, num: 1 ||| Router: remove from navPath: 0 ||| Deinit 🔥: CookieViewModel, id: 211, num: 0 ||| Deinit 🔥: CookieViewModel, id: 893, num: 2 This is where it gets weird. When it's a function returning the desired view for the given destination to .navigationDestination(for: ...) then it appears to be running n * number of items in the NavigationPath-object. You can see on the num: x in the deinit-prints, that instances are inited and deinted that we're never in touch with. Do any of you have a qualified guess why this is happening? To me it seems like a bug. I'll provide the code for mig example in a comment...
1
0
49
1d
swiftUI animation And ID attribute
struct ContentIDView: View { @State var testID = UUID() @State var b = 0 var body: some View { VStack { Image("video_pic_diy_000") .resizable() .scaledToFit() .contentTransition(.interpolate) .id(testID) .offset(x:CGFloat(b>0 ? 100*b:0)) .animation(.easeInOut(duration: 0.01).delay(0.2), value: b) .onAppear(perform: { print("\(testID)") }) Text("\(testID)") Spacer() Button("Move") { withAnimation(Animation.easeInOut(duration: 0.2)) { b = b+1 testID = UUID() } } } } } In the above code, there is an image and a button, and each time the button is clicked, the image moves 100* the distance of the number of clicks in the x direction from 0, but now each time it moves 100 from where the last move stopped instead of 0. What causes this? In addition, I set the id for Image. When the id changes every time the button is clicked, shouldn't the initial state be restored? Since it is the initial state, why didn't it move from 0?
0
0
26
1d
SwiftUI, numeric keypad, and missing keyboard toolbar
Have a SwiftUI TextField with .numberPad keypad. Want to allow the user to make their changes, then hit 'Done' or 'Cancel' to dismiss the keyboard (there are other choices on the page) before hitting 'Submit'. The view containing the field is brought up as a modal, using .FullScreenCover. Here's the code snippet: @State var currentBid: Float = 0 @FocusState var isInputActive: Bool ... TextField("Enter Amount", text: Binding( get: { String(Int(currentBid)) }, set: { currentBid = Float(Int($0) ?? 0) }) ).keyboardType(.numberPad) .focused($isInputActive) .toolbar(content: { ToolbarItemGroup(placement: .keyboard, content: { Button("Cancel") { print("CANCELLED") isInputActive = false } Spacer() Button("Done") { print("DONE") isInputActive = false } }) }) When you tap the text field, the numeric keyboard comes up, but the button bar does not show. This is on iOS 17.6. tested on-device. The alternative is to use a regular alphanumeric keyboard with an "ENTER" button. But the field is to enter a number and I have to either filter the value or discard it in case they enter bad data. I checked online, and others indicated wrapping the whole View inside a NavigationStack might be needed. Tried it and it didn't work. Any suggestions? Thanks!
0
0
53
1d
Issue with observing SwiftData model and UndoManager
I have created a minimum example to demonstrate an issue with observing SwiftData model and UndoManager. This project includes a simple NavigationSplitView, an Item SwiftData model that is being persisted and an enabled UndoManager. Problem: The SwiftData model Item can be observed as expected. Changing the date in the DetailView works as expected and all related views (ListElementView + DetailView) are updated as expected. When pressing ⌘+Z to undo with the enabled UndoManager, deletions or inserts in the sidebar are visible immediately (and properly observed by ContentView). However, when changing the timestamp and pressing ⌘+Z to undo that change, it is not properly observed and immediately updated in the related views (ListElementView + DetailView). Further comments: Undo operation to the model value changes (here: timestamp) are visible in the DetailView when changing sidebar selections Undo operation to the model value changes (here: timestamp) are visible in the ListElementView when restarting the app Undo operation to the model value changes (here: timestamp) are are properly observed and immediately visible in the sidebar, when ommiting the ListElementView (no view encapsulation) Relevant code base: struct ContentView: View { @Environment(\.modelContext) private var modelContext @Query private var items: [Item] @State private var selectedItems: Set<Item> = [] var body: some View { NavigationSplitView { List(selection: $selectedItems) { ForEach(items) { item in ListElementView(item: item) .tag(item) } .onDelete(perform: deleteItems) } .navigationSplitViewColumnWidth(min: 180, ideal: 200) .toolbar { ToolbarItem { Button(action: addItem) { Label("Add Item", systemImage: "plus") } } } } detail: { if let item = selectedItems.first { DetailView(item: item) } else { Text("Select an item") } } .onDeleteCommand { deleteSelectedItems() } } private func addItem() { withAnimation { let newItem = Item(timestamp: Date()) modelContext.insert(newItem) } } private func deleteItems(offsets: IndexSet) { withAnimation { for index in offsets { modelContext.delete(items[index]) } } } private func deleteSelectedItems() { for selectedItem in selectedItems { modelContext.delete(selectedItem) selectedItems.remove(selectedItem) } } } struct ListElementView: View { @Bindable var item: Item var body: some View { Text("Item at \(item.timestamp, format: Date.FormatStyle(date: .numeric, time: .standard))") } } struct DetailView: View { @Bindable var item: Item var body: some View { Text(item.timestamp, format: Date.FormatStyle(date: .numeric, time: .standard)) DatePicker(selection: $item.timestamp, label: { Text("Change Date:") }) } } @Model final class Item { var timestamp: Date init(timestamp: Date) { self.timestamp = timestamp } } It seems that the UndoManager does not trigger a redraw of the ContentView through the items query? Is this a bug or a feature?
0
0
46
1d
XC Test - Xamarin- Mobile Automation - Tiles missing on list view
Unable to see the first element in a Xamarin forms List view while running the automated UI iOS tests using xctest Element with property in Xamarin forms "ListViewCachingStrategy.RetainElement" , the first element is missing from the list view while running the tests in iOS . Inbetween the tests if we remove the WDA and tried the same scenario, it works as expected. The first element was displayed when working with xamarin forms (v4.7.0.1351) and it is observed with only the current version. Manually trying the same scenario does not have any issues , Elements are displayed as expected, issue is observed only through automation
2
0
60
1d
NavigationDestination, NavigationLink with List and ForEach Does Not Work
Dear community, I am a new developer and I am building a view (called Root) that has a list of rows where clicking each row navigates to a completely different view. I have a CaseIteratable enum and I list each enum type using ForEach and each enum case navigates to a different view using NavigationLink and NavigationDestination. But the problem is that clicking any of the rows for the first time navigates correctly to the corresponding view. But when I go back to the root view and chose another row, it navigates me to a blank view for less than a sec and automatically navigates back to the root view. Below is the code for reference. I would really appreciate some help and advice here. Thank you very much! struct RootViewNavigationStack: View { @AppStorage("items") private var items = Item.allCases @State private var enableMove = false @State private var rootStackPath: NavigationPath = .init() var body: some View { NavigationStack(path: $rootStackPath) { VStack { List { ForEach(items) { item in HStack { NavigationLink(value: item) { ListCell( icon: item.icon, title: item.title) } .disabled(enableMove) if enableMove { withAnimation { Image(systemName: "line.3.horizontal") .foregroundStyle(.secondary) } } } } .onMove(perform: enableMove == true ? moveItems : nil) } } .toolbar { ToolbarItem(placement: .navigationBarTrailing) { Button { enableMove.toggle() } label: { if enableMove { Text("Done") .bold() } else { Text("Edit") } } } } .navigationDestination(for: Item.self) { item in item.destinationView } .navigationTitle("Root") } } } and this is the Item enum for more info Just kindly ignore the var iconName since it doesnt represent any actual SF Symbol name enum Item: Identifiable, Codable, Hashable, CaseIterable { case view1 case view2 case view3 case view4 case view5 var id: Item { self } } extension Item { var title: String { switch self { case .view1: "View1" case .view2: "View2" case .view3: "View3" case .view4: "View4" case .view5: "View5" } } var iconName: String { switch self { case .view1: "View1" case .view2: "View2" case .view3: "View3" case .view4: "View4" case .view5: "View5" } } var icon: Image { Image(systemName: self.iconName) } @ViewBuilder var destinationView: some View { switch self { case .view1: CarView() case .view2: HouseView() case .view3: MusicView() case .view4: ShoesView() case .view5: BooksView() } } } Once again, would really appreciate someone to help and many thanks 🙏!
2
0
71
1d
SwiftUI.List.scrollDismissesKeyboard(.immediately) causes scroll glitch on List
When the scrollDismissesKeyboard(.immediately) is used on a SwiftUI.List, the scroll is very glitchy when keyboard is open both on simulator and on device. Glitch is visible when content height is smaller than screen height. A sample code to reproduce the issue: struct ContentView: View { @State private var searchText = "" var body: some View { NavigationStack { List { ForEach(0..<1) { index in Rectangle() .fill(Color.blue) .frame(height: 100) .cornerRadius(10) .padding(.vertical, 5) .padding(.horizontal) } } .searchable(text: $searchText) .scrollDismissesKeyboard(.immediately) } } } Steps to Reproduce: Run the code above. Tap on the search bar so the keyboard appears. Scroll the list down. Glitch should be visible. Along with the glitch, there are many warnings being thrown when I interact with the search bar: -[RTIInputSystemClient remoteTextInputSessionWithID:performInputOperation:] perform input operation requires a valid sessionID. inputModality = Keyboard, inputOperation = <null selector>, customInfoType = UIEmojiSearchOperations -[UIApplication getKeyboardDevicePropertiesForSenderID:shouldUpdate:usingSyntheticEvent:], failed to fetch device property for senderID (***) use primary keyboard info instead. This API seems very unstable. Is this a known issue? If so, are there plans on fixing it?
0
0
69
2d
Spatial Event
Hello. I am building an AVP app with a C++ engine in Metal. From Swift, I get a spatial event from the layerRenderer, and I want to send the event data to my engine. But I have a problem: I need the event ID value (SpatialEventCollection.Event.ID), which I can see in the debugger (it has a value of 1 or 2 depending on the hand), but I need that value as an Int to pass it to the engine. Any ideas on how to do this? Thanks.
0
0
51
2d
SwiftUI State not reliable updating
Hello, I have a SwiftUI view with the following state variable: @State private var startDate: Date = Date() @State private var endDate: Date = Date() @State private var client: Client? = nil @State private var project: Project? = nil @State private var service: Service? = nil @State private var billable: Bool = false Client, Project, and Service are all SwiftData models. I have some view content that binds to these values, including Pickers for the client/project/service and a DatePicker for the Dates. I have an onAppear listener: .onAppear { switch state.mode { case .editing(let tt): Task { await MainActor.run { startDate = tt.startDate endDate = tt.endDate client = tt.client project = tt.project service = tt.service billable = tt.billable } } default: return } } This works as expected. However, if I remove the Task & MainActor.run, the values do not fully update. The DatePickers show the current date, the Pickers show a new value but tapping on them shows a nil default value. What is also extremely strange is that if tt.billable is true, then the view does update as expected. I am using Xcode 15.4 on iOS simulator 17.5. Any help would be appreciated.
0
0
84
2d