Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

158
Views
Devolver un enlace como el valor proyectado de un contenedor de propiedad

Necesito implementar mi propia versión de @AppStorage, ya que también quiero sincronizar los valores predeterminados del usuario con otros dispositivos, a través del almacenamiento KeyValue de iCloud.

Necesito el valor proyectado para devolver un enlace para poder usarlo así:

 struct ContentView: View { @SyncedAppStorage(key: "testKey", defaultValue: true) private var test var body: some View { Toggle(isOn: $test) { Text("Test") } } }

En mi primer intento, la implementación de la propiedad vinculante se quejó de que me estaba mutando a mí mismo:

 @propertyWrapper struct SyncedAppStorage<Value>: DynamicProperty { let key: String var cachedValue: Value init(key: String, defaultValue: Value) { self.key = key self.cachedValue = UserDefaults.standard.object(forKey: key) as? Value) ?? defaultValue } var wrappedValue: Value { get { getValue() } set { setNewValue(newValue) } } var projectedValue: Binding<Value> { .init(get: getValue, set: { n in setNewValue(n)} ) // <-- Compile error ...self is immutable } private func getValue() -> Value { cachedValue } private mutating func setNewValue(_ newValue: Value) { UserDefaults.standard.set(newValue, forKey: key) NSUbiquitousKeyValueStore.default.set(newValue, forKey: key) cachedValue = newValue } }

Mi próximo intento utiliza una propiedad @State en el contenedor de propiedades, que funciona...

 @propertyWrapper struct SyncedAppStorage <Value>: DynamicProperty { let key: String @State var cachedValue: Value init(key: String, defaultValue: Value) { self.key = key self._cachedValue = State(initialValue: (UserDefaults.standard.object(forKey: key) as? Value) ?? defaultValue) } var wrappedValue: Value { get { getValue() } set { setNewValue(newValue) } } var projectedValue: Binding<Value> { .init(get: getValue, set: { n in setNewValue(n)} ) } private func getValue() -> Value { cachedValue } private func setNewValue(_ newValue: Value) { UserDefaults.standard.set(newValue, forKey: key) cachedValue = newValue NSUbiquitousKeyValueStore.default.set(newValue, forKey: key) } }

Pero, ¿es el camino correcto? ¿Hay mejores soluciones?

over 4 years ago · Santiago Trujillo
1 answers
Answer question

0

Puede usar @State aquí si lo desea. Pero por curiosidad, se me ocurrió otra solución, que usa Combine para funcionar. El problema con su primera implementación es la autocaptura implícita en su enlace.

 @propertyWrapper struct SyncedAppStorage<Value> { let key: String private var sinks = Set<AnyCancellable>() // subject definition let subject: CurrentValueSubject<Value,Never> init(key: String, defaultValue: Value) { self.key = key //Initialize the subject subject = CurrentValueSubject(UserDefaults.standard.object(forKey: key) as? Value ?? defaultValue) //observe changes to subject values subject.map{ UserDefaults.standard.set($0, forKey: key) NSUbiquitousKeyValueStore.default.set($0, forKey: key) }.sink(receiveValue: {_ in}) .store(in: &sinks) } var wrappedValue: Value{ get{ subject.value } set{ subject.value = newValue} } var projectedValue: Binding<Value> { return .init(get: { wrappedValue}, set: { subject.value = $0 }) } }

Eliminé su implementación de cachedValue, ya que (dentro del contexto que proporcionó) no creo que sea necesario.

Felicitaciones a Louis Lac por el enlace.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!