Post

Replies

Boosts

Views

Activity

Reply to How to resolve SwiftUI.DynamicProperty on MainActor compiler warning on 6.0?
I had the same error and fixed it by adding an extra @preconcurrency to the protocol conformance, e.g. ... : @preconcurrency DynamicProperty { Mine actually looks like this though: @MainActor @propertyWrapper @preconcurrency public struct DynamicQuery<ResultType>: @preconcurrency DynamicProperty where ResultType: PersistentModel { I noticed that @FetchRequest has did it on a protocol extension, maybe that was their trick: extension FetchRequest : DynamicProperty { @MainActor @preconcurrency public mutating func update() } I wonder why their update func is mutating, that must be a mistake surely. The behaviour of @FetchRequest is rather strange, e.g. when re-init it loses any dynamically configured properties. I have had to implement my own to fix it, it's here: https://github.com/malhal/SwiftUICoreDataFetchRequestRedesign
1w
Reply to Binding with ForEach or List doesn't work anymore when using @Observable macro
Binding is for structs since you have an object it is just: struct LibraryView: View { @Environment(Library.self) private var library var body: some View { List(library.books) { book in BookView(book: book) } } } Note there are 2 design flaws with your code: You shouldn't name your views with model types. Only pass the data the view needs not the whole object, e.g. it could be something like this: var body: some View { List(library.books) { book in BigView(topText: book.title, bottomText: "\(book.releaseDate, format: .date)") } }
Oct ’24
Reply to Duplicate bar buttons appear when .toolbar is applied to a Group View
I'm beginning to think this is a bug because when adding ids the unexpected behaviour causes a crash: Group { Text("1") Text("2") Text("3") } .toolbar(id: "myToolbar") { ToolbarItem(id: "myItem", placement: .primaryAction) { Button("Hi") { } } } Crash log *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'index out of bounds for arranged subview: index = 3 expected to be less than or equal to 2' *** First throw call stack: ( 0 CoreFoundation 0x00000001804b70ec __exceptionPreprocess + 172 1 libobjc.A.dylib 0x000000018008ede8 objc_exception_throw + 72 2 CoreFoundation 0x00000001804b6ffc -[NSException initWithCoder:] + 0 3 UIKitCore 0x0000000185f1da54 -[UIStackView insertArrangedSubview:atIndex:] + 144 4 UIKitCore 0x0000000184fa94c4 -[_UIButtonBar _layoutBar] + 2444 5 UIKitCore 0x0000000184fabb14 __42-[_UIButtonBarStackView updateConstraints]_block_invoke + 40 6 UIKitCore 0x000000018600b380 +[UIView(Animation) performWithoutAnimation:] + 68 7 UIKitCore 0x0000000184fabac0 -[_UIButtonBarStackView updateConstraints] + 84 8 UIKitCore 0x0000000185f3508c -[UIView(AdditionalLayoutSupport) _sendUpdateConstraintsIfNecessaryForSecondPass:] + 316 9 UIKitCore 0x0000000185f354e0 -[UIView(AdditionalLayoutSupport) _updateConstraintsIfNeededCollectingViews:forSecondPass:] + 760 10 UIKitCore 0x0000000185f353fc -[UIView(AdditionalLayoutSupport) _updateConstraintsIfNeededCollectingViews:forSecondPass:] + 532 11 CoreAutoLayout 0x00000001daa63668 -[NSISEngine withBehaviors:performModifications:] + 76 12 UIKitCore 0x0000000185f35aec __100-[UIView(AdditionalLayoutSupport) _updateConstraintsIfNeededWithViewForVariableChangeNotifications:]_block_invoke + 92 13 UIKitCore 0x0000000185f34728 -[UIView(AdditionalLayoutSupport) _withUnsatisfiableConstraintsLoggingSuspendedIfEngineDelegateExists:] + 104 14 UIKitCore 0x0000000185f35778 -[UIView(AdditionalLayoutSupport) _updateConstraintsIfNeededWithViewForVariableChangeNotifications:] + 144 15 UIKitCore 0x000000018501b2a4 -[_UINavigationBarContentViewLayout layoutSubviews] + 156 16 UIKitCore 0x000000018500fb48 -[_UINavigationBarContentView layoutSubviews] + 148 17 UIKitCore 0x0000000186016438 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 2404 18 QuartzCore 0x000000018b059eb0 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 432 19 UIKitCore 0x000000018600583c -[UIView(Hierarchy) layoutBelowIfNeeded] + 308 20 UIKitCore 0x0000000185284068 -[UINavigationController _positionNavigationBarHidden:edge:initialOffset:] + 584 21 UIKitCore 0x000000018528423c -[UINavigationController _positionNavigationBarHidden:edge:] + 292 22 UIKitCore 0x0000000185293d7c -[UINavigationController __viewWillLayoutSubviews] + 128 23 UIKitCore 0x000000018527bb00 -[UILayoutContainerView layoutSubviews] + 168 24 UIKitCore 0x0000000186016438 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 2404 25 QuartzCore 0x000000018b059eb0 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 432 26 QuartzCore 0x000000018b064c34 _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 124 27 QuartzCore 0x000000018af99c58 _ZN2CA7Context18commit_transactionEPNS_11TransactionEdPd + 464 28 QuartzCore 0x000000018afc8468 _ZN2CA11Transaction6commitEv + 652 29 UIKitCore 0x0000000185ab8260 __34-[UIApplication _firstCommitBlock]_block_invoke_2 + 32 30 CoreFoundation 0x000000018041b0ec __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 20 31 CoreFoundation 0x000000018041a824 __CFRunLoopDoBlocks + 352 32 CoreFoundation 0x00000001804150c8 __CFRunLoopRun + 812 33 CoreFoundation 0x0000000180414960 CFRunLoopRunSpecific + 536 34 GraphicsServices 0x000000019016fb10 GSEventRunModal + 160 35 UIKitCore 0x0000000185a9f650 -[UIApplication _run] + 796 36 UIKitCore 0x0000000185aa3848 UIApplicationMain + 124 37 SwiftUI 0x00000001d1cedae4 $s7SwiftUI17KitRendererCommon33_ACC2C5639A7D76F611E170E831FCA491LLys5NeverOyXlXpFAESpySpys4Int8VGSgGXEfU_ + 164 38 SwiftUI 0x00000001d1ced80c $s7SwiftUI6runAppys5NeverOxAA0D0RzlF + 84 39 SwiftUI 0x00000001d1a2fe1c $s7SwiftUI3AppPAAE4mainyyFZ + 148 40 Test.debug.dylib 0x0000000102f20fac $s4Test0A3AppV5$mainyyFZ + 40 41 Test.debug.dylib 0x0000000102f21294 __debug_main_executable_dylib_entry_point + 12 42 dyld 0x0000000100259410 start_sim + 20 43 ??? 0x0000000100426154 0x0 + 4299317588 44 ??? 0xe735800000000000 0x0 + 16660363134015373312 ) libc++abi: terminating due to uncaught exception of type NSException Submitted feedback on this crash and linked to this forum. FB15011577
Sep ’24
Reply to SwiftUI and SwiftData @Query
You actually shouldn't be passing whole objects into child Views and instead only pass the params of the object that the View needs to do its job. If it needs write access to a property then you can convert the object to @Bindable and then pass in a binding to the property. This is one of the basic design principles of SwiftUI, "only pass in the data the View needs to do its job" [Data Essentials in SwiftUI WWDC 2020] By the way, unfortunately you can't currently update @Query with a parameter passed in from a parent View because it is missing the ability to change the filter, e.g. it's missing something like: let somethingPassedIn: String let query = Query<Item, [Item]> var items: [Item] { query.filter = // change filter based on somethingPassedIn but impossible because query is missing the filter property return query.wrappedValue } I know some developers try to re-init the @Query with a param from a parent but that is not the correct approach because these property wrappers are designed to be sources of truth and there is no guarantee they will update correctly if the init params change. As a work around you could fallback to Core Data's @FetchRequest which does have the ability to dynamically change the query, e.g. let fetchRequest = FetchRequest<Item>(sortDescriptors[]) var items: FetchedResults<Item> { fetchRequest.predicate = // dynamically update it is possible return fetchRequest.wrappedValue }
Aug ’24
Reply to SwiftData query filter on an @State var
We currently can't change the filter/predicate of the Query but hopefully in the future we would be able to do something like: @State private var selectedMonth: String = "" @State private var selectedYear: String = "" let query = Query<Transaction, [Transaction]>() var transactions: [Transaction] { query.descriptor.predicate = #Predicate<Transaction> { transaction in transaction.date.monthString == selectedMonth && transaction.date.yearString == selectedYear } query.sort = \Transaction.date return query.wrappedValue } This pattern, of changing the predicate lazily when the results are requested makes more sense to me than trying to re-init the property wrapper with different params. Currently descriptor is a private property of Query for some reason. Feedbacks FB12367164, FB12292784
Aug ’24
Reply to Pass @Query filter predicate from parent view in SwiftData
Hopefully we will be able to replace the predicate in a future version of SwiftData, here is how I would like it to work: struct RemindersList: View { let todoList: TodoList let query = Query<Reminder, [Reminder]> var reminders: [Reminder] { let todoListID = todoList.persistentModelID let predicate = #Predicate<Reminder> { reminder in reminder.todoList?.persistentModelID == todoListID } query.predicate = predicate return query.wrappedValue } var body: some View { List(reminders) { ... } } } Then I would simply be able to do RemindersList(todoList: todoList) I submitted this as feedback FB12367164
Aug ’24
Reply to Create @State vars dynamically
you need to learn @Binding for that. You would create the data in the model that you want to show in the text fields and then bind the fields to that data. There is no @State in this case. Sometimes the UI controls have slightly different types to your model property types in which case you can use computed bindings to do the transformation. The same way you would use computed vars to transform readonly model or state data when passing it down to child Views.
Aug ’24
Reply to SwiftUI State not reliable updating
onAppear is too late to set state. You should have the state configured first, then body is designed to create all the Views depending on the state. This is a crucial part of SwiftUI's design where "views are a function of state". onAppear is designed for external actions unrelated to state. Since you are using SwiftData it's not @State it is @Query to fetch the models and then bind the Views directly to them. If the types are different you can use computed bindings to convert.
Aug ’24
Reply to Regression in Concurrent Task Execution on macOS 15 Beta: Seeking Clarification
To use async/await from SwiftUI it is .task not Task and to get a background thread for a func declared inside the View struct (which is annotated MainActor) use nonisolated func, e.g. Button(isRunning ? "Stop" : "Run Concurrent Tasks") { results.removeAll() isRunning.toggle() } .task(id: isRunning) { // main thread if isRunning { async let task1 = countingTask(name: "Task 1", target: 1000) } } ... } // without nonisolated it would be main actor and thus always on main thread func nonisolated countingTask(name: String, target: Int) async -> String { // background thread If you moved the func to a custom struct then it wouldn't need nonisolated. If that controller struct was an EnvironmentKey then it could be mocked for Previews.
Aug ’24