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

330
Vistas
¿Cómo usar las propiedades @State y @Environment en una estructura que puede producir una vista pero no es una vista?

Estoy tratando de crear un estilo de vista para personalizar una vista personalizada de SwiftUI que estoy desarrollando. Declaré un protocolo con una función makeBody , almaceno el estilo como una propiedad @State para que pueda actualizarse y llamo a makeBody desde dentro de una vista. Esta técnica sigue de cerca lo que ya hace SwiftUI, pero hay una cosa que no puedo entender.

Problema

Hay un comportamiento importante que tienen los estilos de vista propios que no puedo replicar: usar @State , @Environment o cualquier otro contenedor de propiedades de SwiftUI dentro del estilo de vista personalizado.

Por ejemplo, puedo implementar el siguiente ButtonStyle personalizado que solo muestra el valor del esquema de color actual como el contenido del botón.

 struct MyButtonStyle: ButtonStyle { @Environment(\.colorScheme) var colorScheme func makeBody(configuration: Configuration) -> some View { Text(String(describing: colorScheme)) } } struct MyView: View { var body: some View { Button("foo", action: {}).buttonStyle(MyButtonStyle()) } }

Cuando obtengo una vista previa de MyView con un esquema de color preferido .dark , la propiedad colorScheme de MyButtonStyle se actualiza, se vuelve a llamar a la función makeBody y el texto dice "oscuro". Todo esto es lo esperado.

Ahora, echemos un vistazo al estilo de vista personalizado que creé.

 struct MyCustomStyle /* : CustomStyle */ { @Environment(\.colorScheme) var colorScheme @ViewBuilder func makeBody(configuration: CustomStyleConfiguration) -> some View { Text(String(describing: colorScheme)) } } struct MyView: View { @State var style = MyCustomStyle() var body: some View { style.makeBody(configuration: .init()) } }

En el escenario anterior, cuando obtengo una vista previa de MyView con un esquema de color preferido .dark , la propiedad colorScheme no se actualiza y el texto dice "claro" aunque el color de primer plano de la etiqueta haya captado correctamente el cambio.

Pregunta

¿Cómo hacer que las propiedades @State y @Environment funcionen en el estilo de vista personalizado, tal como funcionan en ButtonStyle y en las vistas, sin introducir ningún modelo en la implementación de la función makeBody ?

Estoy seguro de que es posible porque todos los estilos de vista propios ya admiten esto, sin estilos que se ajusten a View y sin que implementen la API privada _makeView que agrega manualmente dependencias al gráfico de SwiftUI (al menos de acuerdo con la interfaz del módulo de SwiftUI ).

Lo que intenté que no funcionó

Intenté inicializar el estilo de vista dentro de un body computable de una vista que envuelve MyView . Eso tampoco funciona.

 struct ContentView: View { var body: some View { MyView(style: MyCustomStyle()) } }

Respuestas inaceptables

Envolver el valor de retorno de la función makeBody personalizada en una vista separada, con la propiedad colorScheme como parte de esa vista, es una solución alternativa conocida que da como resultado un comportamiento correcto. Las respuestas que sugieran esto como una solución alternativa no serán aceptadas porque esta pregunta trata de evitar eso .

No se aceptarán las respuestas que digan que es imposible usar @Environment o @State fuera de un tipo conforme a View (porque es posible, consulte ButtonStyle ), a menos que puedan probar que la API privada es lo que impulsa esto.

over 4 years ago · Santiago Trujillo
1 Respuestas
Responde la pregunta

0

No tenemos acceso a la EnvironmentKey que corresponda con ColorScheme , pero su defaultValue debe ser light . Es por eso que nunca puede obtener un valor, fuera de una vista. Pero su tipo nunca se proporcionará con EnvironmentValues a menos que sea View , ViewModifier , ButtonStyle , ... Apple en realidad no ofrece una lista exhaustiva de protocolos que se consideran "parte de la jerarquía de vistas".

Pero si no se ajusta a uno de ellos, entonces es necesario confiar no en el entorno, sino en la inyección de dependencia. P.ej

 struct MyCustomStyle { init(environment: EnvironmentValues) { colorScheme = environment.colorScheme } private let colorScheme: ColorScheme @ViewBuilder func makeBody() -> some View { Text(String(describing: colorScheme)) } }
 struct ContentView: View { @Environment(\.self) private var environment var style: MyCustomStyle { .init(environment: environment) } var body: some View { style.makeBody() } }

Su pregunta también menciona State , pero no proporcionó un ejemplo. Probablemente solo necesite ajustarse a DynamicProperty para lo que sea que esté haciendo con State .

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