I am engaged on my first iOS app. I’ve a button that when pressed, adjustments a state variable, which in flip causes a block of code to execute in a background thread. This code ends in creating a brand new object that then will get saved into persistent reminiscence by inserting into my modelContext by way of modelContext.insert(myObject)
I’ve observed that there is a noticeable UI lag after I press this button. After plenty of testing and debugging, I’ve found that modelContext.insert(myObject) is the bottleneck. If I omit this one line of code and preserve all the pieces else as is, my button works nice and there may be 0 lag. As quickly as I add this line of code again in, I discover vital lag
What is going on on and the way can I take away my UI lag whereas nonetheless additionally storing my newly created object into persistent reminiscence?
I attempted shifting modelContext.insert(myObject) to varied elements of my code, however irrespective of the place I place it, the minute this will get executed my UI freezes for 0.5-1s till it finishes. I do not need my UI to freeze
That is my triggering button. “amount” here’s a @Binding variable coming from my mother or father view
Button(motion: {
amount += 1
UIImpactFeedbackGenerator(fashion: .medium).impactOccurred()
}) {
Picture(systemName: "plus.circle.fill")
.font(.largeTitle)
}
.padding(.trailing)
}
.body(maxWidth: .infinity)
.background(Colour.grey.opacity(0.2))
.cornerRadius(10)
Inside my mother or father view, “amount” is a @State variable. A change on this variable triggers the next code
.onChange(of: amount) { oldValue, newValue in
// if didCardVariantChange is true, reset variable after which do nothing
guard !didCardVariantChange else {
didCardVariantChange = false
return
}
didCardVariantChange = false // reset variable
workItem?.cancel() // Cancel earlier work if any
let cardID = viewSetCardData.card_ids[indexVar]
workItem = DispatchWorkItem {
let isCardInCollection = Assortment.accommodates(the place: { $0.card_id == cardID })
// Add or replace the cardboard in assortment as mandatory
DispatchQueue.international(qos: .background).async {
if newValue > 0 && !isCardInCollection {
memory_operations.shared.addNewCardToCollection(cardIDToAdd: cardID,
selectedCategory: selectedCardCategory,
selectedVariant: selectedCardVariant,
amount: newValue,
modelContext: modelContext,
cardsArray: allCards)
}
}
DispatchQueue.major.asyncAfter(deadline: .now() + 0.5, execute: workItem!)
The next is the perform for memory_operations.shared.addNewCardToCollection referenced above
func addNewCardToCollection(cardIDToAdd: String, selectedCategory: String, selectedVariant: String = "Main Variant", amount: Int, pricePaid: Double? = nil, modelContext: ModelContext, cardsArray: [CardData]) {
var allVariantsList: [String?] = []
for card in cardsArray the place card.id == cardIDToAdd {
allVariantsList = card.allVariants
}
let newCard = CardsOwned(card_id: cardIDToAdd, allVariants: allVariantsList)
newCard.addQuantity_v2(amount, selectedCategory: selectedCategory, selectedVariant: selectedVariant, unitPrice: pricePaid)
DispatchQueue.major.async {
modelContext.insert(newCard) //Challenge happens at this line. Eradicating this line leads to no UI freezing or lag. Including this line again in, leads to a noticeable lag underneath the identical circumstances
attempt? modelContext.save()
}
}