Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

161
Vistas
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 Respuestas
Responde la pregunta

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 Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda