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

321
Views
¿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 answers
Answer question

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 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!