Hi all,
I'm halfway through 100daysOfSwiftUI and started working on my own app (maybe too early but learned a lot already by trying ;) I got following issue now :
I have a class with user preferences which can be stored in UserDefaults :
struct Prefs: Codable {
var apiKey: String
// some other stuff as well
}
class UserPreferences: ObservableObject {
@Published var prefs: Prefs {
didSet {
let encoder = JSONEncoder()
if let encoded = try? encoder.encode(prefs) {
UserDefaults.standard.set(encoded, forKey: "Prefs")
}
}
}
init() {
if let prefs = UserDefaults.standard.data(forKey: "Prefs") {
let decoder = JSONDecoder()
if let decoded = try? decoder.decode(Prefs.self, from: prefs) {
self.prefs = decoded
return
}
}
self.prefs = Prefs(apiKey: "")
}
}
I have a View that is shown in a sheet to fill in the User Preferences :
struct SheetView: View {
@State private var apiKey: String = ""
@ObservedObject var userPrefs: UserPreferences
@Environment(\.presentationMode) var presentationMode
var body: some View {
VStack {
Form {
Section(header: Text("API key")) {
TextField("\(userPrefs.prefs.apiKey)", text: $apiKey)
}
}
Button(action: {
self.userPrefs.prefs = Prefs(apiKey: self.apiKey)
self.presentationMode.wrappedValue.dismiss()
})
{
Text("Save")
}
}
}
}
My ContentView has 2 @ObservedObject variables : userPrefs and info. It also shows the sheet when a button is pressed :
struct ContentView: View {
@ObservedObject var userPrefs = UserPreferences()
@ObservedObject var info = InfoData()
//...
.sheet(isPresented: $showingSheet) {
SheetView(userPrefs: self.userPrefs)
//...
InfoData is another class where data is being read from an API. It has a base URL to access the API and I want to add the apiKey from the userPrefs to that base URL.
class InfoData: ObservableObject {
private var baseURL = URL(string: "http://www.example.com/\(HERE I SHOULD HAVE MY APIKEY)")!
I fail to see however how I can read that apiKey value in that class... If it was a view instead of a class, I could use a @ObservedObject var userPrefs: UserPreferences in that View and do something like InfoData(userPrefs: self.userPrefs) in my ContentView. However, it's a class, not a View and if I try to write following in my ContentView, I get an error :
struct ContentView: View {
@ObservedObject var userPrefs = UserPreferences()
@ObservedObject var info = InfoData(prefs: userPrefs)
--> Cannot use instance member 'userPrefs' within property initializer; property initializers run before 'self' is available
So I'm not sure how I can use that apiKey from the UserPreferences in my InfoData class...