Reputation: 27103
I'm working on an iOS app using the ParseSwift SDK, where I need to save an Exercise object that has relations to MuscleGroup (for primary and secondary muscles) and Equipment. However, even after saving the Exercise object, the relations (primaryMuscles, secondaryMuscles, equipment) remain nil and are not saved in the database.
I define my model as follows:
struct Exercise: ParseObject {
var objectId: String?
var name: String
var isDefault: Bool
var caloriesPerRep: Double
var primaryMuscles: ParseRelation<MuscleGroup>?
var secondaryMuscles: ParseRelation<MuscleGroup>?
var equipment: ParseRelation<Equipment>?
var image: ParseFile?
var user: Pointer<User>?
init(name: String, isDefault: Bool, caloriesPerRep: Double, image: ParseFile?) {
self.name = name
self.isDefault = isDefault
self.caloriesPerRep = caloriesPerRep
self.image = image
}
}
My Save Code:
Here’s how I attempt to save the Exercise object and add relations:
@objc func saveButtonTapped() {
guard let name = nameTextField.text,
let calories = Double(caloriesTextField.text ?? "0"),
let currentUser = User.current else {
print("Error: User is not logged in or fields are missing.")
return
}
let imageFile: ParseFile? = exerciseImage != nil ? ParseFile(name: "image.jpg", data: exerciseImage!.jpegData(compressionQuality: 0.8)!) : nil
// Create a new Exercise object
var newExercise = Exercise(name: name, isDefault: isDefaultSwitch.isOn, caloriesPerRep: calories, image: imageFile)
// Attach the current user to the Exercise object
do {
newExercise.user = try Pointer(currentUser)
} catch {
print("Error creating user pointer: \(error.localizedDescription)")
return
}
// Adding relations for primary muscles
if !selectedPrimaryMuscles.isEmpty {
print("Selected Primary Muscles: \(selectedPrimaryMuscles)")
do {
let primaryMuscleRelation = newExercise.primaryMuscles
try primaryMuscleRelation?.add(selectedPrimaryMuscles) // Add selected primary muscles
} catch {
print("Error adding primary muscles: \(error.localizedDescription)")
}
}
// Adding relations for secondary muscles
if !selectedSecondaryMuscles.isEmpty {
print("Selected Secondary Muscles: \(selectedSecondaryMuscles)")
do {
let secondaryMuscleRelation = newExercise.secondaryMuscles
try secondaryMuscleRelation?.add(selectedSecondaryMuscles) // Add selected secondary muscles
} catch {
print("Error adding secondary muscles: \(error.localizedDescription)")
}
}
// Adding relations for equipment
if !selectedEquipment.isEmpty {
print("Selected Equipment: \(selectedEquipment)")
do {
let equipmentRelation = newExercise.equipment
try equipmentRelation?.add(selectedEquipment) // Add selected equipment
} catch {
print("Error adding equipment: \(error.localizedDescription)")
}
}
// Save the exercise to the database
newExercise.save { result in
switch result {
case .success(let savedExercise):
print("Exercise saved: \(savedExercise)")
case .failure(let error):
print("Error saving Exercise: \(error.localizedDescription)")
}
}
}
Problem:
The Exercise
object is saved successfully, but the relations (primaryMuscles
, secondaryMuscles
, equipment
) remain nil
in the database.
When I try to add objects to these relations using add, they are still nil.
What I've Tried:
I've confirmed that the selected MuscleGroup and Equipment objects are valid before trying to add them to the relations.
Question:
Why are my relations (ParseRelation) still nil. How can I correctly add and save these relations using ParseSwift? Any help would be greatly appreciated!
Upvotes: 1
Views: 61
Reputation: 35648
With the current implementation, I believe to create a pointer to the currentUser, that object would need to be persisted first. e.g. it needs to have it's objectId property populated.
You have a couple of options:
Option 1:
In the Exercise struct, change
var user: Pointer<User>?
to
var user: User?
then the user can be added to a exercise like this
newExercise.user = currentUser
The above works because the unsaved current user object is written along with the Exercise object.
Option 2:
Leave the struct the way it is and either save the CurrentUser object first and then add it as a pointer to the Exercise or modify an already saved Exercise with the saved currentUser. Something like
Task {
let query = Exercise.query()
let results = try await query.find()
let exercise = results.first! //just getting the first one for this example
let currentUser = UserStruct(userName: "Jay")
let savedCurrentUser = try await currentUser.save()
let changedExercise = try exercise.set(\.user, to: savedCurrentUser.toPointer())
let savedChangedExercise = try await changedExercise.save()
}
Upvotes: 0