I have a class named AudioRecorder
and a view named RecorderView
. Audiorecorder
has the following functions
- startRecording() --> Starts recording and gets recording start time.
- stopRecording() --> Stops recording and gets recording stop time.
- saveToCoreData() --> Saves startTime, stopTime and rating to coredata
How it works is, RecorderView
lets the user to start and stop a recording by calling the functions in AudioRecorder
. Once the user stops the recording, a new view named RatingView
is shown. User provides a rating in RatingView
and hits submit. By selecting submit, saveToCoreData
in RecorderView
is called with the user provided rating. The problem here is that, by the time the view calls saveToCoreData
, startTime
and stopTime
are lost. This is why they are "nil" and only rating
has a proper value. How do I keep startTime
and stopTime
alive for the next use? Is there a way to fix this problem?
import SwiftUI
struct RecorderView: View {
@ObservedObject var audioRecorder: AudioRecorder
@State private var showRatingView = false
var body: some View {
VStack {
if audioRecorder.recording == false {
Button(action: {self.audioRecorder.startRecording()}) {
Image(systemName: "circle.fill")
}
} else {
Button(action: {self.audioRecorder.stopRecording(); showRatingView = true}) {
Image(systemName: "stop.fill")
}
}
VStack {
if showRatingView == true {
NavigationLink(destination: SurveyRatingView(rating: 1, audioRecorder: AudioRecorder()), isActive: self.$showRatingView) { EmptyView()}
}
}
}
}
}
struct RatingView: View {
@Environment(\.managedObjectContext) var moc
@State var rating: Int16
@ObservedObject var audioRecorder: AudioRecorder
@State private var displayNewView: Bool = false
var body: some View {
VStack {
Text("How was the recording experience?")
// RatingView(rating: $survey)
Button(action: {
self.audioRecorder.saveToCoreData(rating: rating)
}) {
Text("Submit Response")
}
}
.navigationBarBackButtonHidden(true)
}
}
This is what the class AudioRecorder
looks like
class AudioRecorder: NSObject, ObservableObject {
@Published var startTime: Date
@Published var stopTime: Date
func startRecording() -> Date {
self.startTime = Date()
//Start recording related code here
}
func stopRecording() -> Date{
// Stop recording related code here
self.stopTime = Date()
}
func saveToCoreData(rating: Int16){
let aRec = AudioRec(context: moc)
aRec.uuid = UUID()
aRec.startTime = self.startTime //This is nil
aRec.stopTime = self.stopTime //This is nil
aRec.rating = rating //Only this has a proper value
try moc.save()
}
}
CodePudding user response:
In your "showRatingView" VStack
you are passing a new instance of AudioRecorder
. You should pass the instance you already have:
VStack {
if showRatingView == true {
NavigationLink(destination: SurveyRatingView(rating: 1, audioRecorder: self.audioRecorder), isActive: self.$showRatingView) { EmptyView()}
}
}
CodePudding user response:
Without code I'm just guessing what is your setup.
One way to fix this issue would be to store the startTime
and stopTime
values in the AudioRecorder
class itself, instead of just using them locally within the startRecording()
and stopRecording()
functions. This way, the values will still be available when the saveToCoreData()
function is called.
For example, you could add two properties to the AudioRecorder class to store the startTime and stopTime values:
class AudioRecorder {
var startTime: Date?
var stopTime: Date?
func startRecording() {
self.startTime = Date()
// other code here...
}
func stopRecording() {
self.stopTime = Date()
// other code here...
}
func saveToCoreData(rating: Int) {
// use self.startTime and self.stopTime here...
// other code here...
}
}
Alternatively, you could pass the startTime and stopTime values as arguments to the saveToCoreData() function, so that the view can provide these values when calling the function. This would look something like this:
class AudioRecorder {
func startRecording() -> Date {
return Date()
// other code here...
}
func stopRecording() -> Date {
return Date()
// other code here...
}
func saveToCoreData(startTime: Date, stopTime: Date, rating: Int) {
// use startTime and stopTime here...
// other code here...
}
}
In this case, the view would need to store the startTime and stopTime values returned by the startRecording() and stopRecording() functions, and then pass these values to the saveToCoreData() function when calling it.
I hope this helps!