Good day, please tell me, is it possible to somehow change the behavior of Computed Property?
What is happening here: we show a list of transactions that are dynamically grouped by dates
import SwiftUI
import SwiftData
struct TransactionsList: View {
@Query(sort: [
SortDescriptor(\Transaction.dateTransaction, order: .reverse)
]) var transactions: [Transaction]
var groupedTransactionByDate: [Date : [Transaction]] {
print("Grouping transaction")
return Dictionary(grouping: transactions, by: { $0.dateTransaction })
}
var body: some View {
NavigationStack {
List {
ForEach(groupedTransactionByDate.keys.sorted(by: >), id: \.self) { date in
Section(header: Text(date, style: .date).font(.headline)) {
ForEach(groupedTransactionByDate[date]!) { transaction in
TransactionRow(transaction: transaction)
}
}
}
}
}
}
}
Here the log is printed several thousand times
Here in such a code, if we have 5k transactions in the database, when obtaining the MAP value (27 line), we recalculate the value of the
groupedTransactionbyDatevariable and allot the memory of 2 GB, which is why oom Killer kills the application
I used to think that the calculated properties count and update only when changing variables that are involved in the calculation, and it turns out to be at every mention of this variable
Possible solutions to the problem
As if it begs to return the two values of Key and Value in the 25th line so that Value can no longer recalculate to each mention, but I did not find a way to do it
I can do when initializing the Fetchdescriptor and fill out the groupedTransactionByDate variable in advance, but then it will not be updated when data changes in the database in background
What did I try to do
I tried to make the simplest model with two fields and try to group it also, which excludes the change in this model from the outside, but this has led to the fact that for each receipt of the computed properties we recalculate
What behavior I need
When the screen is opened, once we take data from the database (when the data changes in the database, we will recalculate the entire screen)
Once a variable
groupedTransactionByDatewill be countedOnce we will draw the screen until it changes/add/delete at least one transaction in the database, after which 1, 2 and 3 points are again counted
One solution is to store the grouped transactions in a local variable in
body. This guarantees that the computation is done exactly once each time SwiftUI asksTransactionsListfor itsbody.