Hi guys, I’m working with Core Data to save Criterion
objects, but when I create and save an object, my app sometimes just stops responding. I don’t know what is going wrong in my code.
This is the function which the view code runs to add a criterion:
func addCriterion(title: String, info: String?) {
// Create a new criterion with the input title and description
let newCriterion = GoalCriterion.createObject(title: title, info: info, in: dataModel.viewContext)
// Add the criterion to the shown list of criteria
withAnimation(.bouncy) {
criteria.insert(newCriterion, at: 0)
}
// Add the criterion to the goal
dataModel.editGoal(addCriteria: [newCriterion])
}
It uses createObject which is a static function in the class declaration of my Core Data GoalCriterion
object generated by XCode:
static func createObject(title: String,
info: String? = nil,
imageData: Data? = nil,
icon: String? = nil,
in viewContext: NSManagedObjectContext) -> Self {
let newObject = GoalCriterion.init(context: viewContext)
newObject.title = title
newObject.info = info
newObject.imageData = imageData
newObject.icon = icon
return newObject
}
It then adds this object to the views array which the view uses to show all added criteria, and then it saves the object using my DataModel
and its editGoal
function which saves the object to Core Data by adding it to the Goal
object. (This is just the general object saved to Core Data, this object holds an array of criterion thus an addToCriteria
function is generated by XCode automatically when generating the Core Data classes. This function is used by the editGoal
function to add a criterion.):
func editGoal(title: String? = nil,
info: String? = nil,
chosenWay: String? = nil,
pathSummary: String? = nil,
addCriteria: NSSet? = nil,
addPracticalGoals: NSSet? = nil,
addSubgoals: NSSet? = nil,
removeCriteria: NSSet? = nil,
removePracticalGoals: NSSet? = nil,
removeSubgoals: NSSet? = nil) {
guard goal != nil else {
// Notify the user
UIHelper.presentAlert(.essentialDataError)
return
}
// Change properties
if title != nil { goal!.title = title }
if info != nil { goal!.info = info }
if chosenWay != nil { goal!.chosenWay = chosenWay }
if pathSummary != nil { goal!.pathSummary = pathSummary }
// Add elements
if addCriteria != nil {
goal!.addToCriteria(addCriteria!)
}
if addPracticalGoals != nil { goal!.addToPracticalGoals(addPracticalGoals!) }
if addSubgoals != nil { goal!.addToSubgoals(addSubgoals!) }
// Remove elements
if removeCriteria != nil { goal!.removeFromCriteria(removeCriteria!) }
if removePracticalGoals != nil { goal!.removeFromPracticalGoals(removePracticalGoals!) }
if removeSubgoals != nil { goal!.removeFromSubgoals(removeSubgoals!) }
// Save
persistenceController.saveViewContext()
// Re-fetch the goal
fetchGoal()
}
func fetchGoal(noDataCompletion: (() -> Void)? = nil, completion: (() -> Void)? = nil) {
do {
let fetchedGoals: [Goal] = try viewContext.fetch(Goal.fetchRequest())
if !fetchedGoals.isEmpty {
DispatchQueue.main.async {
self.goal = fetchedGoals.first!
}
} else {
noDataCompletion?()
}
completion?()
} catch {
// Notify the user
UIHelper.presentAlert(.essentialDataError)
}
}
Is there something wrong with this code or is there a better approach? Thanks for any help!