Posts

Post not yet marked as solved
1 Replies
302 Views
Using SwiftData for a MacOS app I have a working Table but I'd like to add recursion to the rows so instead of stopping at the first child level I can get to grandchildren, etc. Tried creating a separate func that calls itself but cannot get working syntax, possibly because this is happening inside a DisclosureTableRow or I just have bad syntax. Instead of calling TableRow(childAccount) I'd like to be able to call a recursive function which determines if each child is treated as a parent or not until there are no more grandchildren. Each Account class object has .parent: Account, .children: [Account], and .isExpanded:Bool (required by the DisclosureTableRow but not changed here). This is the working non-recursive code: ForEach(theAccounts.sorted(using: sortOrder)) { account in // Make this account bindable so can use .isExpanded directly @Bindable var account = account // Check if the account is not a child of any other account to avoid duplcates, if !theAssetAccounts.contains(where: { $0.children?.contains(account) ?? false }) { // If the account has children, display them in a DisclosureTableRow… if let children = account.children, !children.isEmpty { DisclosureTableRow(account, isExpanded: $account.isExpanded) { ForEach(children) { childAccount in TableRow(childAccount) } } } else { // …or if the account has no children, display it in a simple TableRow TableRow(account) } } } } First the singleton theMotherAccount is at the top level then we iterate over an array of other accounts, theAccounts, showing only those that are not themselves children. Any children are then surfaced as part of another DisclosureTableRow. I thought I could just create a recursive func to return either a DisclosureTableRow or a TableRow but have not been able to find acceptable syntax. This is what I thought ought to work: if let children = account.children, !children.isEmpty { return DisclosureTableRow(account, isExpanded: Bindable(account).isExpanded) { ForEach(children) { child in recursiveAccountRow(account: child) } } } else { return TableRow(account) } }
Posted
by pikes.
Last updated
.
Post not yet marked as solved
1 Replies
152 Views
Using: @Model class Object: Observable, Transferable TableRow(object) .draggable(object) .dropDestination(for: Object.self) { _ in return } (with or without the "return") is the only .dropDestination syntax that compiles for me. Specifying the single return argument as (droppedItems:[Account]) is tolerated Using "return true" or expecting two returned items does not compile. I suspect the single returned item is the dropped items array, seems fair as "location" is not needed when using a TableRow. This is different behavior than all the docs and examples I've seen. My Object is Codable and Transferable. A row can be dragged and a destination row highlights on hover-with-payload, but on drop I get a spinning wheel even though I've not specified any action yet. The action closure is not entered, even a simple print() statement is not reached. I'd appreciate any thoughts on what might be the problem here. Debugger tips welcome, too. swift-driver version: 1.90.11.1 Apple Swift version 5.10 (swiftlang-5.10.0.13 clang-1500.3.9.4) Target: arm64-apple-macosx14.0
Posted
by pikes.
Last updated
.
Post not yet marked as solved
0 Replies
228 Views
Using SwiftData I have one relatively short list of @Model class objects that are referenced in several views. I thought it would be handy to query once and share via the environment but my Table in other views does not update when data changes as it does when I repeat the Query in each view. Is this a bad idea or perhaps I implemented it improperly? @Observable class AllAccounts: ObservableObject { var accounts: [Account] = [] } struct ContentView: View { @Environment(\.modelContext) private var modelContext // an instance of the AllAccounts class, will save Query results to all.accounts @StateObject var all = AllAccounts() // one query for all accounts once in app, store in the environment` @Query private var allAccounts: [Account] .onAppear { all.accounts = allAccounts } .environment(all)
Posted
by pikes.
Last updated
.
Post not yet marked as solved
1 Replies
463 Views
Context: Importing JSON to have some data during development of SwiftData MacOS app. One object is repeated several times in the JSON and each copy is in the decoded data and does get inserted into the context and can be saved to the container, but then there are multiple copies of the same object with the same identifier in the database. When I qualify If the troublesome object's class with an @Attribute(.unique) identifier then the app crashes on .save. I was expecting a silent upsert. In this case there are three @Model classes. The model has a primary object with children objects and each child may have a third object type as a property and that third object may have a distinct third object listed as one of its own properties. It is this third object which appears several times in the file since it can be associated with many children. The insert code only specifies the primary object as I was expecting nested insertion of the children and the third object. Does this need to be handled differently? I'd like to only insert the first instance of the third object and keep the relationship intact. Should upsert work on .insert and might there be a technical problem?
Posted
by pikes.
Last updated
.