diff --git a/README.md b/README.md index 0d788e6..bd87c2b 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,8 @@ [![License](https://img.shields.io/github/license/0xLeif/AppState)](https://github.com/0xLeif/AppState/blob/main/LICENSE) [![Version](https://img.shields.io/github/v/release/0xLeif/AppState)](https://github.com/0xLeif/AppState/releases) +Read this in other languages: [French](documentation/README.fr.md) | [German](documentation/README.de.md) | [Hindi](documentation/README.hi.md) | [Portuguese](documentation/README.pt.md) | [Russian](documentation/README.ru.md) | [Simplified Chinese](documentation/README.zh-CN.md) | [Spanish](documentation/README.es.md) + **AppState** is a Swift 6 library designed to simplify the management of application state in a thread-safe, type-safe, and SwiftUI-friendly way. It provides a set of tools to centralize and synchronize state across your application, as well as inject dependencies into various parts of your app. ## Requirements @@ -38,9 +40,9 @@ ## Getting Started -To integrate **AppState** into your Swift project, you’ll need to use the Swift Package Manager. Follow the [Installation Guide](documentation/installation.md) for detailed instructions on setting up **AppState**. +To integrate **AppState** into your Swift project, you’ll need to use the Swift Package Manager. Follow the [Installation Guide](documentation/en/installation.md) for detailed instructions on setting up **AppState**. -After installation, refer to the [Usage Overview](documentation/usage-overview.md) for a quick introduction on how to manage state and inject dependencies into your project. +After installation, refer to the [Usage Overview](documentation/en/usage-overview.md) for a quick introduction on how to manage state and inject dependencies into your project. ## Quick Example @@ -74,28 +76,28 @@ This snippet demonstrates defining a state value in an `Application` extension a Here’s a detailed breakdown of **AppState**'s documentation: -- [Installation Guide](documentation/installation.md): How to add **AppState** to your project using Swift Package Manager. -- [Usage Overview](documentation/usage-overview.md): An overview of key features with example implementations. +- [Installation Guide](documentation/en/installation.md): How to add **AppState** to your project using Swift Package Manager. +- [Usage Overview](documentation/en/usage-overview.md): An overview of key features with example implementations. ### Detailed Usage Guides: -- [State and Dependency Management](documentation/usage-state-dependency.md): Centralize state and inject dependencies throughout your app. -- [Slicing State](documentation/usage-slice.md): Access and modify specific parts of the state. -- [StoredState Usage Guide](documentation/usage-storedstate.md): How to persist lightweight data using `StoredState`. -- [FileState Usage Guide](documentation/usage-filestate.md): Learn how to persist larger amounts of data securely on disk. -- [Keychain SecureState Usage](documentation/usage-securestate.md): Store sensitive data securely using the Keychain. -- [iCloud Syncing with SyncState](documentation/usage-syncstate.md): Keep state synchronized across devices using iCloud. -- [FAQ](documentation/faq.md): Answers to common questions when using **AppState**. -- [Constant Usage Guide](documentation/usage-constant.md): Access read-only values from your state. -- [ObservedDependency Usage Guide](documentation/usage-observeddependency.md): Work with `ObservableObject` dependencies in your views. -- [Advanced Usage](documentation/advanced-usage.md): Techniques like just‑in‑time creation and preloading dependencies. -- [Best Practices](documentation/best-practices.md): Tips for structuring your app’s state effectively. -- [Migration Considerations](documentation/migration-considerations.md): Guidance when updating persisted models. +- [State and Dependency Management](documentation/en/usage-state-dependency.md): Centralize state and inject dependencies throughout your app. +- [Slicing State](documentation/en/usage-slice.md): Access and modify specific parts of the state. +- [StoredState Usage Guide](documentation/en/usage-storedstate.md): How to persist lightweight data using `StoredState`. +- [FileState Usage Guide](documentation/en/usage-filestate.md): Learn how to persist larger amounts of data securely on disk. +- [Keychain SecureState Usage](documentation/en/usage-securestate.md): Store sensitive data securely using the Keychain. +- [iCloud Syncing with SyncState](documentation/en/usage-syncstate.md): Keep state synchronized across devices using iCloud. +- [FAQ](documentation/en/faq.md): Answers to common questions when using **AppState**. +- [Constant Usage Guide](documentation/en/usage-constant.md): Access read-only values from your state. +- [ObservedDependency Usage Guide](documentation/en/usage-observeddependency.md): Work with `ObservableObject` dependencies in your views. +- [Advanced Usage](documentation/en/advanced-usage.md): Techniques like just‑in‑time creation and preloading dependencies. +- [Best Practices](documentation/en/best-practices.md): Tips for structuring your app’s state effectively. +- [Migration Considerations](documentation/en/migration-considerations.md): Guidance when updating persisted models. ## Contributing -We welcome contributions! Please check out our [Contributing Guide](documentation/contributing.md) for how to get involved. +We welcome contributions! Please check out our [Contributing Guide](documentation/en/contributing.md) for how to get involved. ## Next Steps -With **AppState** installed, you can start exploring its key features by checking out the [Usage Overview](documentation/usage-overview.md) and more detailed guides. Get started with managing state and dependencies effectively in your Swift projects! For more advanced usage techniques, like Just-In-Time creation and preloading dependencies, see the [Advanced Usage Guide](documentation/advanced-usage.md). You can also review the [Constant](documentation/usage-constant.md) and [ObservedDependency](documentation/usage-observeddependency.md) guides for additional features. +With **AppState** installed, you can start exploring its key features by checking out the [Usage Overview](documentation/en/usage-overview.md) and more detailed guides. Get started with managing state and dependencies effectively in your Swift projects! For more advanced usage techniques, like Just-In-Time creation and preloading dependencies, see the [Advanced Usage Guide](documentation/en/advanced-usage.md). You can also review the [Constant](documentation/en/usage-constant.md) and [ObservedDependency](documentation/en/usage-observeddependency.md) guides for additional features. diff --git a/documentation/README.de.md b/documentation/README.de.md new file mode 100644 index 0000000..71aa01e --- /dev/null +++ b/documentation/README.de.md @@ -0,0 +1,104 @@ +# AppState + +[![macOS Build](https://img.shields.io/github/actions/workflow/status/0xLeif/AppState/macOS.yml?label=macOS&branch=main)](https://github.com/0xLeif/AppState/actions/workflows/macOS.yml) +[![Ubuntu Build](https://img.shields.io/github/actions/workflow/status/0xLeif/AppState/ubuntu.yml?label=Ubuntu&branch=main)](https://github.com/0xLeif/AppState/actions/workflows/ubuntu.yml) +[![Windows Build](https://img.shields.io/github/actions/workflow/status/0xLeif/AppState/windows.yml?label=Windows&branch=main)](https://github.com/0xLeif/AppState/actions/workflows/windows.yml) +[![License](https://img.shields.io/github/license/0xLeif/AppState)](https://github.com/0xLeif/AppState/blob/main/LICENSE) +[![Version](https://img.shields.io/github/v/release/0xLeif/AppState)](https://github.com/0xLeif/AppState/releases) + +**AppState** ist eine Swift 6-Bibliothek, die entwickelt wurde, um die Verwaltung des Anwendungszustands auf eine threadsichere, typsichere und SwiftUI-freundliche Weise zu vereinfachen. Sie bietet eine Reihe von Werkzeugen, um den Zustand in Ihrer gesamten Anwendung zu zentralisieren und zu synchronisieren sowie Abhängigkeiten in verschiedene Teile Ihrer App zu injizieren. + +## Anforderungen + +- **iOS**: 15.0+ +- **watchOS**: 8.0+ +- **macOS**: 11.0+ +- **tvOS**: 15.0+ +- **visionOS**: 1.0+ +- **Swift**: 6.0+ +- **Xcode**: 16.0+ + +**Unterstützung für Nicht-Apple-Plattformen**: Linux & Windows + +> 🍎 Mit diesem Symbol gekennzeichnete Funktionen sind spezifisch für Apple-Plattformen, da sie auf Apple-Technologien wie iCloud und dem Schlüsselbund basieren. + +## Hauptmerkmale + +**AppState** enthält mehrere leistungsstarke Funktionen zur Verwaltung von Zustand und Abhängigkeiten: + +- **State**: Zentralisierte Zustandsverwaltung, die es Ihnen ermöglicht, Änderungen in der gesamten App zu kapseln und zu übertragen. +- **StoredState**: Persistenter Zustand mit `UserDefaults`, ideal zum Speichern kleiner Datenmengen zwischen App-Starts. +- **FileState**: Persistenter Zustand, der mit `FileManager` gespeichert wird und nützlich ist, um größere Datenmengen sicher auf der Festplatte zu speichern. +- 🍎 **SyncState**: Synchronisieren Sie den Zustand über mehrere Geräte mit iCloud und stellen Sie die Konsistenz der Benutzereinstellungen sicher. +- 🍎 **SecureState**: Speichern Sie sensible Daten sicher mit dem Schlüsselbund und schützen Sie Benutzerinformationen wie Token oder Passwörter. +- **Abhängigkeitsmanagement**: Injizieren Sie Abhängigkeiten wie Netzwerkdienste oder Datenbankclients in Ihre gesamte App für eine bessere Modularität und Testbarkeit. +- **Slicing**: Greifen Sie auf bestimmte Teile eines Zustands oder einer Abhängigkeit zu, um eine granulare Kontrolle zu erhalten, ohne den gesamten Anwendungszustand verwalten zu müssen. +- **Constants**: Greifen Sie auf schreibgeschützte Teile Ihres Zustands zu, wenn Sie unveränderliche Werte benötigen. +- **Observed Dependencies**: Beobachten Sie `ObservableObject`-Abhängigkeiten, damit Ihre Ansichten aktualisiert werden, wenn sie sich ändern. + +## Erste Schritte + +Um **AppState** in Ihr Swift-Projekt zu integrieren, müssen Sie den Swift Package Manager verwenden. Befolgen Sie die [Installationsanleitung](de/installation.md) für detaillierte Anweisungen zur Einrichtung von **AppState**. + +Nach der Installation finden Sie in der [Verwendungsübersicht](de/usage-overview.md) eine kurze Einführung in die Verwaltung des Zustands und die Injektion von Abhängigkeiten in Ihr Projekt. + +## Schnelles Beispiel + +Unten sehen Sie ein minimales Beispiel, das zeigt, wie man einen Zustandsausschnitt definiert und von einer SwiftUI-Ansicht darauf zugreift: + +```swift +import AppState +import SwiftUI + +private extension Application { + var counter: State { + state(initial: 0) + } +} + +struct ContentView: View { + @AppState(\.counter) var counter: Int + + var body: some View { + VStack { + Text("Zähler: \(counter)") + Button("Inkrementieren") { counter += 1 } + } + } +} +``` + +Dieser Ausschnitt zeigt, wie man einen Zustandswert in einer `Application`-Erweiterung definiert und den `@AppState`-Property-Wrapper verwendet, um ihn in einer Ansicht zu binden. + +## Dokumentation + +Hier ist eine detaillierte Aufschlüsselung der Dokumentation von **AppState**: + +- [Installationsanleitung](de/installation.md): So fügen Sie **AppState** mit dem Swift Package Manager zu Ihrem Projekt hinzu. +- [Verwendungsübersicht](de/usage-overview.md): Eine Übersicht über die wichtigsten Funktionen mit Beispielimplementierungen. + +### Detaillierte Verwendungsanleitungen: + +- [Zustands- und Abhängigkeitsmanagement](de/usage-state-dependency.md): Zentralisieren Sie den Zustand und injizieren Sie Abhängigkeiten in Ihrer gesamten App. +- [Zustand slicen](de/usage-slice.md): Greifen Sie auf bestimmte Teile des Zustands zu und ändern Sie sie. +- [StoredState-Verwendungsanleitung](de/usage-storedstate.md): So persistieren Sie leichtgewichtige Daten mit `StoredState`. +- [FileState-Verwendungsanleitung](de/usage-filestate.md): Erfahren Sie, wie Sie größere Datenmengen sicher auf der Festplatte persistieren. +- [SecureState mit Schlüsselbund verwenden](de/usage-securestate.md): Speichern Sie sensible Daten sicher mit dem Schlüsselbund. +- [iCloud-Synchronisierung mit SyncState](de/usage-syncstate.md): Halten Sie den Zustand über Geräte hinweg mit iCloud synchron. +- [FAQ](de/faq.md): Antworten auf häufig gestellte Fragen zur Verwendung von **AppState**. +- [Konstanten-Verwendungsanleitung](de/usage-constant.md): Greifen Sie auf schreibgeschützte Werte aus Ihrem Zustand zu. +- [ObservedDependency-Verwendungsanleitung](de/usage-observeddependency.md): Arbeiten Sie mit `ObservableObject`-Abhängigkeiten in Ihren Ansichten. +- [Erweiterte Verwendung](de/advanced-usage.md): Techniken wie Just-in-Time-Erstellung und Vorabladen von Abhängigkeiten. +- [Beste Praktiken](de/best-practices.md): Tipps zur effektiven Strukturierung des Zustands Ihrer App. +- [Überlegungen zur Migration](de/migration-considerations.md): Anleitung zur Aktualisierung persistierter Modelle. + +## Mitwirken + +Wir freuen uns über Beiträge! Bitte lesen Sie unsere [Anleitung für Mitwirkende](de/contributing.md), um zu erfahren, wie Sie sich beteiligen können. + +## Nächste Schritte + +Nach der Installation von **AppState** können Sie die wichtigsten Funktionen erkunden, indem Sie sich die [Verwendungsübersicht](de/usage-overview.md) und detailliertere Anleitungen ansehen. Beginnen Sie mit der effektiven Verwaltung von Zustand und Abhängigkeiten in Ihren Swift-Projekten! Für fortgeschrittenere Verwendungstechniken wie die Just-In-Time-Erstellung und das Vorabladen von Abhängigkeiten siehe die [Anleitung zur erweiterten Verwendung](de/advanced-usage.md). Sie können auch die Anleitungen zu [Konstanten](de/usage-constant.md) und [ObservedDependency](de/usage-observeddependency.md) für zusätzliche Funktionen einsehen. + +--- +Diese Übersetzung wurde automatisch generiert und kann Fehler enthalten. Wenn Sie Muttersprachler sind, freuen wir uns über Ihre Korrekturvorschläge per Pull Request. diff --git a/documentation/README.es.md b/documentation/README.es.md new file mode 100644 index 0000000..1d1af0d --- /dev/null +++ b/documentation/README.es.md @@ -0,0 +1,104 @@ +# AppState + +[![macOS Build](https://img.shields.io/github/actions/workflow/status/0xLeif/AppState/macOS.yml?label=macOS&branch=main)](https://github.com/0xLeif/AppState/actions/workflows/macOS.yml) +[![Ubuntu Build](https://img.shields.io/github/actions/workflow/status/0xLeif/AppState/ubuntu.yml?label=Ubuntu&branch=main)](https://github.com/0xLeif/AppState/actions/workflows/ubuntu.yml) +[![Windows Build](https://img.shields.io/github/actions/workflow/status/0xLeif/AppState/windows.yml?label=Windows&branch=main)](https://github.com/0xLeif/AppState/actions/workflows/windows.yml) +[![License](https://img.shields.io/github/license/0xLeif/AppState)](https://github.com/0xLeif/AppState/blob/main/LICENSE) +[![Version](https://img.shields.io/github/v/release/0xLeif/AppState)](https://github.com/0xLeif/AppState/releases) + +**AppState** es una biblioteca de Swift 6 diseñada para simplificar la gestión del estado de la aplicación de una manera segura para hilos, segura para tipos y compatible con SwiftUI. Proporciona un conjunto de herramientas para centralizar y sincronizar el estado en toda su aplicación, así como para inyectar dependencias en diversas partes de su aplicación. + +## Requisitos + +- **iOS**: 15.0+ +- **watchOS**: 8.0+ +- **macOS**: 11.0+ +- **tvOS**: 15.0+ +- **visionOS**: 1.0+ +- **Swift**: 6.0+ +- **Xcode**: 16.0+ + +**Soporte para plataformas no Apple**: Linux y Windows + +> 🍎 Las características marcadas con este símbolo son específicas de las plataformas de Apple, ya que dependen de tecnologías de Apple como iCloud y el Llavero. + +## Características Clave + +**AppState** incluye varias características potentes para ayudar a gestionar el estado y las dependencias: + +- **State**: Gestión centralizada del estado que le permite encapsular y transmitir cambios en toda la aplicación. +- **StoredState**: Estado persistente utilizando `UserDefaults`, ideal para guardar pequeñas cantidades de datos entre lanzamientos de la aplicación. +- **FileState**: Estado persistente almacenado usando `FileManager`, útil para almacenar grandes cantidades de datos de forma segura en el disco. +- 🍎 **SyncState**: Sincronice el estado en múltiples dispositivos usando iCloud, asegurando la coherencia en las preferencias y configuraciones del usuario. +- 🍎 **SecureState**: Almacene datos sensibles de forma segura usando el Llavero, protegiendo información del usuario como tokens o contraseñas. +- **Gestión de Dependencias**: Inyecte dependencias como servicios de red o clientes de bases de datos en toda su aplicación para una mejor modularidad y pruebas. +- **Slicing**: Acceda a partes específicas de un estado o dependencia para un control granular sin necesidad de gestionar todo el estado de la aplicación. +- **Constants**: Acceda a porciones de solo lectura de su estado cuando necesite valores inmutables. +- **Observed Dependencies**: Observe las dependencias de `ObservableObject` para que sus vistas se actualicen cuando cambien. + +## Empezando + +Para integrar **AppState** en su proyecto de Swift, necesitará usar el Swift Package Manager. Siga la [Guía de Instalación](es/installation.md) para obtener instrucciones detalladas sobre cómo configurar **AppState**. + +Después de la instalación, consulte la [Descripción General del Uso](es/usage-overview.md) para una introducción rápida sobre cómo gestionar el estado e inyectar dependencias en su proyecto. + +## Ejemplo Rápido + +A continuación se muestra un ejemplo mínimo que muestra cómo definir una porción de estado y acceder a ella desde una vista de SwiftUI: + +```swift +import AppState +import SwiftUI + +private extension Application { + var counter: State { + state(initial: 0) + } +} + +struct ContentView: View { + @AppState(\.counter) var counter: Int + + var body: some View { + VStack { + Text("Conteo: \(counter)") + Button("Incrementar") { counter += 1 } + } + } +} +``` + +Este fragmento demuestra cómo definir un valor de estado en una extensión de `Application` y usar el property wrapper `@AppState` para enlazarlo dentro de una vista. + +## Documentación + +Aquí hay un desglose detallado de la documentación de **AppState**: + +- [Guía de Instalación](es/installation.md): Cómo agregar **AppState** a su proyecto usando Swift Package Manager. +- [Descripción General del Uso](es/usage-overview.md): Una descripción general de las características clave con implementaciones de ejemplo. + +### Guías de Uso Detalladas: + +- [Gestión de Estado y Dependencias](es/usage-state-dependency.md): Centralice el estado e inyecte dependencias en toda su aplicación. +- [Slicing de Estado](es/usage-slice.md): Acceda y modifique partes específicas del estado. +- [Guía de Uso de StoredState](es/usage-storedstate.md): Cómo persistir datos ligeros usando `StoredState`. +- [Guía de Uso de FileState](es/usage-filestate.md): Aprenda a persistir grandes cantidades de datos de forma segura en el disco. +- [Uso de SecureState con Llavero](es/usage-securestate.md): Almacene datos sensibles de forma segura usando el Llavero. +- [Sincronización con iCloud usando SyncState](es/usage-syncstate.md): Mantenga el estado sincronizado en todos los dispositivos usando iCloud. +- [Preguntas Frecuentes](es/faq.md): Respuestas a preguntas comunes al usar **AppState**. +- [Guía de Uso de Constantes](es/usage-constant.md): Acceda a valores de solo lectura de su estado. +- [Guía de Uso de ObservedDependency](es/usage-observeddependency.md): Trabaje con dependencias de `ObservableObject` en sus vistas. +- [Uso Avanzado](es/advanced-usage.md): Técnicas como la creación justo a tiempo y la precarga de dependencias. +- [Mejores Prácticas](es/best-practices.md): Consejos para estructurar el estado de su aplicación de manera efectiva. +- [Consideraciones sobre la Migración](es/migration-considerations.md): Orientación al actualizar modelos persistentes. + +## Contribuciones + +¡Aceptamos contribuciones! Consulte nuestra [Guía de Contribuciones](es/contributing.md) para saber cómo participar. + +## Próximos Pasos + +Con **AppState** instalado, puede comenzar a explorar sus características clave consultando la [Descripción General del Uso](es/usage-overview.md) y guías más detalladas. ¡Comience a gestionar el estado y las dependencias de manera efectiva en sus proyectos de Swift! Para técnicas de uso más avanzadas, como la creación Justo a Tiempo y la precarga de dependencias, consulte la [Guía de Uso Avanzado](es/advanced-usage.md). También puede revisar las guías de [Constantes](es/usage-constant.md) y [ObservedDependency](es/usage-observeddependency.md) para características adicionales. + +--- +Esta traducción fue generada automáticamente y puede contener errores. Si eres un hablante nativo, te agradecemos que contribuyas con correcciones a través de un Pull Request. diff --git a/documentation/README.fr.md b/documentation/README.fr.md new file mode 100644 index 0000000..243c1a8 --- /dev/null +++ b/documentation/README.fr.md @@ -0,0 +1,104 @@ +# AppState + +[![macOS Build](https://img.shields.io/github/actions/workflow/status/0xLeif/AppState/macOS.yml?label=macOS&branch=main)](https://github.com/0xLeif/AppState/actions/workflows/macOS.yml) +[![Ubuntu Build](https://img.shields.io/github/actions/workflow/status/0xLeif/AppState/ubuntu.yml?label=Ubuntu&branch=main)](https://github.com/0xLeif/AppState/actions/workflows/ubuntu.yml) +[![Windows Build](https://img.shields.io/github/actions/workflow/status/0xLeif/AppState/windows.yml?label=Windows&branch=main)](https://github.com/0xLeif/AppState/actions/workflows/windows.yml) +[![License](https://img.shields.io/github/license/0xLeif/AppState)](https://github.com/0xLeif/AppState/blob/main/LICENSE) +[![Version](https://img.shields.io/github/v/release/0xLeif/AppState)](https://github.com/0xLeif/AppState/releases) + +**AppState** est une bibliothèque Swift 6 conçue pour simplifier la gestion de l'état de l'application de manière thread-safe, type-safe et compatible avec SwiftUI. Elle fournit un ensemble d'outils pour centraliser et synchroniser l'état à travers votre application, ainsi que pour injecter des dépendances dans diverses parties de votre application. + +## Exigences + +- **iOS**: 15.0+ +- **watchOS**: 8.0+ +- **macOS**: 11.0+ +- **tvOS**: 15.0+ +- **visionOS**: 1.0+ +- **Swift**: 6.0+ +- **Xcode**: 16.0+ + +**Prise en charge des plates-formes non-Apple**: Linux et Windows + +> 🍎 Les fonctionnalités marquées de ce symbole sont spécifiques aux plates-formes Apple, car elles reposent sur des technologies Apple telles qu'iCloud et le Trousseau. + +## Fonctionnalités Clés + +**AppState** inclut plusieurs fonctionnalités puissantes pour aider à gérer l'état et les dépendances : + +- **State**: Gestion centralisée de l'état qui vous permet d'encapsuler et de diffuser les changements à travers l'application. +- **StoredState**: État persistant utilisant `UserDefaults`, idéal pour sauvegarder de petites quantités de données entre les lancements de l'application. +- **FileState**: État persistant stocké à l'aide de `FileManager`, utile pour stocker de plus grandes quantités de données en toute sécurité sur le disque. +- 🍎 **SyncState**: Synchronisez l'état sur plusieurs appareils à l'aide d'iCloud, garantissant la cohérence des préférences et des paramètres de l'utilisateur. +- 🍎 **SecureState**: Stockez les données sensibles en toute sécurité à l'aide du Trousseau, protégeant les informations de l'utilisateur telles que les jetons ou les mots de passe. +- **Gestion des Dépendances**: Injectez des dépendances comme des services réseau ou des clients de base de données à travers votre application pour une meilleure modularité et des tests facilités. +- **Slicing**: Accédez à des parties spécifiques d'un état ou d'une dépendance pour un contrôle granulaire sans avoir à gérer l'état complet de l'application. +- **Constants**: Accédez à des tranches en lecture seule de votre état lorsque vous avez besoin de valeurs immuables. +- **Observed Dependencies**: Observez les dépendances `ObservableObject` pour que vos vues se mettent à jour lorsqu'elles changent. + +## Pour Commencer + +Pour intégrer **AppState** dans votre projet Swift, vous devrez utiliser le Swift Package Manager. Suivez le [Guide d'Installation](fr/installation.md) pour des instructions détaillées sur la configuration de **AppState**. + +Après l'installation, consultez l'[Aperçu de l'Utilisation](fr/usage-overview.md) pour une introduction rapide sur la manière de gérer l'état et d'injecter des dépendances dans votre projet. + +## Exemple Rapide + +Voici un exemple minimal montrant comment définir une tranche d'état et y accéder depuis une vue SwiftUI : + +```swift +import AppState +import SwiftUI + +private extension Application { + var counter: State { + state(initial: 0) + } +} + +struct ContentView: View { + @AppState(\.counter) var counter: Int + + var body: some View { + VStack { + Text("Compteur: \(counter)") + Button("Incrémenter") { counter += 1 } + } + } +} +``` + +Cet extrait montre comment définir une valeur d'état dans une extension `Application` et utiliser le property wrapper `@AppState` pour la lier à l'intérieur d'une vue. + +## Documentation + +Voici une ventilation détaillée de la documentation de **AppState** : + +- [Guide d'Installation](fr/installation.md) : Comment ajouter **AppState** à votre projet à l'aide du Swift Package Manager. +- [Aperçu de l'Utilisation](fr/usage-overview.md) : Un aperçu des fonctionnalités clés avec des exemples d'implémentation. + +### Guides d'Utilisation Détaillés : + +- [Gestion de l'État et des Dépendances](fr/usage-state-dependency.md) : Centralisez l'état et injectez des dépendances dans toute votre application. +- [Découpage de l'État (Slicing)](fr/usage-slice.md) : Accédez et modifiez des parties spécifiques de l'état. +- [Guide d'Utilisation de StoredState](fr/usage-storedstate.md) : Comment persister des données légères à l'aide de `StoredState`. +- [Guide d'Utilisation de FileState](fr/usage-filestate.md) : Apprenez à persister de plus grandes quantités de données en toute sécurité sur le disque. +- [Utilisation de SecureState avec le Trousseau](fr/usage-securestate.md) : Stockez les données sensibles en toute sécurité à l'aide du Trousseau. +- [Synchronisation iCloud avec SyncState](fr/usage-syncstate.md) : Maintenez l'état synchronisé sur tous les appareils à l'aide d'iCloud. +- [FAQ](fr/faq.md) : Réponses aux questions courantes lors de l'utilisation de **AppState**. +- [Guide d'Utilisation des Constantes](fr/usage-constant.md) : Accédez à des valeurs en lecture seule de votre état. +- [Guide d'Utilisation de ObservedDependency](fr/usage-observeddependency.md) : Travaillez avec des dépendances `ObservableObject` dans vos vues. +- [Utilisation Avancée](fr/advanced-usage.md) : Techniques telles que la création juste à temps et le préchargement des dépendances. +- [Meilleures Pratiques](fr/best-practices.md) : Conseils pour structurer efficacement l'état de votre application. +- [Considérations sur la Migration](fr/migration-considerations.md) : Guide pour la mise à jour des modèles persistants. + +## Contributions + +Nous accueillons les contributions ! Veuillez consulter notre [Guide de Contribution](fr/contributing.md) pour savoir comment vous impliquer. + +## Prochaines Étapes + +Une fois **AppState** installé, vous pouvez commencer à explorer ses fonctionnalités clés en consultant l'[Aperçu de l'Utilisation](fr/usage-overview.md) et des guides plus détaillés. Commencez à gérer efficacement l'état et les dépendances dans vos projets Swift ! Pour des techniques d'utilisation plus avancées, comme la création Juste-à-Temps et le préchargement des dépendances, consultez le [Guide d'Utilisation Avancée](fr/advanced-usage.md). Vous pouvez également consulter les guides [Constant](fr/usage-constant.md) et [ObservedDependency](fr/usage-observeddependency.md) pour des fonctionnalités supplémentaires. + +--- +Cette traduction a été générée automatiquement et peut contenir des erreurs. Si vous êtes un locuteur natif, nous vous serions reconnaissants de contribuer avec des corrections via une Pull Request. diff --git a/documentation/README.hi.md b/documentation/README.hi.md new file mode 100644 index 0000000..15a028c --- /dev/null +++ b/documentation/README.hi.md @@ -0,0 +1,104 @@ +# AppState + +[![macOS बिल्ड](https://img.shields.io/github/actions/workflow/status/0xLeif/AppState/macOS.yml?label=macOS&branch=main)](https://github.com/0xLeif/AppState/actions/workflows/macOS.yml) +[![Ubuntu बिल्ड](https://img.shields.io/github/actions/workflow/status/0xLeif/AppState/ubuntu.yml?label=Ubuntu&branch=main)](https://github.com/0xLeif/AppState/actions/workflows/ubuntu.yml) +[![Windows बिल्ड](https://img.shields.io/github/actions/workflow/status/0xLeif/AppState/windows.yml?label=Windows&branch=main)](https://github.com/0xLeif/AppState/actions/workflows/windows.yml) +[![लाइसेंस](https://img.shields.io/github/license/0xLeif/AppState)](https://github.com/0xLeif/AppState/blob/main/LICENSE) +[![संस्करण](https://img.shields.io/github/v/release/0xLeif/AppState)](https://github.com/0xLeif/AppState/releases) + +**AppState** एक स्विफ्ट 6 लाइब्रेरी है जिसे एप्लिकेशन स्थिति के प्रबंधन को थ्रेड-सुरक्षित, प्रकार-सुरक्षित और SwiftUI-अनुकूल तरीके से सरल बनाने के लिए डिज़ाइन किया गया है। यह आपके एप्लिकेशन में स्थिति को केंद्रीकृत और सिंक्रनाइज़ करने के लिए उपकरणों का एक सेट प्रदान करता है, साथ ही आपके ऐप के विभिन्न हिस्सों में निर्भरताएँ इंजेक्ट करता है। + +## आवश्यकताएँ + +- **iOS**: 15.0+ +- **watchOS**: 8.0+ +- **macOS**: 11.0+ +- **tvOS**: 15.0+ +- **visionOS**: 1.0+ +- **स्विफ्ट**: 6.0+ +- **Xcode**: 16.0+ + +**गैर-Apple प्लेटफ़ॉर्म समर्थन**: लिनक्स और विंडोज + +> 🍎 इस प्रतीक के साथ चिह्नित सुविधाएँ Apple प्लेटफ़ॉर्म के लिए विशिष्ट हैं, क्योंकि वे iCloud और कीचेन जैसी Apple तकनीकों पर निर्भर करती हैं। + +## मुख्य विशेषताएँ + +**AppState** में स्थिति और निर्भरताओं के प्रबंधन में मदद करने के लिए कई शक्तिशाली सुविधाएँ शामिल हैं: + +- **State**: केंद्रीकृत स्थिति प्रबंधन जो आपको पूरे ऐप में परिवर्तनों को एनकैप्सुलेट और प्रसारित करने की अनुमति देता है। +- **StoredState**: `UserDefaults` का उपयोग करके स्थायी स्थिति, ऐप लॉन्च के बीच थोड़ी मात्रा में डेटा सहेजने के लिए आदर्श। +- **FileState**: `FileManager` का उपयोग करके संग्रहीत स्थायी स्थिति, डिस्क पर बड़ी मात्रा में डेटा को सुरक्षित रूप से संग्रहीत करने के लिए उपयोगी। +- 🍎 **SyncState**: iCloud का उपयोग करके कई उपकरणों में स्थिति को सिंक्रनाइज़ करें, उपयोगकर्ता की प्राथमिकताओं और सेटिंग्स में स्थिरता सुनिश्चित करता है। +- 🍎 **SecureState**: कीचेन का उपयोग करके संवेदनशील डेटा को सुरक्षित रूप से संग्रहीत करें, उपयोगकर्ता की जानकारी जैसे टोकन या पासवर्ड की सुरक्षा करता है। +- **निर्भरता प्रबंधन**: बेहतर मॉड्यूलरिटी और परीक्षण के लिए अपने ऐप में नेटवर्क सेवाओं या डेटाबेस क्लाइंट जैसी निर्भरताएँ इंजेक्ट करें। +- **Slicing**: संपूर्ण एप्लिकेशन स्थिति को प्रबंधित करने की आवश्यकता के बिना दानेदार नियंत्रण के लिए किसी स्थिति या निर्भरता के विशिष्ट भागों तक पहुँचें। +- **Constants**: जब आपको अपरिवर्तनीय मानों की आवश्यकता हो तो अपनी स्थिति के केवल-पढ़ने के लिए स्लाइस तक पहुँचें। +- **Observed Dependencies**: `ObservableObject` निर्भरताओं का निरीक्षण करें ताकि जब वे बदलें तो आपके विचार अपडेट हों। + +## शुरुआत कैसे करें + +**AppState** को अपने स्विफ्ट प्रोजेक्ट में एकीकृत करने के लिए, आपको स्विफ्ट पैकेज मैनेजर का उपयोग करना होगा। **AppState** स्थापित करने के बारे में विस्तृत निर्देशों के लिए [स्थापना मार्गदर्शिका](hi/installation.md) का पालन करें। + +स्थापना के बाद, अपने प्रोजेक्ट में स्थिति को प्रबंधित करने और निर्भरताएँ इंजेक्ट करने के तरीके के बारे में त्वरित परिचय के लिए [उपयोग अवलोकन](hi/usage-overview.md) देखें। + +## त्वरित उदाहरण + +नीचे एक न्यूनतम उदाहरण दिया गया है जो दिखाता है कि स्थिति का एक टुकड़ा कैसे परिभाषित करें और इसे SwiftUI दृश्य से कैसे एक्सेस करें: + +```swift +import AppState +import SwiftUI + +private extension Application { + var counter: State { + state(initial: 0) + } +} + +struct ContentView: View { + @AppState(\.counter) var counter: Int + + var body: some View { + VStack { + Text("गणना: \(counter)") + Button("बढ़ाएँ") { counter += 1 } + } + } +} +``` + +यह स्निपेट एक `Application` एक्सटेंशन में एक स्थिति मान को परिभाषित करने और इसे एक दृश्य के अंदर बाँधने के लिए `@AppState` प्रॉपर्टी रैपर का उपयोग करने का प्रदर्शन करता है। + +## दस्तावेज़ीकरण + +यहाँ **AppState** के दस्तावेज़ीकरण का विस्तृत विवरण दिया गया है: + +- [स्थापना मार्गदर्शिका](hi/installation.md): स्विफ्ट पैकेज मैनेजर का उपयोग करके अपने प्रोजेक्ट में **AppState** कैसे जोड़ें। +- [उपयोग अवलोकन](hi/usage-overview.md): उदाहरण कार्यान्वयन के साथ मुख्य विशेषताओं का अवलोकन। + +### विस्तृत उपयोग मार्गदर्शिकाएँ: + +- [स्थिति और निर्भरता प्रबंधन](hi/usage-state-dependency.md): स्थिति को केंद्रीकृत करें और अपने पूरे ऐप में निर्भरताएँ इंजेक्ट करें। +- [स्लाइसिंग स्थिति](hi/usage-slice.md): स्थिति के विशिष्ट भागों तक पहुँचें और संशोधित करें। +- [StoredState उपयोग मार्गदर्शिका](hi/usage-storedstate.md): `StoredState` का उपयोग करके हल्के डेटा को कैसे बनाए रखें। +- [FileState उपयोग मार्गदर्शिका](hi/usage-filestate.md): डिस्क पर बड़ी मात्रा में डेटा को सुरक्षित रूप से कैसे बनाए रखें, जानें। +- [कीचेन SecureState उपयोग](hi/usage-securestate.md): कीचेन का उपयोग करके संवेदनशील डेटा को सुरक्षित रूप से संग्रहीत करें। +- [SyncState के साथ iCloud सिंकिंग](hi/usage-syncstate.md): iCloud का उपयोग करके उपकरणों में स्थिति को सिंक्रनाइज़ रखें। +- [अक्सर पूछे जाने वाले प्रश्न](hi/faq.md): **AppState** का उपयोग करते समय सामान्य प्रश्नों के उत्तर। +- [स्थिरांक उपयोग मार्गदर्शिका](hi/usage-constant.md): अपनी स्थिति से केवल-पढ़ने के लिए मानों तक पहुँचें। +- [ObservedDependency उपयोग मार्गदर्शिका](hi/usage-observeddependency.md): अपने विचारों में `ObservableObject` निर्भरताओं के साथ काम करें। +- [उन्नत उपयोग](hi/advanced-usage.md): जस्ट-इन-टाइम निर्माण और निर्भरताओं को प्रीलोड करने जैसी तकनीकें। +- [सर्वोत्तम प्रथाएँ](hi/best-practices.md): अपने ऐप की स्थिति को प्रभावी ढंग से संरचित करने के लिए युक्तियाँ। +- [माइग्रेशन विचार](hi/migration-considerations.md): स्थायी मॉडल अपडेट करते समय मार्गदर्शन। + +## योगदान + +हम योगदान का स्वागत करते हैं! कृपया शामिल होने के तरीके के लिए हमारी [योगदान मार्गदर्शिका](hi/contributing.md) देखें। + +## अगले चरण + +**AppState** स्थापित होने के साथ, आप [उपयोग अवलोकन](hi/usage-overview.md) और अधिक विस्तृत मार्गदर्शिकाओं को देखकर इसकी मुख्य विशेषताओं की खोज शुरू कर सकते हैं। अपने स्विफ्ट प्रोजेक्ट्स में स्थिति और निर्भरताओं का प्रभावी ढंग से प्रबंधन शुरू करें! अधिक उन्नत उपयोग तकनीकों के लिए, जैसे जस्ट-इन-टाइम निर्माण और निर्भरताओं को प्रीलोड करना, [उन्नत उपयोग मार्गदर्शिका](hi/advanced-usage.md) देखें। आप अतिरिक्त सुविधाओं के लिए [स्थिरांक](hi/usage-constant.md) और [ObservedDependency](hi/usage-observeddependency.md) मार्गदर्शिकाओं की भी समीक्षा कर सकते हैं। + +--- +यह अनुवाद स्वचालित रूप से उत्पन्न किया गया था और इसमें त्रुटियाँ हो सकती हैं। यदि आप एक देशी वक्ता हैं, तो हम एक पुल अनुरोध के माध्यम से सुधारों में आपके योगदान की सराहना करेंगे। diff --git a/documentation/README.pt.md b/documentation/README.pt.md new file mode 100644 index 0000000..048395f --- /dev/null +++ b/documentation/README.pt.md @@ -0,0 +1,104 @@ +# AppState + +[![macOS Build](https://img.shields.io/github/actions/workflow/status/0xLeif/AppState/macOS.yml?label=macOS&branch=main)](https://github.com/0xLeif/AppState/actions/workflows/macOS.yml) +[![Ubuntu Build](https://img.shields.io/github/actions/workflow/status/0xLeif/AppState/ubuntu.yml?label=Ubuntu&branch=main)](https://github.com/0xLeif/AppState/actions/workflows/ubuntu.yml) +[![Windows Build](https://img.shields.io/github/actions/workflow/status/0xLeif/AppState/windows.yml?label=Windows&branch=main)](https://github.com/0xLeif/AppState/actions/workflows/windows.yml) +[![License](https://img.shields.io/github/license/0xLeif/AppState)](https://github.com/0xLeif/AppState/blob/main/LICENSE) +[![Version](https://img.shields.io/github/v/release/0xLeif/AppState)](https://github.com/0xLeif/AppState/releases) + +**AppState** é uma biblioteca Swift 6 projetada para simplificar o gerenciamento do estado da aplicação de uma forma segura para threads, segura para tipos e amigável ao SwiftUI. Ele fornece um conjunto de ferramentas para centralizar e sincronizar o estado em toda a sua aplicação, bem como para injetar dependências em várias partes do seu aplicativo. + +## Requisitos + +- **iOS**: 15.0+ +- **watchOS**: 8.0+ +- **macOS**: 11.0+ +- **tvOS**: 15.0+ +- **visionOS**: 1.0+ +- **Swift**: 6.0+ +- **Xcode**: 16.0+ + +**Suporte a plataformas não-Apple**: Linux e Windows + +> 🍎 Recursos marcados com este símbolo são específicos para plataformas Apple, pois dependem de tecnologias da Apple, como iCloud e o Keychain. + +## Principais Recursos + +**AppState** inclui vários recursos poderosos para ajudar a gerenciar o estado e as dependências: + +- **State**: Gerenciamento de estado centralizado que permite encapsular e transmitir alterações em todo o aplicativo. +- **StoredState**: Estado persistente usando `UserDefaults`, ideal para salvar pequenas quantidades de dados entre as inicializações do aplicativo. +- **FileState**: Estado persistente armazenado usando `FileManager`, útil para armazenar grandes quantidades de dados com segurança no disco. +- 🍎 **SyncState**: Sincronize o estado em vários dispositivos usando o iCloud, garantindo a consistência nas preferências e configurações do usuário. +- 🍎 **SecureState**: Armazene dados confidenciais com segurança usando o Keychain, protegendo informações do usuário, como tokens ou senhas. +- **Gerenciamento de Dependências**: Injete dependências como serviços de rede ou clientes de banco de dados em todo o seu aplicativo para melhor modularidade e testes. +- **Slicing**: Acesse partes específicas de um estado ou dependência para controle granular sem a necessidade de gerenciar todo o estado da aplicação. +- **Constants**: Acesse fatias somente leitura do seu estado quando precisar de valores imutáveis. +- **Observed Dependencies**: Observe as dependências `ObservableObject` para que suas visualizações sejam atualizadas quando elas mudarem. + +## Começando + +Para integrar o **AppState** ao seu projeto Swift, você precisará usar o Swift Package Manager. Siga o [Guia de Instalação](pt/installation.md) para obter instruções detalhadas sobre como configurar o **AppState**. + +Após a instalação, consulte a [Visão Geral do Uso](pt/usage-overview.md) para uma introdução rápida sobre como gerenciar o estado e injetar dependências em seu projeto. + +## Exemplo Rápido + +Abaixo está um exemplo mínimo mostrando como definir uma fatia de estado e acessá-la a partir de uma visualização SwiftUI: + +```swift +import AppState +import SwiftUI + +private extension Application { + var counter: State { + state(initial: 0) + } +} + +struct ContentView: View { + @AppState(\.counter) var counter: Int + + var body: some View { + VStack { + Text("Contagem: \(counter)") + Button("Incrementar") { counter += 1 } + } + } +} +``` + +Este trecho demonstra a definição de um valor de estado em uma extensão `Application` e o uso do property wrapper `@AppState` para vinculá-lo dentro de uma visualização. + +## Documentação + +Aqui está um detalhamento da documentação do **AppState**: + +- [Guia de Instalação](pt/installation.md): Como adicionar o **AppState** ao seu projeto usando o Swift Package Manager. +- [Visão Geral do Uso](pt/usage-overview.md): Uma visão geral dos principais recursos com exemplos de implementação. + +### Guias de Uso Detalhados: + +- [Gerenciamento de Estado e Dependência](pt/usage-state-dependency.md): Centralize o estado e injete dependências em todo o seu aplicativo. +- [Fatiando o Estado](pt/usage-slice.md): Acesse e modifique partes específicas do estado. +- [Guia de Uso do StoredState](pt/usage-storedstate.md): Como persistir dados leves usando `StoredState`. +- [Guia de Uso do FileState](pt/usage-filestate.md): Aprenda a persistir grandes quantidades de dados com segurança no disco. +- [Uso do SecureState com Keychain](pt/usage-securestate.md): Armazene dados confidenciais com segurança usando o Keychain. +- [Sincronização com iCloud com SyncState](pt/usage-syncstate.md): Mantenha o estado sincronizado em todos os dispositivos usando o iCloud. +- [FAQ](pt/faq.md): Respostas a perguntas comuns ao usar o **AppState**. +- [Guia de Uso de Constantes](pt/usage-constant.md): Acesse valores somente leitura do seu estado. +- [Guia de Uso de ObservedDependency](pt/usage-observeddependency.md): Trabalhe com dependências `ObservableObject` em suas visualizações. +- [Uso Avançado](pt/advanced-usage.md): Técnicas como criação just-in-time e pré-carregamento de dependências. +- [Melhores Práticas](pt/best-practices.md): Dicas para estruturar o estado do seu aplicativo de forma eficaz. +- [Considerações sobre Migração](pt/migration-considerations.md): Orientação ao atualizar modelos persistidos. + +## Contribuições + +Aceitamos contribuições! Por favor, confira nosso [Guia de Contribuição](pt/contributing.md) para saber como se envolver. + +## Próximos Passos + +Com o **AppState** instalado, você pode começar a explorar seus principais recursos, consultando a [Visão Geral do Uso](pt/usage-overview.md) e guias mais detalhados. Comece a gerenciar o estado e as dependências de forma eficaz em seus projetos Swift! Para técnicas de uso mais avançadas, como criação Just-In-Time e pré-carregamento de dependências, consulte o [Guia de Uso Avançado](pt/advanced-usage.md). Você também pode revisar os guias [Constant](pt/usage-constant.md) e [ObservedDependency](pt/usage-observeddependency.md) para recursos adicionais. + +--- +Esta tradução foi gerada automaticamente e pode conter erros. Se você é um falante nativo, agradecemos suas contribuições com correções por meio de um Pull Request. diff --git a/documentation/README.ru.md b/documentation/README.ru.md new file mode 100644 index 0000000..ed1b362 --- /dev/null +++ b/documentation/README.ru.md @@ -0,0 +1,104 @@ +# AppState + +[![macOS Build](https://img.shields.io/github/actions/workflow/status/0xLeif/AppState/macOS.yml?label=macOS&branch=main)](https://github.com/0xLeif/AppState/actions/workflows/macOS.yml) +[![Ubuntu Build](https://img.shields.io/github/actions/workflow/status/0xLeif/AppState/ubuntu.yml?label=Ubuntu&branch=main)](https://github.com/0xLeif/AppState/actions/workflows/ubuntu.yml) +[![Windows Build](https://img.shields.io/github/actions/workflow/status/0xLeif/AppState/windows.yml?label=Windows&branch=main)](https://github.com/0xLeif/AppState/actions/workflows/windows.yml) +[![License](https://img.shields.io/github/license/0xLeif/AppState)](https://github.com/0xLeif/AppState/blob/main/LICENSE) +[![Version](https://img.shields.io/github/v/release/0xLeif/AppState)](https://github.com/0xLeif/AppState/releases) + +**AppState** - это библиотека Swift 6, разработанная для упрощения управления состоянием приложения в поточно-безопасном, типобезопасном и дружественном к SwiftUI виде. Она предоставляет набор инструментов для централизации и синхронизации состояния в вашем приложении, а также для внедрения зависимостей в различные части вашего приложения. + +## Требования + +- **iOS**: 15.0+ +- **watchOS**: 8.0+ +- **macOS**: 11.0+ +- **tvOS**: 15.0+ +- **visionOS**: 1.0+ +- **Swift**: 6.0+ +- **Xcode**: 16.0+ + +**Поддержка платформ, не относящихся к Apple**: Linux и Windows + +> 🍎 Функции, отмеченные этим символом, специфичны для платформ Apple, так как они зависят от технологий Apple, таких как iCloud и Keychain. + +## Ключевые особенности + +**AppState** включает в себя несколько мощных функций для управления состоянием и зависимостями: + +- **State**: Централизованное управление состоянием, которое позволяет инкапсулировать и транслировать изменения по всему приложению. +- **StoredState**: Постоянное состояние с использованием `UserDefaults`, идеально подходящее для сохранения небольших объемов данных между запусками приложения. +- **FileState**: Постоянное состояние, хранящееся с использованием `FileManager`, полезное для безопасного хранения больших объемов данных на диске. +- 🍎 **SyncState**: Синхронизация состояния между несколькими устройствами с использованием iCloud, обеспечивающая согласованность пользовательских предпочтений и настроек. +- 🍎 **SecureState**: Безопасное хранение конфиденциальных данных с использованием Keychain, защита информации пользователя, такой как токены или пароли. +- **Управление зависимостями**: Внедряйте зависимости, такие как сетевые службы или клиенты баз данных, по всему вашему приложению для лучшей модульности и тестирования. +- **Slicing**: Доступ к определенным частям состояния или зависимости для гранулярного контроля без необходимости управлять всем состоянием приложения. +- **Constants**: Доступ к срезам вашего состояния только для чтения, когда вам нужны неизменяемые значения. +- **Observed Dependencies**: Наблюдайте за зависимостями `ObservableObject`, чтобы ваши представления обновлялись при их изменении. + +## Начало работы + +Чтобы интегрировать **AppState** в ваш проект Swift, вам понадобится использовать Swift Package Manager. Следуйте [Руководству по установке](ru/installation.md) для получения подробных инструкций по настройке **AppState**. + +После установки обратитесь к [Обзору использования](ru/usage-overview.md) для быстрого введения в управление состоянием и внедрение зависимостей в ваш проект. + +## Краткий пример + +Ниже приведен минимальный пример, показывающий, как определить фрагмент состояния и получить к нему доступ из представления SwiftUI: + +```swift +import AppState +import SwiftUI + +private extension Application { + var counter: State { + state(initial: 0) + } +} + +struct ContentView: View { + @AppState(\.counter) var counter: Int + + var body: some View { + VStack { + Text("Счет: \(counter)") + Button("Увеличить") { counter += 1 } + } + } +} +``` + +Этот фрагмент демонстрирует определение значения состояния в расширении `Application` и использование обертки свойства `@AppState` для его привязки внутри представления. + +## Документация + +Вот подробная разбивка документации **AppState**: + +- [Руководство по установке](ru/installation.md): Как добавить **AppState** в ваш проект с помощью Swift Package Manager. +- [Обзор использования](ru/usage-overview.md): Обзор ключевых функций с примерами реализации. + +### Подробные руководства по использованию: + +- [Управление состоянием и зависимостями](ru/usage-state-dependency.md): Централизуйте состояние и внедряйте зависимости по всему вашему приложению. +- [Нарезка состояния](ru/usage-slice.md): Доступ и изменение определенных частей состояния. +- [Руководство по использованию StoredState](ru/usage-storedstate.md): Как сохранять легковесные данные с помощью `StoredState`. +- [Руководство по использованию FileState](ru/usage-filestate.md): Узнайте, как безопасно хранить большие объемы данных на диске. +- [Использование SecureState с Keychain](ru/usage-securestate.md): Безопасное хранение конфиденциальных данных с использованием Keychain. +- [Синхронизация с iCloud с помощью SyncState](ru/usage-syncstate.md): Поддерживайте синхронизацию состояния на всех устройствах с помощью iCloud. +- [Часто задаваемые вопросы](ru/faq.md): Ответы на часто задаваемые вопросы при использовании **AppState**. +- [Руководство по использованию констант](ru/usage-constant.md): Доступ к значениям только для чтения из вашего состояния. +- [Руководство по использованию ObservedDependency](ru/usage-observeddependency.md): Работа с зависимостями `ObservableObject` в ваших представлениях. +- [Расширенное использование](ru/advanced-usage.md): Такие методы, как создание «точно в срок» и предварительная загрузка зависимостей. +- [Лучшие практики](ru/best-practices.md): Советы по эффективной структуре состояния вашего приложения. +- [Рекомендации по миграции](ru/migration-considerations.md): Руководство при обновлении сохраненных моделей. + +## Вклад + +Мы приветствуем вклад! Пожалуйста, ознакомьтесь с нашим [Руководством по участию](ru/contributing.md), чтобы узнать, как принять участие. + +## Следующие шаги + +После установки **AppState** вы можете начать изучать его ключевые функции, ознакомившись с [Обзором использования](ru/usage-overview.md) и более подробными руководствами. Начните эффективно управлять состоянием и зависимостями в ваших проектах Swift! Для более продвинутых техник использования, таких как создание «Точно в срок» и предварительная загрузка зависимостей, см. [Руководство по расширенному использованию](ru/advanced-usage.md). Вы также можете просмотреть руководства [Constant](ru/usage-constant.md) и [ObservedDependency](ru/usage-observeddependency.md) для получения дополнительных функций. + +--- +Это было сгенерировано с использованием [Jules](https://jules.google), могут возникнуть ошибки. Пожалуйста, сделайте Pull Request с любыми исправлениями, которые должны произойти, если вы носитель языка. diff --git a/documentation/README.zh-CN.md b/documentation/README.zh-CN.md new file mode 100644 index 0000000..c02c869 --- /dev/null +++ b/documentation/README.zh-CN.md @@ -0,0 +1,104 @@ +# AppState + +[![macOS 构建](https://img.shields.io/github/actions/workflow/status/0xLeif/AppState/macOS.yml?label=macOS&branch=main)](https://github.com/0xLeif/AppState/actions/workflows/macOS.yml) +[![Ubuntu 构建](https://img.shields.io/github/actions/workflow/status/0xLeif/AppState/ubuntu.yml?label=Ubuntu&branch=main)](https://github.com/0xLeif/AppState/actions/workflows/ubuntu.yml) +[![Windows 构建](https://img.shields.io/github/actions/workflow/status/0xLeif/AppState/windows.yml?label=Windows&branch=main)](https://github.com/0xLeif/AppState/actions/workflows/windows.yml) +[![许可证](https://img.shields.io/github/license/0xLeif/AppState)](https://github.com/0xLeif/AppState/blob/main/LICENSE) +[![版本](https://img.shields.io/github/v/release/0xLeif/AppState)](https://github.com/0xLeif/AppState/releases) + +**AppState** 是一个 Swift 6 库,旨在以线程安全、类型安全和 SwiftUI 友好的方式简化应用程序状态的管理。它提供了一套工具来集中和同步整个应用程序的状态,并将依赖项注入到应用程序的各个部分。 + +## 要求 + +- **iOS**: 15.0+ +- **watchOS**: 8.0+ +- **macOS**: 11.0+ +- **tvOS**: 15.0+ +- **visionOS**: 1.0+ +- **Swift**: 6.0+ +- **Xcode**: 16.0+ + +**非苹果平台支持**:Linux 和 Windows + +> 🍎 标有此符号的功能是苹果平台特有的,因为它们依赖于 iCloud 和钥匙串等苹果技术。 + +## 主要功能 + +**AppState** 包括几个强大的功能来帮助管理状态和依赖项: + +- **State**:集中式状态管理,允许您封装和广播整个应用程序的更改。 +- **StoredState**:使用 `UserDefaults` 的持久状态,非常适合在应用程序启动之间保存少量数据。 +- **FileState**:使用 `FileManager` 存储的持久状态,用于在磁盘上安全地存储大量数据。 +- 🍎 **SyncState**:使用 iCloud 在多个设备之间同步状态,确保用户偏好和设置的一致性。 +- 🍎 **SecureState**:使用钥匙串安全地存储敏感数据,保护用户信息(如令牌或密码)。 +- **依赖管理**:在整个应用程序中注入网络服务或数据库客户端等依赖项,以实现更好的模块化和测试。 +- **Slicing**:访问状态或依赖项的特定部分以进行精细控制,而无需管理整个应用程序状态。 +- **Constants**:当您需要不可变值时,可以访问状态的只读切片。 +- **Observed Dependencies**:观察 `ObservableObject` 依赖项,以便在它们更改时更新您的视图。 + +## 入门 + +要将 **AppState** 集成到您的 Swift 项目中,您需要使用 Swift 包管理器。有关设置 **AppState** 的详细说明,请遵循[安装指南](zh-CN/installation.md)。 + +安装后,请参阅[用法概述](zh-CN/usage-overview.md),快速了解如何管理状态和将依赖项注入到您的项目中。 + +## 快速示例 + +以下是一个最小示例,展示了如何定义一个状态片段并从 SwiftUI 视图中访问它: + +```swift +import AppState +import SwiftUI + +private extension Application { + var counter: State { + state(initial: 0) + } +} + +struct ContentView: View { + @AppState(\.counter) var counter: Int + + var body: some View { + VStack { + Text("计数: \(counter)") + Button("递增") { counter += 1 } + } + } +} +``` + +此代码片段演示了如何在 `Application` 扩展中定义状态值,并使用 `@AppState` 属性包装器将其绑定到视图中。 + +## 文档 + +以下是 **AppState** 文档的详细分类: + +- [安装指南](zh-CN/installation.md):如何使用 Swift 包管理器将 **AppState** 添加到您的项目中。 +- [用法概述](zh-CN/usage-overview.md):主要功能的概述及示例实现。 + +### 详细用法指南: + +- [状态和依赖管理](zh-CN/usage-state-dependency.md):集中管理状态并在整个应用程序中注入依赖项。 +- [状态切片](zh-CN/usage-slice.md):访问和修改状态的特定部分。 +- [StoredState 用法指南](zh-CN/usage-storedstate.md):如何使用 `StoredState` 持久化轻量级数据。 +- [FileState 用法指南](zh-CN/usage-filestate.md):了解如何安全地在磁盘上持久化大量数据。 +- [钥匙串 SecureState 用法](zh-CN/usage-securestate.md):使用钥匙串安全地存储敏感数据。 +- [使用 SyncState 进行 iCloud 同步](zh-CN/usage-syncstate.md):使用 iCloud 在设备之间保持状态同步。 +- [常见问题解答](zh-CN/faq.md):使用 **AppState** 时常见问题的解答。 +- [常量用法指南](zh-CN/usage-constant.md):从您的状态中访问只读值。 +- [ObservedDependency 用法指南](zh-CN/usage-observeddependency.md):在您的视图中使用 `ObservableObject` 依赖项。 +- [高级用法](zh-CN/advanced-usage.md):诸如即时创建和预加载依赖项等技术。 +- [最佳实践](zh-CN/best-practices.md):有效构建应用程序状态的技巧。 +- [迁移注意事项](zh-CN/migration-considerations.md):更新持久化模型时的指导。 + +## 贡献 + +我们欢迎贡献!请查看我们的[贡献指南](zh-CN/contributing.md)以了解如何参与。 + +## 后续步骤 + +安装 **AppState** 后,您可以通过查看[用法概述](zh-CN/usage-overview.md)和更详细的指南来开始探索其主要功能。开始在您的 Swift 项目中有效地管理状态和依赖项!有关更高级的用法技术,如即时创建和预加载依赖项,请参阅[高级用法指南](zh-CN/advanced-usage.md)。您还可以查看[常量](zh-CN/usage-constant.md)和[ObservedDependency](zh-CN/usage-observeddependency.md)指南以了解其他功能。 + +--- +这是使用 [Jules](https://jules.google) 生成的,可能会出现错误。如果您是母语人士,请提出包含任何应有修复的拉取请求。 diff --git a/documentation/de/advanced-usage.md b/documentation/de/advanced-usage.md new file mode 100644 index 0000000..8f87580 --- /dev/null +++ b/documentation/de/advanced-usage.md @@ -0,0 +1,181 @@ +# Erweiterte Nutzung von AppState + +Dieser Leitfaden behandelt fortgeschrittene Themen zur Verwendung von **AppState**, einschließlich Just-in-Time-Erstellung, Vorladen von Abhängigkeiten, effektive Verwaltung von Zustand und Abhängigkeiten und ein Vergleich von **AppState** mit der **SwiftUI-Umgebung**. + +## 1. Just-in-Time-Erstellung + +AppState-Werte wie `State`, `Dependency`, `StoredState` und `SyncState` werden just-in-time erstellt. Das bedeutet, dass sie erst instanziiert werden, wenn zum ersten Mal auf sie zugegriffen wird, was die Effizienz und Leistung Ihrer Anwendung verbessert. + +### Beispiel + +```swift +extension Application { + var defaultState: State { + state(initial: 0) // Der Wert wird erst erstellt, wenn darauf zugegriffen wird + } +} +``` + +In diesem Beispiel wird `defaultState` erst erstellt, wenn zum ersten Mal darauf zugegriffen wird, was die Ressourcennutzung optimiert. + +## 2. Vorladen von Abhängigkeiten + +In einigen Fällen möchten Sie möglicherweise bestimmte Abhängigkeiten vorladen, um sicherzustellen, dass sie beim Start Ihrer Anwendung verfügbar sind. AppState bietet eine `load`-Funktion, die Abhängigkeiten vorlädt. + +### Beispiel + +```swift +extension Application { + var databaseClient: Dependency { + dependency(DatabaseClient()) + } +} + +// Beim Initialisieren der App vorladen +Application.load(dependency: \.databaseClient) +``` + +In diesem Beispiel wird `databaseClient` während der Initialisierung der App vorgeladen, um sicherzustellen, dass er bei Bedarf in Ihren Ansichten verfügbar ist. + +## 3. Zustands- und Abhängigkeitsverwaltung + +### 3.1 Gemeinsamer Zustand und Abhängigkeiten in der gesamten Anwendung + +Sie können einen gemeinsamen Zustand oder Abhängigkeiten in einem Teil Ihrer App definieren und in einem anderen Teil über eindeutige IDs darauf zugreifen. + +### Beispiel + +```swift +private extension Application { + var stateValue: State { + state(initial: 0, id: "stateValue") + } + + var dependencyValue: Dependency { + dependency(SomeType(), id: "dependencyValue") + } +} +``` + +Dies ermöglicht es Ihnen, auf denselben `State` oder dieselbe `Dependency` an anderer Stelle zuzugreifen, indem Sie dieselbe ID verwenden. + +```swift +private extension Application { + var theSameStateValue: State { + state(initial: 0, id: "stateValue") + } + + var theSameDependencyValue: Dependency { + dependency(SomeType(), id: "dependencyValue") + } +} +``` + +Obwohl dieser Ansatz gültig ist, um Zustand und Abhängigkeiten in der gesamten Anwendung durch Wiederverwendung derselben Zeichenfolgen-`id` zu teilen, wird er im Allgemeinen nicht empfohlen. Er beruht auf der manuellen Verwaltung dieser Zeichenfolgen-IDs, was zu Folgendem führen kann: +- Versehentliche ID-Kollisionen, wenn dieselbe ID für verschiedene beabsichtigte Zustände/Abhängigkeiten verwendet wird. +- Schwierigkeiten bei der Nachverfolgung, wo ein Zustand/eine Abhängigkeit definiert und wo darauf zugegriffen wird. +- Reduzierte Code-Klarheit und Wartbarkeit. +Der in nachfolgenden Definitionen mit derselben ID angegebene `initial`-Wert wird ignoriert, wenn der Zustand/die Abhängigkeit bereits durch den ersten Zugriff initialisiert wurde. Dieses Verhalten ist eher ein Nebeneffekt der ID-basierten Zwischenspeicherung in AppState als ein empfohlenes primäres Muster für die Definition gemeinsamer Daten. Bevorzugen Sie die Definition von Zuständen und Abhängigkeiten als eindeutige berechnete Eigenschaften in `Application`-Erweiterungen (die automatisch eindeutige interne IDs generieren, wenn der Factory-Methode keine explizite `id` übergeben wird). + +### 3.2 Eingeschränkter Zustands- und Abhängigkeitszugriff + +Um den Zugriff einzuschränken, verwenden Sie eine eindeutige ID wie eine UUID, um sicherzustellen, dass nur die richtigen Teile der App auf bestimmte Zustände oder Abhängigkeiten zugreifen können. + +### Beispiel + +```swift +private extension Application { + var restrictedState: State { + state(initial: nil, id: UUID().uuidString) + } + + var restrictedDependency: Dependency { + dependency(SomeType(), id: UUID().uuidString) + } +} +``` + +### 3.3 Eindeutige IDs für Zustände und Abhängigkeiten + +Wenn keine ID angegeben wird, generiert AppState eine Standard-ID basierend auf dem Speicherort im Quellcode. Dadurch wird sichergestellt, dass jeder `State` oder jede `Dependency` eindeutig ist und vor unbeabsichtigtem Zugriff geschützt ist. + +### Beispiel + +```swift +extension Application { + var defaultState: State { + state(initial: 0) // AppState generiert eine eindeutige ID + } + + var defaultDependency: Dependency { + dependency(SomeType()) // AppState generiert eine eindeutige ID + } +} +``` + +### 3.4 Dateiprivater Zustands- und Abhängigkeitszugriff + +Für einen noch stärker eingeschränkten Zugriff innerhalb derselben Swift-Datei verwenden Sie die Zugriffsebene `fileprivate`, um Zustände und Abhängigkeiten vor externem Zugriff zu schützen. + +### Beispiel + +```swift +fileprivate extension Application { + var fileprivateState: State { + state(initial: 0) + } + + var fileprivateDependency: Dependency { + dependency(SomeType()) + } +} +``` + +### 3.5 Verständnis des Speichermechanismus von AppState + +AppState verwendet einen einheitlichen Cache zum Speichern von `State`, `Dependency`, `StoredState` und `SyncState`. Dadurch wird sichergestellt, dass diese Datentypen in Ihrer gesamten App effizient verwaltet werden. + +Standardmäßig weist AppState einen Namenswert als "App" zu, wodurch sichergestellt wird, dass alle mit einem Modul verbundenen Werte an diesen Namen gebunden sind. Dies erschwert den Zugriff auf diese Zustände und Abhängigkeiten von anderen Modulen. + +## 4. AppState vs. SwiftUI-Umgebung + +Sowohl AppState als auch die SwiftUI-Umgebung bieten Möglichkeiten zur Verwaltung von gemeinsamem Zustand und Abhängigkeiten in Ihrer Anwendung, unterscheiden sich jedoch in Umfang, Funktionalität und Anwendungsfällen. + +### 4.1 SwiftUI-Umgebung + +Die SwiftUI-Umgebung ist ein integrierter Mechanismus, mit dem Sie gemeinsame Daten über eine Ansichtshierarchie weitergeben können. Sie ist ideal für die Weitergabe von Daten, auf die viele Ansichten zugreifen müssen, hat aber Einschränkungen bei der Verwaltung komplexerer Zustände. + +**Stärken:** +- Einfach zu bedienen und gut in SwiftUI integriert. +- Ideal für leichtgewichtige Daten, die über mehrere Ansichten in einer Hierarchie geteilt werden müssen. + +**Einschränkungen:** +- Daten sind nur innerhalb der spezifischen Ansichtshierarchie verfügbar. Der Zugriff auf dieselben Daten über verschiedene Ansichtshierarchien hinweg ist ohne zusätzliche Arbeit nicht möglich. +- Weniger Kontrolle über Threadsicherheit und Persistenz im Vergleich zu AppState. +- Fehlende integrierte Persistenz- oder Synchronisierungsmechanismen. + +### 4.2 AppState + +AppState bietet ein leistungsfähigeres und flexibleres System zur Verwaltung von Zustand in der gesamten Anwendung mit Threadsicherheit, Persistenz und Abhängigkeitsinjektionsfunktionen. + +**Stärken:** +- Zentralisierte Zustandsverwaltung, die in der gesamten App zugänglich ist, nicht nur in bestimmten Ansichtshierarchien. +- Integrierte Persistenzmechanismen (`StoredState`, `FileState` und `SyncState`). +- Typ- und Threadsicherheitsgarantien, die sicherstellen, dass der Zustand korrekt abgerufen und geändert wird. +- Kann komplexere Zustands- und Abhängigkeitsverwaltung handhaben. + +**Einschränkungen:** +- Erfordert mehr Einrichtung und Konfiguration im Vergleich zur SwiftUI-Umgebung. +- Etwas weniger integriert mit SwiftUI im Vergleich zur Umgebung, funktioniert aber dennoch gut in SwiftUI-Apps. + +### 4.3 Wann man was verwenden sollte + +- Verwenden Sie die **SwiftUI-Umgebung**, wenn Sie einfache Daten haben, die über eine Ansichtshierarchie geteilt werden müssen, z. B. Benutzereinstellungen oder Designpräferenzen. +- Verwenden Sie **AppState**, wenn Sie eine zentralisierte Zustandsverwaltung, Persistenz oder einen komplexeren Zustand benötigen, auf den in der gesamten App zugegriffen werden muss. + +## Fazit + +Durch die Verwendung dieser fortschrittlichen Techniken wie Just-in-Time-Erstellung, Vorladen, Zustands- und Abhängigkeitsverwaltung und das Verständnis der Unterschiede zwischen AppState und der SwiftUI-Umgebung können Sie mit **AppState** effiziente und ressourcenbewusste Anwendungen erstellen. + +--- +Diese Übersetzung wurde automatisch generiert und kann Fehler enthalten. Wenn Sie Muttersprachler sind, freuen wir uns über Ihre Korrekturvorschläge per Pull Request. diff --git a/documentation/de/best-practices.md b/documentation/de/best-practices.md new file mode 100644 index 0000000..f9c90b6 --- /dev/null +++ b/documentation/de/best-practices.md @@ -0,0 +1,65 @@ +# Best Practices für die Verwendung von AppState + +Dieser Leitfaden enthält Best Practices, die Ihnen helfen, AppState in Ihren Swift-Anwendungen effizient und effektiv zu verwenden. + +## 1. Verwenden Sie AppState sparsam + +AppState ist vielseitig und eignet sich sowohl für die gemeinsame als auch für die lokalisierte Zustandsverwaltung. Es ist ideal für Daten, die über mehrere Komponenten hinweg gemeinsam genutzt, über Ansichten oder Benutzersitzungen hinweg beibehalten oder auf Komponentenebene verwaltet werden müssen. Eine übermäßige Nutzung kann jedoch zu unnötiger Komplexität führen. + +### Empfehlung: +- Verwenden Sie AppState für Daten, die wirklich anwendungsweit sein müssen, über entfernte Komponenten hinweg gemeinsam genutzt werden müssen oder die spezifischen Persistenz-/Synchronisierungsfunktionen von AppState erfordern. +- Für Zustände, die lokal für eine einzelne SwiftUI-Ansicht oder eine enge Hierarchie von Ansichten sind, bevorzugen Sie die integrierten Werkzeuge von SwiftUI wie `@State`, `@StateObject`, `@ObservedObject` oder `@EnvironmentObject`. + +## 2. Halten Sie einen sauberen AppState + +Wenn Ihre Anwendung wächst, kann Ihr AppState an Komplexität zunehmen. Überprüfen und refaktorisieren Sie Ihren AppState regelmäßig, um nicht verwendete Zustände und Abhängigkeiten zu entfernen. Einen sauberen AppState zu halten, macht ihn einfacher zu verstehen, zu warten und zu testen. + +### Empfehlung: +- Überprüfen Sie Ihren AppState regelmäßig auf nicht verwendete oder redundante Zustände und Abhängigkeiten. +- Refaktorisieren Sie große AppState-Strukturen, um sie sauber und überschaubar zu halten. + +## 3. Testen Sie Ihren AppState + +Stellen Sie wie bei anderen Aspekten Ihrer Anwendung sicher, dass Ihr AppState gründlich getestet wird. Verwenden Sie Mock-Abhängigkeiten, um Ihren AppState während des Testens von externen Abhängigkeiten zu isolieren, und bestätigen Sie, dass sich jeder Teil Ihrer Anwendung wie erwartet verhält. + +### Empfehlung: +- Verwenden Sie XCTest oder ähnliche Frameworks, um das Verhalten und die Interaktionen von AppState zu testen. +- Mocken oder stubben Sie Abhängigkeiten, um sicherzustellen, dass AppState-Tests isoliert und zuverlässig sind. + +## 4. Verwenden Sie das Slice-Feature mit Bedacht + +Das `Slice`-Feature ermöglicht es Ihnen, auf bestimmte Teile des Zustands eines AppState zuzugreifen, was für die Handhabung großer und komplexer Zustandsstrukturen nützlich ist. Verwenden Sie diese Funktion jedoch mit Bedacht, um einen sauberen und gut organisierten AppState beizubehalten und unnötige Slices zu vermeiden, die die Zustandsbehandlung fragmentieren. + +### Empfehlung: +- Verwenden Sie `Slice` nur für große oder verschachtelte Zustände, bei denen der Zugriff auf einzelne Komponenten erforderlich ist. +- Vermeiden Sie ein übermäßiges Slicing des Zustands, was zu Verwirrung und einer fragmentierten Zustandsverwaltung führen kann. + +## 5. Verwenden Sie Konstanten für statische Werte + +Die `@Constant`-Funktion ermöglicht es Ihnen, schreibgeschützte Konstanten zu definieren, die in Ihrer gesamten Anwendung gemeinsam genutzt werden können. Sie ist nützlich für Werte, die während des gesamten Lebenszyklus Ihrer App unverändert bleiben, wie z. B. Konfigurationseinstellungen oder vordefinierte Daten. Konstanten stellen sicher, dass diese Werte nicht unbeabsichtigt geändert werden. + +### Empfehlung: +- Verwenden Sie `@Constant` für Werte, die unverändert bleiben, wie z. B. App-Konfigurationen, Umgebungsvariablen oder statische Referenzen. + +## 6. Modularisieren Sie Ihren AppState + +Für größere Anwendungen sollten Sie in Betracht ziehen, Ihren AppState in kleinere, besser verwaltbare Module aufzuteilen. Jedes Modul kann seinen eigenen Zustand und seine eigenen Abhängigkeiten haben, die dann in den Gesamt-AppState integriert werden. Dies kann Ihren AppState leichter verständlich, testbar und wartbar machen. + +### Empfehlung: +- Organisieren Sie Ihre `Application`-Erweiterungen in separaten Swift-Dateien oder sogar in separaten Swift-Modulen, die nach Funktion oder Domäne gruppiert sind. Dies modularisiert die Definitionen auf natürliche Weise. +- Wenn Sie Zustände oder Abhängigkeiten mit Factory-Methoden wie `state(initial:feature:id:)` definieren, verwenden Sie den `feature`-Parameter, um einen Namespace bereitzustellen, z. B. `state(initial: 0, feature: "UserProfile", id: "score")`. Dies hilft bei der Organisation und Vermeidung von ID-Kollisionen, wenn manuelle IDs verwendet werden. +- Vermeiden Sie die Erstellung mehrerer Instanzen von `Application`. Halten Sie sich an die Erweiterung und Verwendung des gemeinsam genutzten Singletons (`Application.shared`). + +## 7. Nutzen Sie die Just-in-Time-Erstellung + +AppState-Werte werden just-in-time erstellt, d. h. sie werden erst instanziiert, wenn auf sie zugegriffen wird. Dies optimiert die Speichernutzung und stellt sicher, dass AppState-Werte nur bei Bedarf erstellt werden. + +### Empfehlung: +- Erlauben Sie, dass AppState-Werte just-in-time erstellt werden, anstatt alle Zustände und Abhängigkeiten unnötig vorab zu laden. + +## Fazit + +Jede Anwendung ist einzigartig, daher passen diese Best Practices möglicherweise nicht in jede Situation. Berücksichtigen Sie immer die spezifischen Anforderungen Ihrer Anwendung, wenn Sie entscheiden, wie Sie AppState verwenden, und bemühen Sie sich, Ihre Zustandsverwaltung sauber, effizient und gut getestet zu halten. + +--- +Diese Übersetzung wurde automatisch generiert und kann Fehler enthalten. Wenn Sie Muttersprachler sind, freuen wir uns über Ihre Korrekturvorschläge per Pull Request. diff --git a/documentation/de/contributing.md b/documentation/de/contributing.md new file mode 100644 index 0000000..76d51a0 --- /dev/null +++ b/documentation/de/contributing.md @@ -0,0 +1,63 @@ +# Zu AppState beitragen + +Vielen Dank, dass Sie in Betracht ziehen, zu **AppState** beizutragen! Ihre Beiträge helfen, dieses Projekt für alle besser zu machen. + +## Wie man beitragen kann + +### 1. Fehler melden + +Wenn Sie auf Fehler stoßen, öffnen Sie bitte ein Issue auf GitHub. Wenn Sie einen Fehler melden, geben Sie bitte Folgendes an: + +- Einen klaren und beschreibenden Titel. +- Eine detaillierte Beschreibung des Fehlers, einschließlich der Schritte, um ihn zu reproduzieren. +- Das erwartete Verhalten und was tatsächlich passiert ist. +- Die Version von **AppState**, die Sie verwenden. +- Alle relevanten Screenshots oder Protokolle. + +### 2. Funktionen vorschlagen + +Neue Ideen sind willkommen! Wenn Sie eine Funktion haben, die Sie gerne in **AppState** sehen würden, öffnen Sie bitte ein Issue und beschreiben Sie: + +- Das Problem, das die Funktion lösen würde. +- Wie Sie denken, dass die Funktion funktionieren sollte. +- Jeder zusätzliche Kontext oder Beispiele, die helfen würden, Ihre Idee zu veranschaulichen. + +### 3. Pull Requests einreichen + +Wenn Sie Code zu **AppState** beitragen möchten, befolgen Sie diese Schritte: + +1. **Das Repository forken**: Erstellen Sie einen persönlichen Fork des **AppState**-Repositorys auf GitHub. +2. **Ihren Fork klonen**: Klonen Sie Ihren Fork auf Ihren lokalen Computer: + ```bash + git clone https://github.com/your-username/AppState.git + ``` +3. **Einen neuen Branch erstellen**: Erstellen Sie einen neuen Branch für Ihre Funktion oder Fehlerbehebung: + ```bash + git checkout -b mein-feature-branch + ``` +4. **Änderungen vornehmen**: Implementieren Sie Ihre Änderungen im neuen Branch. +5. **Ihre Änderungen testen**: Stellen Sie sicher, dass Ihre Änderungen alle Tests bestehen. Fügen Sie bei Bedarf neue Tests hinzu. +6. **Ihre Änderungen committen**: Committen Sie Ihre Änderungen mit einer beschreibenden Commit-Nachricht: + ```bash + git commit -m "Meine neue Funktion hinzufügen" + ``` +7. **Auf GitHub pushen**: Pushen Sie Ihren Branch zu Ihrem GitHub-Fork: + ```bash + git push origin mein-feature-branch + ``` +8. **Einen Pull-Request erstellen**: Gehen Sie zum **AppState**-Repository auf GitHub und erstellen Sie einen Pull-Request aus Ihrem Branch. + +### 4. Code-Stil + +Bitte befolgen Sie die im **AppState**-Projekt verwendeten Richtlinien für den Codierungsstil. Ein einheitlicher Code-Stil trägt dazu bei, die Codebasis wartbarer und leichter überprüfbar zu machen. + +### 5. Lizenz + +Indem Sie zu **AppState** beitragen, stimmen Sie zu, dass Ihre Beiträge unter derselben Lizenz wie das Projekt lizenziert werden: [LIZENZ](https://github.com/0xLeif/AppState/blob/main/LICENSE). + +## Vielen Dank! + +Ihre Beiträge werden sehr geschätzt und gewürdigt. Vielen Dank, dass Sie zur Verbesserung von **AppState** beitragen! + +--- +Diese Übersetzung wurde automatisch generiert und kann Fehler enthalten. Wenn Sie Muttersprachler sind, freuen wir uns über Ihre Korrekturvorschläge per Pull Request. diff --git a/documentation/de/faq.md b/documentation/de/faq.md new file mode 100644 index 0000000..ea8d2af --- /dev/null +++ b/documentation/de/faq.md @@ -0,0 +1,43 @@ +# Häufig gestellte Fragen + +Diese kurze FAQ beantwortet häufig gestellte Fragen, die Entwickler bei der Verwendung von **AppState** haben können. + +## Wie setze ich einen Zustandswert zurück? + +Für persistente Zustände wie `StoredState`, `FileState` und `SyncState` können Sie sie auf ihre Anfangswerte zurücksetzen, indem Sie die statischen `reset`-Funktionen für den `Application`-Typ verwenden. + +Um beispielsweise einen `StoredState` zurückzusetzen: +```swift +extension Application { + var hasCompletedOnboarding: StoredState { storedState(initial: false, id: "onboarding_complete") } +} + +// Irgendwo in Ihrem Code +Application.reset(storedState: \.hasCompletedOnboarding) +``` +Dadurch wird der Wert in `UserDefaults` auf `false` zurückgesetzt. Ähnliche `reset`-Funktionen gibt es für `FileState`, `SyncState` und `SecureState`. + +Für einen nicht-persistenten `State` können Sie ihn auf die gleiche Weise wie persistente Zustände zurücksetzen: +```swift +extension Application { + var counter: State { state(initial: 0) } +} + +// Irgendwo in Ihrem Code +Application.reset(\.counter) +``` + +## Kann ich AppState mit asynchronen Aufgaben verwenden? + +Ja. `State`- und Abhängigkeitswerte sind threadsicher und funktionieren nahtlos mit Swift Concurrency. Sie können sie innerhalb von `async`-Funktionen ohne zusätzliche Sperren aufrufen und ändern. + +## Wo sollte ich Zustände und Abhängigkeiten definieren? + +Bewahren Sie alle Ihre Zustände und Abhängigkeiten in `Application`-Erweiterungen auf. Dies gewährleistet eine einzige Quelle der Wahrheit und erleichtert das Auffinden aller verfügbaren Werte. + +## Ist AppState mit Combine kompatibel? + +Sie können AppState zusammen mit Combine verwenden, indem Sie `State`-Änderungen an Publisher überbrücken. Beobachten Sie einen `State`-Wert und senden Sie bei Bedarf Aktualisierungen über einen `PassthroughSubject` oder einen anderen Combine-Publisher. + +--- +Diese Übersetzung wurde automatisch generiert und kann Fehler enthalten. Wenn Sie Muttersprachler sind, freuen wir uns über Ihre Korrekturvorschläge per Pull Request. diff --git a/documentation/de/installation.md b/documentation/de/installation.md new file mode 100644 index 0000000..48c6127 --- /dev/null +++ b/documentation/de/installation.md @@ -0,0 +1,87 @@ +# Installationsanleitung + +Diese Anleitung führt Sie durch den Prozess der Installation von **AppState** in Ihr Swift-Projekt mit dem Swift Package Manager. + +## Swift Package Manager + +**AppState** kann einfach mit dem Swift Package Manager in Ihr Projekt integriert werden. Befolgen Sie die folgenden Schritte, um **AppState** als Abhängigkeit hinzuzufügen. + +### Schritt 1: Aktualisieren Sie Ihre `Package.swift`-Datei + +Fügen Sie **AppState** zum `dependencies`-Abschnitt Ihrer `Package.swift`-Datei hinzu: + +```swift +dependencies: [ + .package(url: "https://github.com/0xLeif/AppState.git", from: "2.2.0") +] +``` + +### Schritt 2: Fügen Sie AppState zu Ihrem Ziel hinzu + +Schließen Sie AppState in die Abhängigkeiten Ihres Ziels ein: + +```swift +.target( + name: "YourTarget", + dependencies: ["AppState"] +) +``` + +### Schritt 3: Erstellen Sie Ihr Projekt + +Nachdem Sie AppState zu Ihrer `Package.swift`-Datei hinzugefügt haben, erstellen Sie Ihr Projekt, um die Abhängigkeit abzurufen und in Ihre Codebasis zu integrieren. + +``` +swift build +``` + +### Schritt 4: Importieren Sie AppState in Ihren Code + +Jetzt können Sie AppState in Ihrem Projekt verwenden, indem Sie es am Anfang Ihrer Swift-Dateien importieren: + +```swift +import AppState +``` + +## Xcode + +Wenn Sie **AppState** lieber direkt über Xcode hinzufügen möchten, befolgen Sie diese Schritte: + +### Schritt 1: Öffnen Sie Ihr Xcode-Projekt + +Öffnen Sie Ihr Xcode-Projekt oder Ihren Arbeitsbereich. + +### Schritt 2: Fügen Sie eine Swift-Paketabhängigkeit hinzu + +1. Navigieren Sie zum Projektnavigator und wählen Sie Ihre Projektdatei aus. +2. Wählen Sie im Projekteditor Ihr Ziel aus und gehen Sie dann zum Tab "Swift Packages". +3. Klicken Sie auf die Schaltfläche "+", um eine Paketabhängigkeit hinzuzufügen. + +### Schritt 3: Geben Sie die Repository-URL ein + +Geben Sie im Dialogfeld "Choose Package Repository" die folgende URL ein: `https://github.com/0xLeif/AppState.git` + +Klicken Sie dann auf "Weiter". + +### Schritt 4: Geben Sie die Version an + +Wählen Sie die Version aus, die Sie verwenden möchten. Es wird empfohlen, die Option "Bis zur nächsten Hauptversion" auszuwählen und `2.0.0` als Untergrenze anzugeben. Klicken Sie dann auf "Weiter". + +### Schritt 5: Fügen Sie das Paket hinzu + +Xcode ruft das Paket ab und bietet Ihnen Optionen zum Hinzufügen von **AppState** zu Ihrem Ziel an. Stellen Sie sicher, dass Sie das richtige Ziel auswählen, und klicken Sie auf "Fertig stellen". + +### Schritt 6: Importieren Sie `AppState` in Ihren Code + +Sie können **AppState** jetzt am Anfang Ihrer Swift-Dateien importieren: + +```swift +import AppState +``` + +## Nächste Schritte + +Nach der Installation von AppState können Sie zur [Verwendungsübersicht](usage-overview.md) übergehen, um zu sehen, wie Sie die wichtigsten Funktionen in Ihrem Projekt implementieren. + +--- +Diese Übersetzung wurde automatisch generiert und kann Fehler enthalten. Wenn Sie Muttersprachler sind, freuen wir uns über Ihre Korrekturvorschläge per Pull Request. diff --git a/documentation/de/migration-considerations.md b/documentation/de/migration-considerations.md new file mode 100644 index 0000000..af3046f --- /dev/null +++ b/documentation/de/migration-considerations.md @@ -0,0 +1,81 @@ +# Überlegungen zur Migration + +Bei der Aktualisierung Ihres Datenmodells, insbesondere bei persistenten oder synchronisierten Daten, müssen Sie die Abwärtskompatibilität berücksichtigen, um potenzielle Probleme beim Laden älterer Daten zu vermeiden. Hier sind einige wichtige Punkte, die Sie beachten sollten: + +## 1. Hinzufügen von nicht-optionalen Feldern +Wenn Sie Ihrem Modell neue, nicht-optionale Felder hinzufügen, kann die Dekodierung alter Daten (die diese Felder nicht enthalten) fehlschlagen. Um dies zu vermeiden: +- Erwägen Sie, neuen Feldern Standardwerte zu geben. +- Machen Sie die neuen Felder optional, um die Kompatibilität mit älteren Versionen Ihrer App zu gewährleisten. + +### Beispiel: +```swift +struct Settings: Codable { + var text: String + var isDarkMode: Bool + var newField: String? // Neues Feld ist optional +} +``` + +## 2. Änderungen am Datenformat +Wenn Sie die Struktur eines Modells ändern (z. B. einen Typ von `Int` in `String` ändern), kann der Dekodierungsprozess beim Lesen älterer Daten fehlschlagen. Planen Sie eine reibungslose Migration durch: +- Erstellen einer Migrationslogik, um alte Datenformate in die neue Struktur zu konvertieren. +- Verwendung des benutzerdefinierten Initialisierers von `Decodable`, um alte Daten zu verarbeiten und sie Ihrem neuen Modell zuzuordnen. + +### Beispiel: +```swift +struct Settings: Codable { + var text: String + var isDarkMode: Bool + var version: Int + + // Benutzerdefinierte Dekodierungslogik für ältere Versionen + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.text = try container.decode(String.self, forKey: .text) + self.isDarkMode = try container.decode(Bool.self, forKey: .isDarkMode) + self.version = (try? container.decode(Int.self, forKey: .version)) ?? 1 // Standard für ältere Daten + } +} +``` + +## 3. Umgang mit gelöschten oder veralteten Feldern +Wenn Sie ein Feld aus dem Modell entfernen, stellen Sie sicher, dass alte Versionen der App die neuen Daten immer noch ohne Absturz dekodieren können. Sie können: +- Zusätzliche Felder beim Dekodieren ignorieren. +- Benutzerdefinierte Dekoder verwenden, um alte Daten zu verarbeiten und veraltete Felder ordnungsgemäß zu verwalten. + +## 4. Versionierung Ihrer Modelle + +Die Versionierung Ihrer Modelle ermöglicht es Ihnen, Änderungen an Ihrer Datenstruktur im Laufe der Zeit zu handhaben. Indem Sie eine Versionsnummer als Teil Ihres Modells beibehalten, können Sie einfach eine Migrationslogik implementieren, um ältere Datenformate in neuere zu konvertieren. Dieser Ansatz stellt sicher, dass Ihre App ältere Datenstrukturen verarbeiten und gleichzeitig reibungslos auf neue Versionen umsteigen kann. + +- **Warum Versionierung wichtig ist**: Wenn Benutzer ihre App aktualisieren, haben sie möglicherweise noch ältere Daten auf ihren Geräten gespeichert. Die Versionierung hilft Ihrer App, das Datenformat zu erkennen und die richtige Migrationslogik anzuwenden. +- **Wie zu verwenden**: Fügen Sie Ihrem Modell ein `version`-Feld hinzu und überprüfen Sie es während des Dekodierungsprozesses, um festzustellen, ob eine Migration erforderlich ist. + +### Beispiel: +```swift +struct Settings: Codable { + var version: Int + var text: String + var isDarkMode: Bool + + // Handhaben der versionsspezifischen Dekodierungslogik + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.version = try container.decode(Int.self, forKey: .version) + self.text = try container.decode(String.self, forKey: .text) + self.isDarkMode = try container.decode(Bool.self, forKey: .isDarkMode) + + // Wenn von einer älteren Version migriert wird, wenden Sie hier die erforderlichen Transformationen an + if version < 2 { + // Migrieren Sie ältere Daten in das neuere Format + } + } +} +``` + +- **Beste Vorgehensweise**: Beginnen Sie von Anfang an mit einem `version`-Feld. Jedes Mal, wenn Sie Ihre Modellstruktur aktualisieren, erhöhen Sie die Version und behandeln die erforderliche Migrationslogik. + +## 5. Testen der Migration +Testen Sie Ihre Migration immer gründlich, indem Sie das Laden alter Daten mit neuen Versionen Ihres Modells simulieren, um sicherzustellen, dass sich Ihre App wie erwartet verhält. + +--- +Diese Übersetzung wurde automatisch generiert und kann Fehler enthalten. Wenn Sie Muttersprachler sind, freuen wir uns über Ihre Korrekturvorschläge per Pull Request. diff --git a/documentation/de/starting-to-use-syncstate.md b/documentation/de/starting-to-use-syncstate.md new file mode 100644 index 0000000..1fd7a9c --- /dev/null +++ b/documentation/de/starting-to-use-syncstate.md @@ -0,0 +1,25 @@ +Um SyncState zu nutzen, müssen Sie zuerst die iCloud-Fähigkeiten und -Berechtigungen in Ihrem Xcode-Projekt einrichten. Hier ist eine Einführung, die Sie durch den Prozess führt: + +### Einrichten der iCloud-Fähigkeiten: + +1. Öffnen Sie Ihr Xcode-Projekt und passen Sie die Bundle-Identifikatoren für die macOS- und iOS-Ziele an Ihre eigenen an. +2. Als Nächstes müssen Sie die iCloud-Fähigkeit zu Ihrem Projekt hinzufügen. Wählen Sie dazu Ihr Projekt im Projektnavigator aus und wählen Sie dann Ihr Ziel aus. Klicken Sie in der Tab-Leiste oben im Editorbereich auf "Signing & Capabilities". +3. Aktivieren Sie im Bereich "Capabilities" iCloud, indem Sie auf den Schalter in der iCloud-Zeile klicken. Sie sollten sehen, wie sich der Schalter in die Ein-Position bewegt. +4. Sobald Sie iCloud aktiviert haben, müssen Sie den Schlüssel-Wert-Speicher aktivieren. Dies können Sie tun, indem Sie das Kontrollkästchen "Key-Value storage" aktivieren. + +### Aktualisieren der Berechtigungen: + +1. Sie müssen nun Ihre Berechtigungsdatei aktualisieren. Öffnen Sie die Berechtigungsdatei für Ihr Ziel. +2. Stellen Sie sicher, dass der Wert des iCloud-Schlüssel-Wert-Speichers mit Ihrer eindeutigen Schlüssel-Wert-Speicher-ID übereinstimmt. Ihre eindeutige ID sollte dem Format `$(TeamIdentifierPrefix)` folgen. Der Standardwert sollte etwa `$(TeamIdentifierPrefix)$(CFBundleIdentifier)` lauten. Dies ist für Einzelplattform-Apps in Ordnung, aber wenn Ihre App auf mehreren Apple-Betriebssystemen läuft, ist es wichtig, dass die Teile der Schlüssel-Wert-Speicher-ID für beide Ziele gleich sind. + +### Konfigurieren der Geräte: + +Zusätzlich zur Konfiguration des Projekts selbst müssen Sie auch die Geräte vorbereiten, auf denen das Projekt ausgeführt wird. + +- Stellen Sie sicher, dass iCloud Drive sowohl auf iOS- als auch auf macOS-Geräten aktiviert ist. +- Melden Sie sich auf beiden Geräten mit demselben iCloud-Konto an. + +Wenn Sie Fragen haben oder auf Probleme stoßen, können Sie sich gerne an uns wenden oder ein Problem melden. + +--- +Diese Übersetzung wurde automatisch generiert und kann Fehler enthalten. Wenn Sie Muttersprachler sind, freuen wir uns über Ihre Korrekturvorschläge per Pull Request. diff --git a/documentation/de/syncstate-implementation.md b/documentation/de/syncstate-implementation.md new file mode 100644 index 0000000..40d567e --- /dev/null +++ b/documentation/de/syncstate-implementation.md @@ -0,0 +1,84 @@ +# SyncState-Implementierung in AppState + +Dieser Leitfaden beschreibt, wie Sie SyncState in Ihrer Anwendung einrichten und konfigurieren, einschließlich der Einrichtung von iCloud-Funktionen und des Verständnisses potenzieller Einschränkungen. + +## 1. Einrichten der iCloud-Funktionen + +Um SyncState in Ihrer Anwendung zu verwenden, müssen Sie zuerst iCloud in Ihrem Projekt aktivieren und den Schlüssel-Wert-Speicher konfigurieren. + +### Schritte zum Aktivieren von iCloud und des Schlüssel-Wert-Speichers: + +1. Öffnen Sie Ihr Xcode-Projekt und navigieren Sie zu Ihren Projekteinstellungen. +2. Wählen Sie unter dem Tab "Signing & Capabilities" Ihr Ziel (iOS oder macOS) aus. +3. Klicken Sie auf die Schaltfläche "+ Capability" und wählen Sie "iCloud" aus der Liste. +4. Aktivieren Sie die Option "Key-Value storage" unter den iCloud-Einstellungen. Dadurch kann Ihre App kleine Datenmengen mithilfe von iCloud speichern und synchronisieren. + +### Konfiguration der Entitlements-Datei: + +1. Suchen oder erstellen Sie in Ihrem Xcode-Projekt die **Entitlements-Datei** für Ihre App. +2. Stellen Sie sicher, dass der iCloud-Schlüssel-Wert-Speicher in der Entitlements-Datei mit dem richtigen iCloud-Container korrekt eingerichtet ist. + +Beispiel in der Entitlements-Datei: + +```xml +com.apple.developer.ubiquity-kvstore-identifier +$(TeamIdentifierPrefix)com.yourdomain.app +``` + +Stellen Sie sicher, dass der Zeichenfolgenwert mit dem mit Ihrem Projekt verknüpften iCloud-Container übereinstimmt. + +## 2. Verwendung von SyncState in Ihrer Anwendung + +Sobald iCloud aktiviert ist, können Sie `SyncState` in Ihrer Anwendung verwenden, um Daten über Geräte hinweg zu synchronisieren. + +### Beispiel für die Verwendung von SyncState: + +```swift +import AppState +import SwiftUI + +extension Application { + var syncValue: SyncState { + syncState(id: "syncValue") + } +} + +struct ContentView: View { + @SyncState(\.syncValue) private var syncValue: Int? + + var body: some View { + VStack { + if let syncValue = syncValue { + Text("SyncValue: \(syncValue)") + } else { + Text("No SyncValue") + } + + Button("Update SyncValue") { + syncValue = Int.random(in: 0..<100) + } + } + } +} +``` + +In diesem Beispiel wird der Synchronisierungszustand in iCloud gespeichert und auf allen Geräten synchronisiert, die mit demselben iCloud-Konto angemeldet sind. + +## 3. Einschränkungen und bewährte Verfahren + +SyncState verwendet `NSUbiquitousKeyValueStore`, das einige Einschränkungen aufweist: + +- **Speicherlimit**: SyncState ist für kleine Datenmengen ausgelegt. Das Gesamtspeicherlimit beträgt 1 MB, und jedes Schlüssel-Wert-Paar ist auf etwa 1 MB begrenzt. +- **Synchronisierung**: Änderungen am SyncState werden nicht sofort auf allen Geräten synchronisiert. Es kann zu einer leichten Verzögerung bei der Synchronisierung kommen, und die iCloud-Synchronisierung kann gelegentlich durch Netzwerkbedingungen beeinträchtigt werden. + +### Bewährte Verfahren: + +- **Verwenden Sie SyncState für kleine Daten**: Stellen Sie sicher, dass nur kleine Daten wie Benutzereinstellungen oder Einstellungen mit SyncState synchronisiert werden. +- **Behandeln Sie SyncState-Fehler ordnungsgemäß**: Verwenden Sie Standardwerte oder Fehlerbehandlungsmechanismen, um potenzielle Synchronisierungsverzögerungen oder -fehler zu berücksichtigen. + +## 4. Fazit + +Indem Sie iCloud ordnungsgemäß konfigurieren und die Einschränkungen von SyncState verstehen, können Sie dessen Leistungsfähigkeit nutzen, um Daten über Geräte hinweg zu synchronisieren. Stellen Sie sicher, dass Sie SyncState nur für kleine, kritische Daten verwenden, um potenzielle Probleme mit den iCloud-Speicherlimits zu vermeiden. + +--- +Diese Übersetzung wurde automatisch generiert und kann Fehler enthalten. Wenn Sie Muttersprachler sind, freuen wir uns über Ihre Korrekturvorschläge per Pull Request. diff --git a/documentation/de/usage-constant.md b/documentation/de/usage-constant.md new file mode 100644 index 0000000..03eef7f --- /dev/null +++ b/documentation/de/usage-constant.md @@ -0,0 +1,87 @@ +# Verwendung von Konstanten + +`Constant` in der **AppState**-Bibliothek bietet schreibgeschützten Zugriff auf Werte im Zustand Ihrer Anwendung. Es funktioniert ähnlich wie `Slice`, stellt jedoch sicher, dass die zugegriffenen Werte unveränderlich sind. Dies macht `Constant` ideal für den Zugriff auf Werte, die andernfalls veränderbar sein könnten, aber in bestimmten Kontexten schreibgeschützt bleiben sollen. + +## Hauptmerkmale + +- **Schreibgeschützter Zugriff**: Konstanten bieten Zugriff auf veränderbare Zustände, aber die Werte können nicht geändert werden. +- **Auf die Anwendung beschränkt**: Wie `Slice` wird `Constant` innerhalb der `Application`-Erweiterung definiert und ist auf den Zugriff auf bestimmte Teile des Zustands beschränkt. +- **Threadsicher**: `Constant` gewährleistet einen sicheren Zugriff auf den Zustand in nebenläufigen Umgebungen. + +## Anwendungsbeispiel + +### Definieren einer Konstante in der Anwendung + +So definieren Sie eine `Constant` in der `Application`-Erweiterung, um auf einen schreibgeschützten Wert zuzugreifen: + +```swift +import AppState +import SwiftUI + +struct ExampleValue { + var username: String? + var isLoading: Bool + let value: String + var mutableValue: String +} + +extension Application { + var exampleValue: State { + state( + initial: ExampleValue( + username: "Leif", + isLoading: false, + value: "value", + mutableValue: "" + ) + ) + } +} +``` + +### Zugriff auf die Konstante in einer SwiftUI-Ansicht + +In einer SwiftUI-Ansicht können Sie den `@Constant`-Property-Wrapper verwenden, um auf den konstanten Zustand schreibgeschützt zuzugreifen: + +```swift +import AppState +import SwiftUI + +struct ExampleView: View { + @Constant(\.exampleValue, \.value) var constantValue: String + + var body: some View { + Text("Konstanter Wert: \(constantValue)") + } +} +``` + +### Schreibgeschützter Zugriff auf veränderbaren Zustand + +Auch wenn der Wert an anderer Stelle veränderbar ist, wird der Wert bei Zugriff über `@Constant` unveränderlich: + +```swift +import AppState +import SwiftUI + +struct ExampleView: View { + @Constant(\.exampleValue, \.mutableValue) var constantMutableValue: String + + var body: some View { + Text("Schreibgeschützter veränderbarer Wert: \(constantMutableValue)") + } +} +``` + +## Bewährte Praktiken + +- **Verwendung für schreibgeschützten Zugriff**: Verwenden Sie `Constant`, um auf Teile des Zustands zuzugreifen, die in bestimmten Kontexten nicht geändert werden sollen, auch wenn sie an anderer Stelle veränderbar sind. +- **Threadsicher**: Wie andere AppState-Komponenten gewährleistet `Constant` einen threadsicheren Zugriff auf den Zustand. +- **Verwenden Sie `OptionalConstant` für optionale Werte**: Wenn der Teil des Zustands, auf den Sie zugreifen, `nil` sein kann, verwenden Sie `OptionalConstant`, um das Fehlen eines Werts sicher zu behandeln. + +## Fazit + +`Constant` und `OptionalConstant` bieten eine effiziente Möglichkeit, auf bestimmte Teile des Zustands Ihrer App schreibgeschützt zuzugreifen. Sie stellen sicher, dass Werte, die andernfalls veränderbar sein könnten, bei Zugriff innerhalb einer Ansicht als unveränderlich behandelt werden, was Sicherheit und Klarheit in Ihrem Code gewährleistet. + +--- +Diese Übersetzung wurde automatisch generiert und kann Fehler enthalten. Wenn Sie Muttersprachler sind, freuen wir uns über Ihre Korrekturvorschläge per Pull Request. diff --git a/documentation/de/usage-filestate.md b/documentation/de/usage-filestate.md new file mode 100644 index 0000000..2aeda2f --- /dev/null +++ b/documentation/de/usage-filestate.md @@ -0,0 +1,96 @@ +# Verwendung von FileState + +`FileState` ist eine Komponente der **AppState**-Bibliothek, mit der Sie persistente Daten mithilfe des Dateisystems speichern und abrufen können. Es ist nützlich zum Speichern großer Datenmengen oder komplexer Objekte, die zwischen App-Starts gespeichert und bei Bedarf wiederhergestellt werden müssen. + +## Hauptmerkmale + +- **Persistenter Speicher**: Mit `FileState` gespeicherte Daten bleiben über App-Starts hinweg erhalten. +- **Umgang mit großen Datenmengen**: Im Gegensatz zu `StoredState` ist `FileState` ideal für den Umgang mit größeren oder komplexeren Daten. +- **Threadsicher**: Wie andere AppState-Komponenten gewährleistet `FileState` einen sicheren Zugriff auf die Daten in nebenläufigen Umgebungen. + +## Anwendungsbeispiel + +### Speichern und Abrufen von Daten mit FileState + +So definieren Sie einen `FileState` in der `Application`-Erweiterung, um ein großes Objekt zu speichern und abzurufen: + +```swift +import AppState +import SwiftUI + +struct UserProfile: Codable { + var name: String + var age: Int +} + +extension Application { + @MainActor + var userProfile: FileState { + fileState(initial: UserProfile(name: "Guest", age: 25), filename: "userProfile") + } +} + +struct FileStateExampleView: View { + @FileState(\.userProfile) var userProfile: UserProfile + + var body: some View { + VStack { + Text("Name: \(userProfile.name), Alter: \(userProfile.age)") + Button("Profil aktualisieren") { + userProfile = UserProfile(name: "UpdatedName", age: 30) + } + } + } +} +``` + +### Umgang mit großen Datenmengen mit FileState + +Wenn Sie mit größeren Datensätzen oder Objekten arbeiten müssen, stellt `FileState` sicher, dass die Daten effizient im Dateisystem der App gespeichert werden. Dies ist nützlich für Szenarien wie Caching oder Offline-Speicherung. + +```swift +import AppState +import SwiftUI + +extension Application { + @MainActor + var largeDataset: FileState<[String]> { + fileState(initial: [], filename: "largeDataset") + } +} + +struct LargeDataView: View { + @FileState(\.largeDataset) var largeDataset: [String] + + var body: some View { + List(largeDataset, id: \.self) { item in + Text(item) + } + } +} +``` + +### Überlegungen zur Migration + +Bei der Aktualisierung Ihres Datenmodells ist es wichtig, potenzielle Migrationsherausforderungen zu berücksichtigen, insbesondere bei der Arbeit mit persistenten Daten mit **StoredState**, **FileState** oder **SyncState**. Ohne eine ordnungsgemäße Migrationsbehandlung können Änderungen wie das Hinzufügen neuer Felder oder das Ändern von Datenformaten Probleme beim Laden älterer Daten verursachen. + +Hier sind einige wichtige Punkte, die Sie beachten sollten: +- **Hinzufügen neuer nicht optionaler Felder**: Stellen Sie sicher, dass neue Felder entweder optional sind oder Standardwerte haben, um die Abwärtskompatibilität zu gewährleisten. +- **Umgang mit Änderungen des Datenformats**: Wenn sich die Struktur Ihres Modells ändert, implementieren Sie eine benutzerdefinierte Dekodierungslogik, um alte Formate zu unterstützen. +- **Versionierung Ihrer Modelle**: Verwenden Sie ein `version`-Feld in Ihren Modellen, um bei Migrationen zu helfen und Logik basierend auf der Datenversion anzuwenden. + +Weitere Informationen zur Verwaltung von Migrationen und zur Vermeidung potenzieller Probleme finden Sie im [Leitfaden zu Migrationsüberlegungen](migration-considerations.md). + + +## Bewährte Praktiken + +- **Verwendung für große oder komplexe Daten**: Wenn Sie große Datenmengen oder komplexe Objekte speichern, ist `FileState` `StoredState` vorzuziehen. +- **Threadsicherer Zugriff**: Wie andere Komponenten von **AppState** stellt `FileState` sicher, dass auf Daten sicher zugegriffen wird, auch wenn mehrere Aufgaben mit den gespeicherten Daten interagieren. +- **Kombinieren mit Codable**: Stellen Sie bei der Arbeit mit benutzerdefinierten Datentypen sicher, dass diese `Codable` entsprechen, um die Kodierung und Dekodierung in und aus dem Dateisystem zu vereinfachen. + +## Fazit + +`FileState` ist ein leistungsstarkes Werkzeug für den Umgang mit persistenten Daten in Ihrer App, mit dem Sie größere oder komplexere Objekte auf threadsichere und persistente Weise speichern und abrufen können. Es arbeitet nahtlos mit dem `Codable`-Protokoll von Swift zusammen und stellt sicher, dass Ihre Daten für die langfristige Speicherung einfach serialisiert und deserialisiert werden können. + +--- +Diese Übersetzung wurde automatisch generiert und kann Fehler enthalten. Wenn Sie Muttersprachler sind, freuen wir uns über Ihre Korrekturvorschläge per Pull Request. diff --git a/documentation/de/usage-observeddependency.md b/documentation/de/usage-observeddependency.md new file mode 100644 index 0000000..ec9f7a0 --- /dev/null +++ b/documentation/de/usage-observeddependency.md @@ -0,0 +1,135 @@ +# Verwendung von ObservedDependency + +`ObservedDependency` ist eine Komponente der **AppState**-Bibliothek, mit der Sie Abhängigkeiten verwenden können, die dem `ObservableObject`-Protokoll entsprechen. Dies ist nützlich, wenn Sie möchten, dass die Abhängigkeit Ihre SwiftUI-Ansichten über Änderungen benachrichtigt, wodurch Ihre Ansichten reaktiv und dynamisch werden. + +## Hauptmerkmale + +- **Beobachtbare Abhängigkeiten**: Verwenden Sie Abhängigkeiten, die dem `ObservableObject`-Protokoll entsprechen, sodass die Abhängigkeit Ihre Ansichten automatisch aktualisiert, wenn sich ihr Zustand ändert. +- **Reaktive UI-Aktualisierungen**: SwiftUI-Ansichten werden automatisch aktualisiert, wenn Änderungen von der beobachteten Abhängigkeit veröffentlicht werden. +- **Threadsicher**: Wie andere AppState-Komponenten gewährleistet `ObservedDependency` einen threadsicheren Zugriff auf die beobachtete Abhängigkeit. + +## Anwendungsbeispiel + +### Definieren einer beobachtbaren Abhängigkeit + +So definieren Sie einen beobachtbaren Dienst als Abhängigkeit in der `Application`-Erweiterung: + +```swift +import AppState +import SwiftUI + +@MainActor +class ObservableService: ObservableObject { + @Published var count: Int = 0 +} + +extension Application { + @MainActor + var observableService: Dependency { + dependency(ObservableService()) + } +} +``` + +### Verwendung der beobachteten Abhängigkeit in einer SwiftUI-Ansicht + +In Ihrer SwiftUI-Ansicht können Sie mit dem `@ObservedDependency`-Property-Wrapper auf die beobachtbare Abhängigkeit zugreifen. Das beobachtete Objekt aktualisiert die Ansicht automatisch, wenn sich sein Zustand ändert. + +```swift +import AppState +import SwiftUI + +struct ObservedDependencyExampleView: View { + @ObservedDependency(\.observableService) var service: ObservableService + + var body: some View { + VStack { + Text("Zähler: \(service.count)") + Button("Zähler erhöhen") { + service.count += 1 + } + } + } +} +``` + +### Testfall + +Der folgende Testfall zeigt die Interaktion mit `ObservedDependency`: + +```swift +import XCTest +@testable import AppState + +@MainActor +fileprivate class ObservableService: ObservableObject { + @Published var count: Int + + init() { + count = 0 + } +} + +fileprivate extension Application { + @MainActor + var observableService: Dependency { + dependency(ObservableService()) + } +} + +@MainActor +fileprivate struct ExampleDependencyWrapper { + @ObservedDependency(\.observableService) var service + + func test() { + service.count += 1 + } +} + +final class ObservedDependencyTests: XCTestCase { + @MainActor + func testDependency() async { + let example = ExampleDependencyWrapper() + + XCTAssertEqual(example.service.count, 0) + + example.test() + + XCTAssertEqual(example.service.count, 1) + } +} +``` + +### Reaktive UI-Aktualisierungen + +Da die Abhängigkeit dem `ObservableObject`-Protokoll entspricht, löst jede Änderung ihres Zustands eine UI-Aktualisierung in der SwiftUI-Ansicht aus. Sie können den Zustand direkt an UI-Elemente wie einen `Picker` binden: + +```swift +import AppState +import SwiftUI + +struct ReactiveView: View { + @ObservedDependency(\.observableService) var service: ObservableService + + var body: some View { + Picker("Zähler auswählen", selection: $service.count) { + ForEach(0..<10) { count in + Text("\(count)").tag(count) + } + } + } +} +``` + +## Bewährte Praktiken + +- **Verwendung für beobachtbare Dienste**: `ObservedDependency` ist ideal, wenn Ihre Abhängigkeit Ansichten über Änderungen benachrichtigen muss, insbesondere für Dienste, die Daten- oder Zustandsaktualisierungen bereitstellen. +- **Veröffentlichte Eigenschaften nutzen**: Stellen Sie sicher, dass Ihre Abhängigkeit `@Published`-Eigenschaften verwendet, um Aktualisierungen in Ihren SwiftUI-Ansichten auszulösen. +- **Threadsicher**: Wie andere AppState-Komponenten gewährleistet `ObservedDependency` einen threadsicheren Zugriff und Änderungen am beobachtbaren Dienst. + +## Fazit + +`ObservedDependency` ist ein leistungsstarkes Werkzeug zur Verwaltung beobachtbarer Abhängigkeiten in Ihrer App. Durch die Nutzung des `ObservableObject`-Protokolls von Swift wird sichergestellt, dass Ihre SwiftUI-Ansichten reaktiv und auf dem neuesten Stand der Änderungen im Dienst oder in der Ressource bleiben. + +--- +Diese Übersetzung wurde automatisch generiert und kann Fehler enthalten. Wenn Sie Muttersprachler sind, freuen wir uns über Ihre Korrekturvorschläge per Pull Request. diff --git a/documentation/de/usage-overview.md b/documentation/de/usage-overview.md new file mode 100644 index 0000000..87ab054 --- /dev/null +++ b/documentation/de/usage-overview.md @@ -0,0 +1,215 @@ +# Verwendungsübersicht + +Diese Übersicht bietet eine schnelle Einführung in die Verwendung der Schlüsselkomponenten der **AppState**-Bibliothek in einer SwiftUI-`View`. Jeder Abschnitt enthält einfache Beispiele, die in den Rahmen einer SwiftUI-Ansichtsstruktur passen. + +## Definieren von Werten in der Anwendungserweiterung + +Um anwendungsweite Zustände oder Abhängigkeiten zu definieren, sollten Sie das `Application`-Objekt erweitern. Dies ermöglicht es Ihnen, den gesamten Zustand Ihrer App an einem Ort zu zentralisieren. Hier ist ein Beispiel, wie Sie `Application` erweitern können, um verschiedene Zustände und Abhängigkeiten zu erstellen: + +```swift +import AppState + +extension Application { + var user: State { + state(initial: User(name: "Guest", isLoggedIn: false)) + } + + var userPreferences: StoredState { + storedState(initial: "Default Preferences", id: "userPreferences") + } + + var darkModeEnabled: SyncState { + syncState(initial: false, id: "darkModeEnabled") + } + + var userToken: SecureState { + secureState(id: "userToken") + } + + @MainActor + var largeDataset: FileState<[String]> { + fileState(initial: [], filename: "largeDataset") + } +} +``` + +## State + +`State` ermöglicht es Ihnen, einen anwendungsweiten Zustand zu definieren, auf den überall in Ihrer App zugegriffen und der geändert werden kann. + +### Beispiel + +```swift +import AppState +import SwiftUI + +struct ContentView: View { + @AppState(\.user) var user: User + + var body: some View { + VStack { + Text("Hallo, \(user.name)!") + Button("Anmelden") { + user.isLoggedIn.toggle() + } + } + } +} +``` + +## StoredState + +`StoredState` speichert den Zustand mit `UserDefaults`, um sicherzustellen, dass die Werte über App-Starts hinweg gespeichert werden. + +### Beispiel + +```swift +import AppState +import SwiftUI + +struct PreferencesView: View { + @StoredState(\.userPreferences) var userPreferences: String + + var body: some View { + VStack { + Text("Einstellungen: \(userPreferences)") + Button("Einstellungen aktualisieren") { + userPreferences = "Updated Preferences" + } + } + } +} +``` + +## SyncState + +`SyncState` synchronisiert den App-Zustand über mehrere Geräte hinweg mit iCloud. + +### Beispiel + +```swift +import AppState +import SwiftUI + +struct SyncSettingsView: View { + @SyncState(\.darkModeEnabled) var isDarkModeEnabled: Bool + + var body: some View { + VStack { + Toggle("Dunkelmodus", isOn: $isDarkModeEnabled) + } + } +} +``` + +## FileState + +`FileState` wird verwendet, um größere oder komplexere Daten dauerhaft im Dateisystem zu speichern, was es ideal für das Caching oder das Speichern von Daten macht, die nicht in die Grenzen von `UserDefaults` passen. + +### Beispiel + +```swift +import AppState +import SwiftUI + +struct LargeDataView: View { + @FileState(\.largeDataset) var largeDataset: [String] + + var body: some View { + List(largeDataset, id: \.self) { item in + Text(item) + } + } +} +``` + +## SecureState + +`SecureState` speichert vertrauliche Daten sicher im Schlüsselbund. + +### Beispiel + +```swift +import AppState +import SwiftUI + +struct SecureView: View { + @SecureState(\.userToken) var userToken: String? + + var body: some View { + VStack { + if let token = userToken { + Text("Benutzertoken: \(token)") + } else { + Text("Kein Token gefunden.") + } + Button("Token festlegen") { + userToken = "secure_token_value" + } + } + } +} +``` + +## Constant + +`Constant` bietet unveränderlichen, schreibgeschützten Zugriff auf Werte im Zustand Ihrer Anwendung und gewährleistet so die Sicherheit beim Zugriff auf Werte, die nicht geändert werden sollen. + +### Beispiel + +```swift +import AppState +import SwiftUI + +struct ExampleView: View { + @Constant(\.user, \.name) var name: String + + var body: some View { + Text("Benutzername: \(name)") + } +} +``` + +## Slicing State + +`Slice` und `OptionalSlice` ermöglichen den Zugriff auf bestimmte Teile des Zustands Ihrer Anwendung. + +### Beispiel + +```swift +import AppState +import SwiftUI + +struct SlicingView: View { + @Slice(\.user, \.name) var name: String + + var body: some View { + VStack { + Text("Benutzername: \(name)") + Button("Benutzernamen aktualisieren") { + name = "NewUsername" + } + } + } +} +``` + +## Bewährte Praktiken + +- **Verwenden Sie `AppState` in SwiftUI-Ansichten**: Eigenschafts-Wrapper wie `@AppState`, `@StoredState`, `@FileState`, `@SecureState` und andere sind für die Verwendung im Geltungsbereich von SwiftUI-Ansichten konzipiert. +- **Definieren Sie den Zustand in der Anwendungserweiterung**: Zentralisieren Sie die Zustandsverwaltung, indem Sie `Application` erweitern, um den Zustand und die Abhängigkeiten Ihrer App zu definieren. +- **Reaktive Aktualisierungen**: SwiftUI aktualisiert Ansichten automatisch, wenn sich der Zustand ändert, sodass Sie die Benutzeroberfläche nicht manuell aktualisieren müssen. +- **[Leitfaden zu bewährten Praktiken](best-practices.md)**: Für eine detaillierte Aufschlüsselung der bewährten Praktiken bei der Verwendung von AppState. + +## Nächste Schritte + +Nachdem Sie sich mit der grundlegenden Verwendung vertraut gemacht haben, können Sie sich mit fortgeschritteneren Themen befassen: + +- Erkunden Sie die Verwendung von **FileState** zum dauerhaften Speichern großer Datenmengen in Dateien im [FileState-Verwendungsleitfaden](usage-filestate.md). +- Erfahren Sie mehr über **Konstanten** und wie Sie sie für unveränderliche Werte im Zustand Ihrer App verwenden können, im [Konstanten-Verwendungsleitfaden](usage-constant.md). +- Untersuchen Sie, wie **Dependency** in AppState verwendet wird, um gemeinsam genutzte Dienste zu verarbeiten, und sehen Sie sich Beispiele im [Zustandsabhängigkeits-Verwendungsleitfaden](usage-state-dependency.md) an. +- Tauchen Sie tiefer in fortgeschrittene **SwiftUI**-Techniken wie die Verwendung von `ObservedDependency` zur Verwaltung beobachtbarer Abhängigkeiten in Ansichten im [ObservedDependency-Verwendungsleitfaden](usage-observeddependency.md) ein. +- Informationen zu fortgeschritteneren Verwendungstechniken wie der Just-in-Time-Erstellung und dem Vorabladen von Abhängigkeiten finden Sie im [Leitfaden zur erweiterten Verwendung](advanced-usage.md). + +--- +Diese Übersetzung wurde automatisch generiert und kann Fehler enthalten. Wenn Sie Muttersprachler sind, freuen wir uns über Ihre Korrekturvorschläge per Pull Request. diff --git a/documentation/de/usage-securestate.md b/documentation/de/usage-securestate.md new file mode 100644 index 0000000..d7a51fa --- /dev/null +++ b/documentation/de/usage-securestate.md @@ -0,0 +1,68 @@ +# Verwendung von SecureState + +`SecureState` ist eine Komponente der **AppState**-Bibliothek, mit der Sie sensible Daten sicher im Schlüsselbund speichern können. Es eignet sich am besten zum Speichern kleiner Datenmengen wie Token oder Passwörter, die sicher verschlüsselt werden müssen. + +## Hauptmerkmale + +- **Sichere Speicherung**: Mit `SecureState` gespeicherte Daten werden verschlüsselt und sicher im Schlüsselbund gespeichert. +- **Persistenz**: Die Daten bleiben über App-Starts hinweg erhalten, was eine sichere Wiederherstellung sensibler Werte ermöglicht. + +## Einschränkungen des Schlüsselbunds + +Obwohl `SecureState` sehr sicher ist, gibt es bestimmte Einschränkungen: + +- **Begrenzte Speichergröße**: Der Schlüsselbund ist für kleine Datenmengen ausgelegt. Er ist nicht zum Speichern großer Dateien oder Datensätze geeignet. +- **Leistung**: Der Zugriff auf den Schlüsselbund ist langsamer als der Zugriff auf `UserDefaults`. Verwenden Sie ihn daher nur, wenn es erforderlich ist, sensible Daten sicher zu speichern. + +## Anwendungsbeispiel + +### Speichern eines sicheren Tokens + +```swift +import AppState +import SwiftUI + +extension Application { + var userToken: SecureState { + secureState(id: "userToken") + } +} + +struct SecureView: View { + @SecureState(\.userToken) var userToken: String? + + var body: some View { + VStack { + if let token = userToken { + Text("Benutzertoken: \(token)") + } else { + Text("Kein Token gefunden.") + } + Button("Token festlegen") { + userToken = "secure_token_value" + } + } + } +} +``` + +### Umgang mit dem Fehlen sicherer Daten + +Beim ersten Zugriff auf den Schlüsselbund oder wenn kein Wert gespeichert ist, gibt `SecureState` `nil` zurück. Stellen Sie sicher, dass Sie dieses Szenario ordnungsgemäß behandeln: + +```swift +if let token = userToken { + print("Token: \(token)") +} else { + print("Kein Token verfügbar.") +} +``` + +## Bewährte Praktiken + +- **Verwendung für kleine Daten**: Der Schlüsselbund sollte zum Speichern kleiner sensibler Informationen wie Token, Passwörter und Schlüssel verwendet werden. +- **Vermeiden Sie große Datensätze**: Wenn Sie große Datensätze sicher speichern müssen, sollten Sie eine dateibasierte Verschlüsselung oder andere Methoden in Betracht ziehen, da der Schlüsselbund nicht für die Speicherung großer Datenmengen ausgelegt ist. +- **Behandeln Sie nil**: Behandeln Sie immer Fälle, in denen der Schlüsselbund `nil` zurückgibt, wenn kein Wert vorhanden ist. + +--- +Diese Übersetzung wurde automatisch generiert und kann Fehler enthalten. Wenn Sie Muttersprachler sind, freuen wir uns über Ihre Korrekturvorschläge per Pull Request. diff --git a/documentation/de/usage-slice.md b/documentation/de/usage-slice.md new file mode 100644 index 0000000..24e583a --- /dev/null +++ b/documentation/de/usage-slice.md @@ -0,0 +1,94 @@ +# Verwendung von Slice und OptionalSlice + +`Slice` und `OptionalSlice` sind Komponenten der **AppState**-Bibliothek, mit denen Sie auf bestimmte Teile des Zustands Ihrer Anwendung zugreifen können. Sie sind nützlich, wenn Sie einen Teil einer komplexeren Zustandsstruktur bearbeiten oder beobachten müssen. + +## Übersicht + +- **Slice**: Ermöglicht den Zugriff auf und die Änderung eines bestimmten Teils eines vorhandenen `State`-Objekts. +- **OptionalSlice**: Funktioniert ähnlich wie `Slice`, ist aber für den Umgang mit optionalen Werten konzipiert, z. B. wenn ein Teil Ihres Zustands `nil` sein kann oder nicht. + +### Hauptmerkmale + +- **Selektiver Zustandszugriff**: Greifen Sie nur auf den Teil des Zustands zu, den Sie benötigen. +- **Threadsicherheit**: Genau wie bei anderen Zustandsverwaltungstypen in **AppState** sind `Slice` und `OptionalSlice` threadsicher. +- **Reaktivität**: SwiftUI-Ansichten werden aktualisiert, wenn sich der Slice des Zustands ändert, wodurch sichergestellt wird, dass Ihre Benutzeroberfläche reaktiv bleibt. + +## Anwendungsbeispiel + +### Verwendung von Slice + +In diesem Beispiel verwenden wir `Slice`, um auf einen bestimmten Teil des Zustands zuzugreifen und ihn zu aktualisieren – in diesem Fall den `username` aus einem komplexeren `User`-Objekt, das im App-Zustand gespeichert ist. + +```swift +import AppState +import SwiftUI + +struct User { + var username: String + var email: String +} + +extension Application { + var user: State { + state(initial: User(username: "Guest", email: "guest@example.com")) + } +} + +struct SlicingView: View { + @Slice(\.user, \.username) var username: String + + var body: some View { + VStack { + Text("Benutzername: \(username)") + Button("Benutzernamen aktualisieren") { + username = "NewUsername" + } + } + } +} +``` + +### Verwendung von OptionalSlice + +`OptionalSlice` ist nützlich, wenn ein Teil Ihres Zustands `nil` sein kann. In diesem Beispiel kann das `User`-Objekt selbst `nil` sein, daher verwenden wir `OptionalSlice`, um diesen Fall sicher zu behandeln. + +```swift +import AppState +import SwiftUI + +extension Application { + var user: State { + state(initial: nil) + } +} + +struct OptionalSlicingView: View { + @OptionalSlice(\.user, \.username) var username: String? + + var body: some View { + VStack { + if let username = username { + Text("Benutzername: \(username)") + } else { + Text("Kein Benutzername verfügbar") + } + Button("Benutzernamen festlegen") { + username = "UpdatedUsername" + } + } + } +} +``` + +## Bewährte Praktiken + +- **Verwenden Sie `Slice` für nicht-optionale Zustände**: Wenn Ihr Zustand garantiert nicht-optional ist, verwenden Sie `Slice`, um darauf zuzugreifen und ihn zu aktualisieren. +- **Verwenden Sie `OptionalSlice` für optionale Zustände**: Wenn Ihr Zustand oder ein Teil des Zustands optional ist, verwenden Sie `OptionalSlice`, um Fälle zu behandeln, in denen der Wert `nil` sein kann. +- **Threadsicherheit**: Genau wie bei `State` sind `Slice` und `OptionalSlice` threadsicher und für die Arbeit mit dem Nebenläufigkeitsmodell von Swift konzipiert. + +## Fazit + +`Slice` und `OptionalSlice` bieten leistungsstarke Möglichkeiten, auf bestimmte Teile Ihres Zustands auf threadsichere Weise zuzugreifen und diese zu ändern. Durch die Nutzung dieser Komponenten können Sie die Zustandsverwaltung in komplexeren Anwendungen vereinfachen und sicherstellen, dass Ihre Benutzeroberfläche reaktiv und auf dem neuesten Stand bleibt. + +--- +Diese Übersetzung wurde automatisch generiert und kann Fehler enthalten. Wenn Sie Muttersprachler sind, freuen wir uns über Ihre Korrekturvorschläge per Pull Request. diff --git a/documentation/de/usage-state-dependency.md b/documentation/de/usage-state-dependency.md new file mode 100644 index 0000000..35a1139 --- /dev/null +++ b/documentation/de/usage-state-dependency.md @@ -0,0 +1,136 @@ +# Verwendung von Zustand und Abhängigkeiten + +**AppState** bietet leistungsstarke Werkzeuge zur Verwaltung des anwendungsweiten Zustands und zur Injektion von Abhängigkeiten in SwiftUI-Ansichten. Durch die Zentralisierung Ihres Zustands und Ihrer Abhängigkeiten können Sie sicherstellen, dass Ihre Anwendung konsistent und wartbar bleibt. + +## Übersicht + +- **Zustand**: Stellt einen Wert dar, der in der gesamten App gemeinsam genutzt werden kann. Zustandswerte können in Ihren SwiftUI-Ansichten geändert und beobachtet werden. +- **Abhängigkeit**: Stellt eine gemeinsam genutzte Ressource oder einen Dienst dar, der in SwiftUI-Ansichten injiziert und auf den zugegriffen werden kann. + +### Hauptmerkmale + +- **Zentralisierter Zustand**: Definieren und verwalten Sie den anwendungsweiten Zustand an einem Ort. +- **Abhängigkeitsinjektion**: Injizieren und greifen Sie auf gemeinsam genutzte Dienste und Ressourcen in verschiedenen Komponenten Ihrer Anwendung zu. + +## Anwendungsbeispiel + +### Definieren des Anwendungszustands + +Um den anwendungsweiten Zustand zu definieren, erweitern Sie das `Application`-Objekt und deklarieren Sie die Zustandseigenschaften. + +```swift +import AppState + +struct User { + var name: String + var isLoggedIn: Bool +} + +extension Application { + var user: State { + state(initial: User(name: "Guest", isLoggedIn: false)) + } +} +``` + +### Zugreifen auf und Ändern von Zustand in einer Ansicht + +Sie können mit dem `@AppState`-Property-Wrapper direkt in einer SwiftUI-Ansicht auf Zustandswerte zugreifen und diese ändern. + +```swift +import AppState +import SwiftUI + +struct ContentView: View { + @AppState(\.user) var user: User + + var body: some View { + VStack { + Text("Hallo, \(user.name)!") + Button("Anmelden") { + user.name = "John Doe" + user.isLoggedIn = true + } + } + } +} +``` + +### Definieren von Abhängigkeiten + +Sie können gemeinsam genutzte Ressourcen wie einen Netzwerkdienst als Abhängigkeiten im `Application`-Objekt definieren. Diese Abhängigkeiten können in SwiftUI-Ansichten injiziert werden. + +```swift +import AppState + +protocol NetworkServiceType { + func fetchData() -> String +} + +class NetworkService: NetworkServiceType { + func fetchData() -> String { + return "Data from network" + } +} + +extension Application { + var networkService: Dependency { + dependency(NetworkService()) + } +} +``` + +### Zugreifen auf Abhängigkeiten in einer Ansicht + +Greifen Sie mit dem `@AppDependency`-Property-Wrapper in einer SwiftUI-Ansicht auf Abhängigkeiten zu. Dies ermöglicht es Ihnen, Dienste wie einen Netzwerkdienst in Ihre Ansicht zu injizieren. + +```swift +import AppState +import SwiftUI + +struct NetworkView: View { + @AppDependency(\.networkService) var networkService: NetworkServiceType + + var body: some View { + VStack { + Text("Daten: \(networkService.fetchData())") + } + } +} +``` + +### Kombinieren von Zustand und Abhängigkeiten in einer Ansicht + +Zustand und Abhängigkeiten können zusammenarbeiten, um eine komplexere Anwendungslogik zu erstellen. Sie können beispielsweise Daten von einem Dienst abrufen und den Zustand aktualisieren: + +```swift +import AppState +import SwiftUI + +struct CombinedView: View { + @AppState(\.user) var user: User + @AppDependency(\.networkService) var networkService: NetworkServiceType + + var body: some View { + VStack { + Text("Benutzer: \(user.name)") + Button("Daten abrufen") { + user.name = networkService.fetchData() + user.isLoggedIn = true + } + } + } +} +``` + +### Bewährte Praktiken + +- **Zentralisieren Sie den Zustand**: Halten Sie Ihren anwendungsweiten Zustand an einem Ort, um Duplizierung zu vermeiden und Konsistenz zu gewährleisten. +- **Verwenden Sie Abhängigkeiten für gemeinsam genutzte Dienste**: Injizieren Sie Abhängigkeiten wie Netzwerkdienste, Datenbanken oder andere gemeinsam genutzte Ressourcen, um eine enge Kopplung zwischen den Komponenten zu vermeiden. + +## Fazit + +Mit **AppState** können Sie den anwendungsweiten Zustand verwalten und gemeinsam genutzte Abhängigkeiten direkt in Ihre SwiftUI-Ansichten injizieren. Dieses Muster hilft, Ihre App modular und wartbar zu halten. Entdecken Sie weitere Funktionen der **AppState**-Bibliothek wie [SecureState](usage-securestate.md) und [SyncState](usage-syncstate.md), um die Zustandsverwaltung Ihrer App weiter zu verbessern. + +--- +Diese Übersetzung wurde automatisch generiert und kann Fehler enthalten. Wenn Sie Muttersprachler sind, freuen wir uns über Ihre Korrekturvorschläge per Pull Request. diff --git a/documentation/de/usage-storedstate.md b/documentation/de/usage-storedstate.md new file mode 100644 index 0000000..9cf65a5 --- /dev/null +++ b/documentation/de/usage-storedstate.md @@ -0,0 +1,75 @@ +# Verwendung von StoredState + +`StoredState` ist eine Komponente der **AppState**-Bibliothek, mit der Sie kleine Datenmengen mithilfe von `UserDefaults` speichern und beibehalten können. Es ist ideal zum Speichern von leichtgewichtigen, nicht sensiblen Daten, die über App-Starts hinweg erhalten bleiben sollen. + +## Übersicht + +- **StoredState** basiert auf `UserDefaults`, was bedeutet, dass es schnell und effizient zum Speichern kleiner Datenmengen (wie Benutzereinstellungen oder App-Einstellungen) ist. +- In **StoredState** gespeicherte Daten bleiben über App-Sitzungen hinweg erhalten, sodass Sie den Anwendungszustand beim Start wiederherstellen können. + +### Hauptmerkmale + +- **Permanenter Speicher**: In `StoredState` gespeicherte Daten bleiben zwischen den App-Starts verfügbar. +- **Umgang mit kleinen Daten**: Am besten für leichtgewichtige Daten wie Einstellungen, Schalter oder kleine Konfigurationen geeignet. +- **Threadsicher**: `StoredState` stellt sicher, dass der Datenzugriff in nebenläufigen Umgebungen sicher bleibt. + +## Anwendungsbeispiel + +### Definieren eines StoredState + +Sie können einen **StoredState** definieren, indem Sie das `Application`-Objekt erweitern und die Zustandseigenschaft deklarieren: + +```swift +import AppState + +extension Application { + var userPreferences: StoredState { + storedState(initial: "Default Preferences", id: "userPreferences") + } +} +``` + +### Zugreifen auf und Ändern von StoredState in einer Ansicht + +Sie können mit dem `@StoredState`-Property-Wrapper in SwiftUI-Ansichten auf **StoredState**-Werte zugreifen und diese ändern: + +```swift +import AppState +import SwiftUI + +struct PreferencesView: View { + @StoredState(\.userPreferences) var userPreferences: String + + var body: some View { + VStack { + Text("Einstellungen: \(userPreferences)") + Button("Einstellungen aktualisieren") { + userPreferences = "Updated Preferences" + } + } + } +} +``` + +## Umgang mit Datenmigration + +Wenn sich Ihre App weiterentwickelt, können Sie die Modelle aktualisieren, die über **StoredState** beibehalten werden. Stellen Sie beim Aktualisieren Ihres Datenmodells die Abwärtskompatibilität sicher. Sie können beispielsweise neue Felder hinzufügen oder Ihr Modell versionieren, um die Migration zu handhaben. + +Weitere Informationen finden Sie im [Leitfaden zu Migrationsüberlegungen](migration-considerations.md). + +### Überlegungen zur Migration + +- **Hinzufügen neuer nicht optionaler Felder**: Stellen Sie sicher, dass neue Felder entweder optional sind oder Standardwerte haben, um die Abwärtskompatibilität zu gewährleisten. +- **Versionierung von Modellen**: Wenn sich Ihr Datenmodell im Laufe der Zeit ändert, fügen Sie ein `version`-Feld hinzu, um verschiedene Versionen Ihrer beibehaltenen Daten zu verwalten. + +## Bewährte Praktiken + +- **Verwendung für kleine Daten**: Speichern Sie leichtgewichtige, nicht sensible Daten, die über App-Starts hinweg erhalten bleiben müssen, wie z. B. Benutzereinstellungen. +- **Berücksichtigen Sie Alternativen für größere Daten**: Wenn Sie große Datenmengen speichern müssen, sollten Sie stattdessen **FileState** verwenden. + +## Fazit + +**StoredState** ist eine einfache und effiziente Möglichkeit, kleine Datenmengen mit `UserDefaults` beizubehalten. Es ist ideal zum Speichern von Einstellungen und anderen kleinen Konfigurationen über App-Starts hinweg und bietet gleichzeitig einen sicheren Zugriff und eine einfache Integration mit SwiftUI. Für komplexere Persistenzanforderungen erkunden Sie andere **AppState**-Funktionen wie [FileState](usage-filestate.md) oder [SyncState](usage-syncstate.md). + +--- +Diese Übersetzung wurde automatisch generiert und kann Fehler enthalten. Wenn Sie Muttersprachler sind, freuen wir uns über Ihre Korrekturvorschläge per Pull Request. diff --git a/documentation/de/usage-syncstate.md b/documentation/de/usage-syncstate.md new file mode 100644 index 0000000..e3b5e52 --- /dev/null +++ b/documentation/de/usage-syncstate.md @@ -0,0 +1,159 @@ +# Verwendung von SyncState + +`SyncState` ist eine Komponente der **AppState**-Bibliothek, mit der Sie den App-Zustand über mehrere Geräte hinweg mithilfe von iCloud synchronisieren können. Dies ist besonders nützlich, um Benutzereinstellungen, Einstellungen oder andere wichtige Daten über Geräte hinweg konsistent zu halten. + +## Übersicht + +`SyncState` nutzt den `NSUbiquitousKeyValueStore` von iCloud, um kleine Datenmengen über Geräte hinweg synchron zu halten. Dies macht es ideal für die Synchronisierung von leichtgewichtigen Anwendungszuständen wie Einstellungen oder Benutzereinstellungen. + +### Hauptmerkmale + +- **iCloud-Synchronisierung**: Synchronisieren Sie den Zustand automatisch über alle Geräte, die mit demselben iCloud-Konto angemeldet sind. +- **Permanenter Speicher**: Daten werden dauerhaft in iCloud gespeichert, was bedeutet, dass sie auch dann erhalten bleiben, wenn die App beendet oder neu gestartet wird. +- **Nahezu Echtzeit-Synchronisierung**: Zustandsänderungen werden fast sofort auf andere Geräte übertragen. + +> **Hinweis**: `SyncState` wird auf watchOS 9.0 und höher unterstützt. + +## Anwendungsbeispiel + +### Datenmodell + +Angenommen, wir haben eine Struktur namens `Settings`, die `Codable` entspricht: + +```swift +struct Settings: Codable { + var text: String + var isShowingSheet: Bool + var isDarkMode: Bool +} +``` + +### Definieren eines SyncState + +Sie können einen `SyncState` definieren, indem Sie das `Application`-Objekt erweitern und die Zustandseigenschaften deklarieren, die synchronisiert werden sollen: + +```swift +extension Application { + var settings: SyncState { + syncState( + initial: Settings( + text: "Hello, World!", + isShowingSheet: false, + isDarkMode: false + ), + id: "settings" + ) + } +} +``` + +### Umgang mit externen Änderungen + +Um sicherzustellen, dass die App auf externe Änderungen von iCloud reagiert, überschreiben Sie die Funktion `didChangeExternally`, indem Sie eine benutzerdefinierte `Application`-Unterklasse erstellen: + +```swift +class CustomApplication: Application { + override func didChangeExternally(notification: Notification) { + super.didChangeExternally(notification: notification) + + DispatchQueue.main.async { + self.objectWillChange.send() + } + } +} +``` + +### Erstellen von Ansichten zum Ändern und Synchronisieren des Zustands + +Im folgenden Beispiel haben wir zwei Ansichten: `ContentView` und `ContentViewInnerView`. Diese Ansichten teilen und synchronisieren den `Settings`-Zustand zwischen sich. `ContentView` ermöglicht es dem Benutzer, den `text` zu ändern und `isDarkMode` umzuschalten, während `ContentViewInnerView` denselben Text anzeigt und ihn bei Berührung aktualisiert. + +```swift +struct ContentView: View { + @SyncState(\.settings) private var settings: Settings + + var body: some View { + VStack { + TextField("", text: $settings.text) + + Button(settings.isDarkMode ? "Light" : "Dark") { + settings.isDarkMode.toggle() + } + + Button("Show") { settings.isShowingSheet = true } + } + .preferredColorScheme(settings.isDarkMode ? .dark : .light) + .sheet(isPresented: $settings.isShowingSheet, content: ContentViewInnerView.init) + } +} + +struct ContentViewInnerView: View { + @Slice(\.settings, \.text) private var text: String + + var body: some View { + Text("\(text)") + .onTapGesture { + text = Date().formatted() + } + } +} +``` + +### Einrichten der App + +Richten Sie schließlich die Anwendung in der `@main`-Struktur ein. In der Initialisierung bewerben Sie die benutzerdefinierte Anwendung, aktivieren die Protokollierung und laden die iCloud-Speicherabhängigkeit für die Synchronisierung: + +```swift +@main +struct SyncStateExampleApp: App { + init() { + Application + .promote(to: CustomApplication.self) + .logging(isEnabled: true) + .load(dependency: \.icloudStore) + } + + var body: some Scene { + WindowGroup { + ContentView() + } + } +} +``` + +### Aktivieren des iCloud-Schlüssel-Wert-Speichers + +Um die iCloud-Synchronisierung zu aktivieren, stellen Sie sicher, dass Sie dieser Anleitung folgen, um die Funktion des iCloud-Schlüssel-Wert-Speichers zu aktivieren: [Erste Schritte mit SyncState](starting-to-use-syncstate.md). + +### SyncState: Hinweise zum iCloud-Speicher + +Obwohl `SyncState` eine einfache Synchronisierung ermöglicht, ist es wichtig, die Einschränkungen von `NSUbiquitousKeyValueStore` zu beachten: + +- **Speicherlimit**: Sie können mit `NSUbiquitousKeyValueStore` bis zu 1 MB Daten in iCloud speichern, mit einem Größenlimit von 1 MB pro Schlüssel-Wert-Paar. + +### Überlegungen zur Migration + +Bei der Aktualisierung Ihres Datenmodells ist es wichtig, potenzielle Migrationsherausforderungen zu berücksichtigen, insbesondere bei der Arbeit mit persistenten Daten mit **StoredState**, **FileState** oder **SyncState**. Ohne eine ordnungsgemäße Migrationsbehandlung können Änderungen wie das Hinzufügen neuer Felder oder das Ändern von Datenformaten Probleme beim Laden älterer Daten verursachen. + +Hier sind einige wichtige Punkte, die Sie beachten sollten: +- **Hinzufügen neuer nicht optionaler Felder**: Stellen Sie sicher, dass neue Felder entweder optional sind oder Standardwerte haben, um die Abwärtskompatibilität zu gewährleisten. +- **Umgang mit Änderungen des Datenformats**: Wenn sich die Struktur Ihres Modells ändert, implementieren Sie eine benutzerdefinierte Dekodierungslogik, um alte Formate zu unterstützen. +- **Versionierung Ihrer Modelle**: Verwenden Sie ein `version`-Feld in Ihren Modellen, um bei Migrationen zu helfen und Logik basierend auf der Datenversion anzuwenden. + +Weitere Informationen zur Verwaltung von Migrationen und zur Vermeidung potenzieller Probleme finden Sie im [Leitfaden zu Migrationsüberlegungen](migration-considerations.md). + +## SyncState-Implementierungsleitfaden + +Detaillierte Anweisungen zur Konfiguration von iCloud und zur Einrichtung von SyncState in Ihrem Projekt finden Sie im [SyncState-Implementierungsleitfaden](syncstate-implementation.md). + +## Bewährte Praktiken + +- **Verwendung für kleine, kritische Daten**: `SyncState` ist ideal für die Synchronisierung kleiner, wichtiger Zustandsteile wie Benutzereinstellungen, Einstellungen oder Funktionskennzeichen. +- **Überwachen Sie den iCloud-Speicher**: Stellen Sie sicher, dass Ihre Verwendung von `SyncState` innerhalb der iCloud-Speichergrenzen bleibt, um Probleme bei der Datensynchronisierung zu vermeiden. +- **Behandeln Sie externe Aktualisierungen**: Wenn Ihre App auf Zustandsänderungen reagieren muss, die auf einem anderen Gerät initiiert wurden, überschreiben Sie die Funktion `didChangeExternally`, um den Zustand der App in Echtzeit zu aktualisieren. + +## Fazit + +`SyncState` bietet eine leistungsstarke Möglichkeit, kleine Mengen von Anwendungszuständen über Geräte hinweg über iCloud zu synchronisieren. Es ist ideal, um sicherzustellen, dass Benutzereinstellungen und andere wichtige Daten auf allen Geräten, die mit demselben iCloud-Konto angemeldet sind, konsistent bleiben. Für fortgeschrittenere Anwendungsfälle erkunden Sie andere Funktionen von **AppState**, wie [SecureState](usage-securestate.md) und [FileState](usage-filestate.md). + +--- +Diese Übersetzung wurde automatisch generiert und kann Fehler enthalten. Wenn Sie Muttersprachler sind, freuen wir uns über Ihre Korrekturvorschläge per Pull Request. diff --git a/documentation/advanced-usage.md b/documentation/en/advanced-usage.md similarity index 100% rename from documentation/advanced-usage.md rename to documentation/en/advanced-usage.md diff --git a/documentation/best-practices.md b/documentation/en/best-practices.md similarity index 100% rename from documentation/best-practices.md rename to documentation/en/best-practices.md diff --git a/documentation/contributing.md b/documentation/en/contributing.md similarity index 100% rename from documentation/contributing.md rename to documentation/en/contributing.md diff --git a/documentation/faq.md b/documentation/en/faq.md similarity index 100% rename from documentation/faq.md rename to documentation/en/faq.md diff --git a/documentation/installation.md b/documentation/en/installation.md similarity index 100% rename from documentation/installation.md rename to documentation/en/installation.md diff --git a/documentation/migration-considerations.md b/documentation/en/migration-considerations.md similarity index 100% rename from documentation/migration-considerations.md rename to documentation/en/migration-considerations.md diff --git a/documentation/en/starting-to-use-syncstate.md b/documentation/en/starting-to-use-syncstate.md new file mode 100644 index 0000000..cd0b159 --- /dev/null +++ b/documentation/en/starting-to-use-syncstate.md @@ -0,0 +1,22 @@ +To utilize SyncState, you will first need to set up iCloud capabilities and entitlements in your Xcode project. Here's an introduction to guide you through the process: + +### Setting Up iCloud Capabilities: + +1. Open your Xcode project and adjust the Bundle Identifiers for both macOS and iOS targets to match your own. +2. Next, you need to add the iCloud capability to your project. To do this, select your project in the Project Navigator, then select your target. In the tab bar at the top of the editor area, click on "Signing & Capabilities". +3. In the Capabilities pane, turn on iCloud by clicking the switch in the iCloud row. You should see the switch move to the On position. +4. Once you have enabled iCloud, you need to enable Key-Value storage. You can do this by checking the "Key-Value storage" checkbox. + +### Updating the Entitlements: + +1. You will now need to update your entitlements file. Open the entitlements file for your target. +2. Make sure the iCloud Key-Value Store value matches your unique key-value store ID. Your unique ID should follow the format `$(TeamIdentifierPrefix)`. The default value should be something like, `$(TeamIdentifierPrefix)$(CFBundleIdentifier)`. This is fine for single platform apps, but if your app is on multiple Apple OSs, it’s important that the key-value store ID portions are the same for both targets. + +### Configuring the Devices: + +In addition to configuring the project itself, you also need to prepare the devices that will run the project. + +- Ensure that iCloud Drive is enabled on both iOS and macOS devices. +- Log into both devices using the same iCloud account. + +If you have any questions or run into any issues, feel free to reach out or submit an issue. diff --git a/documentation/syncstate-implementation.md b/documentation/en/syncstate-implementation.md similarity index 100% rename from documentation/syncstate-implementation.md rename to documentation/en/syncstate-implementation.md diff --git a/documentation/usage-constant.md b/documentation/en/usage-constant.md similarity index 100% rename from documentation/usage-constant.md rename to documentation/en/usage-constant.md diff --git a/documentation/usage-filestate.md b/documentation/en/usage-filestate.md similarity index 100% rename from documentation/usage-filestate.md rename to documentation/en/usage-filestate.md diff --git a/documentation/usage-observeddependency.md b/documentation/en/usage-observeddependency.md similarity index 100% rename from documentation/usage-observeddependency.md rename to documentation/en/usage-observeddependency.md diff --git a/documentation/usage-overview.md b/documentation/en/usage-overview.md similarity index 100% rename from documentation/usage-overview.md rename to documentation/en/usage-overview.md diff --git a/documentation/usage-securestate.md b/documentation/en/usage-securestate.md similarity index 100% rename from documentation/usage-securestate.md rename to documentation/en/usage-securestate.md diff --git a/documentation/usage-slice.md b/documentation/en/usage-slice.md similarity index 100% rename from documentation/usage-slice.md rename to documentation/en/usage-slice.md diff --git a/documentation/usage-state-dependency.md b/documentation/en/usage-state-dependency.md similarity index 100% rename from documentation/usage-state-dependency.md rename to documentation/en/usage-state-dependency.md diff --git a/documentation/usage-storedstate.md b/documentation/en/usage-storedstate.md similarity index 100% rename from documentation/usage-storedstate.md rename to documentation/en/usage-storedstate.md diff --git a/documentation/usage-syncstate.md b/documentation/en/usage-syncstate.md similarity index 98% rename from documentation/usage-syncstate.md rename to documentation/en/usage-syncstate.md index 8012f59..557eb5f 100644 --- a/documentation/usage-syncstate.md +++ b/documentation/en/usage-syncstate.md @@ -122,7 +122,7 @@ struct SyncStateExampleApp: App { ### Enabling iCloud Key-Value Store -To enable iCloud syncing, make sure you follow this guide to enable the iCloud Key-Value Store capability: [Starting to use SyncState](https://github.com/0xLeif/AppState/wiki/Starting-to-use-SyncState). +To enable iCloud syncing, make sure you follow this guide to enable the iCloud Key-Value Store capability: [Starting to use SyncState](starting-to-use-syncstate.md). ### SyncState: Notes on iCloud Storage diff --git a/documentation/es/advanced-usage.md b/documentation/es/advanced-usage.md new file mode 100644 index 0000000..cfa7b0e --- /dev/null +++ b/documentation/es/advanced-usage.md @@ -0,0 +1,181 @@ +# Uso Avanzado de AppState + +Esta guía cubre temas avanzados para el uso de **AppState**, incluyendo la creación Just-In-Time, la precarga de dependencias, la gestión eficaz de estados y dependencias, y la comparación de **AppState** con el **Entorno de SwiftUI**. + +## 1. Creación Just-In-Time + +Los valores de AppState, como `State`, `Dependency`, `StoredState` y `SyncState`, se crean justo a tiempo. Esto significa que se instancian solo cuando se accede a ellos por primera vez, mejorando la eficiencia y el rendimiento de su aplicación. + +### Ejemplo + +```swift +extension Application { + var defaultState: State { + state(initial: 0) // El valor no se crea hasta que se accede a él + } +} +``` + +En este ejemplo, `defaultState` no se crea hasta que se accede por primera vez, optimizando el uso de recursos. + +## 2. Precarga de Dependencias + +En algunos casos, es posible que desee precargar ciertas dependencias para asegurarse de que estén disponibles cuando se inicie su aplicación. AppState proporciona una función `load` que precarga las dependencias. + +### Ejemplo + +```swift +extension Application { + var databaseClient: Dependency { + dependency(DatabaseClient()) + } +} + +// Precargar en la inicialización de la aplicación +Application.load(dependency: \.databaseClient) +``` + +En este ejemplo, `databaseClient` se precarga durante la inicialización de la aplicación, asegurando que esté disponible cuando se necesite en sus vistas. + +## 3. Gestión de Estado y Dependencias + +### 3.1 Estado y Dependencias Compartidos en Toda la Aplicación + +Puede definir un estado o dependencias compartidas en una parte de su aplicación y acceder a ellos en otra parte utilizando ID únicos. + +### Ejemplo + +```swift +private extension Application { + var stateValue: State { + state(initial: 0, id: "stateValue") + } + + var dependencyValue: Dependency { + dependency(SomeType(), id: "dependencyValue") + } +} +``` + +Esto le permite acceder al mismo `State` o `Dependency` en otro lugar utilizando el mismo ID. + +```swift +private extension Application { + var theSameStateValue: State { + state(initial: 0, id: "stateValue") + } + + var theSameDependencyValue: Dependency { + dependency(SomeType(), id: "dependencyValue") + } +} +``` + +Aunque este enfoque es válido para compartir estados y dependencias en toda la aplicación reutilizando el mismo `id` de cadena, generalmente se desaconseja. Se basa en la gestión manual de estos ID de cadena, lo que puede llevar a: +- Colisiones accidentales de ID si el mismo ID se utiliza para diferentes estados/dependencias previstos. +- Dificultad para rastrear dónde se define un estado/dependencia frente a dónde se accede. +- Reducción de la claridad y mantenibilidad del código. +El valor `initial` proporcionado en definiciones posteriores con el mismo ID se ignorará si el estado/dependencia ya ha sido inicializado por su primer acceso. Este comportamiento es más un efecto secundario de cómo funciona el almacenamiento en caché basado en ID en AppState, en lugar de un patrón principal recomendado para definir datos compartidos. Prefiera definir estados y dependencias como propiedades computadas únicas en extensiones de `Application` (que generan automáticamente ID internos únicos si no se proporciona un `id` explícito al método de fábrica). + +### 3.2 Acceso Restringido a Estado y Dependencias + +Para restringir el acceso, utilice un ID único como un UUID para asegurarse de que solo las partes correctas de la aplicación puedan acceder a estados o dependencias específicos. + +### Ejemplo + +```swift +private extension Application { + var restrictedState: State { + state(initial: nil, id: UUID().uuidString) + } + + var restrictedDependency: Dependency { + dependency(SomeType(), id: UUID().uuidString) + } +} +``` + +### 3.3 ID Únicos para Estados y Dependencias + +Cuando no se proporciona un ID, AppState genera un ID predeterminado basado en la ubicación en el código fuente. Esto asegura que cada `State` o `Dependency` sea único y esté protegido contra accesos no deseados. + +### Ejemplo + +```swift +extension Application { + var defaultState: State { + state(initial: 0) // AppState genera un ID único + } + + var defaultDependency: Dependency { + dependency(SomeType()) // AppState genera un ID único + } +} +``` + +### 3.4 Acceso a Estado y Dependencias Privado a Nivel de Archivo + +Para un acceso aún más restringido dentro del mismo archivo Swift, utilice el nivel de acceso `fileprivate` para proteger los estados y las dependencias de ser accedidos externamente. + +### Ejemplo + +```swift +fileprivate extension Application { + var fileprivateState: State { + state(initial: 0) + } + + var fileprivateDependency: Dependency { + dependency(SomeType()) + } +} +``` + +### 3.5 Comprensión del Mecanismo de Almacenamiento de AppState + +AppState utiliza una caché unificada para almacenar `State`, `Dependency`, `StoredState` y `SyncState`. Esto asegura que estos tipos de datos se gestionen de manera eficiente en toda su aplicación. + +Por defecto, AppState asigna un valor de nombre como "App", lo que asegura que todos los valores asociados con un módulo estén vinculados a ese nombre. Esto dificulta el acceso a estos estados y dependencias desde otros módulos. + +## 4. AppState vs Entorno de SwiftUI + +AppState y el Entorno de SwiftUI ofrecen formas de gestionar el estado compartido y las dependencias en su aplicación, pero difieren en alcance, funcionalidad y casos de uso. + +### 4.1 Entorno de SwiftUI + +El Entorno de SwiftUI es un mecanismo incorporado que le permite pasar datos compartidos a través de una jerarquía de vistas. Es ideal para pasar datos a los que muchas vistas necesitan acceso, pero tiene limitaciones cuando se trata de una gestión de estado más compleja. + +**Fortalezas:** +- Fácil de usar y bien integrado con SwiftUI. +- Ideal para datos ligeros que necesitan ser compartidos entre múltiples vistas en una jerarquía. + +**Limitaciones:** +- Los datos solo están disponibles dentro de la jerarquía de vistas específica. Acceder a los mismos datos a través de diferentes jerarquías de vistas no es posible sin trabajo adicional. +- Menos control sobre la seguridad de hilos y la persistencia en comparación con AppState. +- Falta de mecanismos de persistencia o sincronización incorporados. + +### 4.2 AppState + +AppState proporciona un sistema más potente y flexible para gestionar el estado en toda la aplicación, con capacidades de seguridad de hilos, persistencia e inyección de dependencias. + +**Fortalezas:** +- Gestión de estado centralizada, accesible en toda la aplicación, no solo en jerarquías de vistas específicas. +- Mecanismos de persistencia incorporados (`StoredState`, `FileState` y `SyncState`). +- Garantías de seguridad de tipos y de hilos, asegurando que el estado se acceda y modifique correctamente. +- Puede manejar una gestión de estado y dependencias más compleja. + +**Limitaciones:** +- Requiere más configuración en comparación con el Entorno de SwiftUI. +- Algo menos integrado con SwiftUI en comparación con Environment, aunque sigue funcionando bien en aplicaciones de SwiftUI. + +### 4.3 Cuándo Usar Cada Uno + +- Use el **Entorno de SwiftUI** cuando tenga datos simples que necesiten ser compartidos a través de una jerarquía de vistas, como la configuración del usuario o las preferencias de temas. +- Use **AppState** cuando necesite una gestión de estado centralizada, persistencia o un estado más complejo que deba ser accedido en toda la aplicación. + +## Conclusión + +Al utilizar estas técnicas avanzadas, como la creación justo a tiempo, la precarga, la gestión de estados y dependencias, y la comprensión de las diferencias entre AppState y el Entorno de SwiftUI, puede crear aplicaciones eficientes y conscientes de los recursos con **AppState**. + +--- +Esta traducción fue generada automáticamente y puede contener errores. Si eres un hablante nativo, te agradecemos que contribuyas con correcciones a través de un Pull Request. diff --git a/documentation/es/best-practices.md b/documentation/es/best-practices.md new file mode 100644 index 0000000..209bcec --- /dev/null +++ b/documentation/es/best-practices.md @@ -0,0 +1,65 @@ +# Mejores Prácticas para Usar AppState + +Esta guía proporciona las mejores prácticas para ayudarlo a usar AppState de manera eficiente y efectiva en sus aplicaciones Swift. + +## 1. Use AppState con Moderación + +AppState es versátil y adecuado tanto para la gestión de estado compartido como localizado. Es ideal para datos que necesitan ser compartidos entre múltiples componentes, persistir a través de vistas o sesiones de usuario, o ser gestionados a nivel de componente. Sin embargo, el uso excesivo puede llevar a una complejidad innecesaria. + +### Recomendación: +- Use AppState para datos que realmente necesiten ser de toda la aplicación, compartidos entre componentes distantes, o que requieran las características específicas de persistencia/sincronización de AppState. +- Para el estado que es local a una sola vista de SwiftUI o una jerarquía cercana de vistas, prefiera las herramientas integradas de SwiftUI como `@State`, `@StateObject`, `@ObservedObject`, o `@EnvironmentObject`. + +## 2. Mantenga un AppState Limpio + +A medida que su aplicación se expande, su AppState puede crecer en complejidad. Revise y refactorice regularmente su AppState para eliminar estados y dependencias no utilizados. Mantener su AppState limpio lo hace más simple de entender, mantener y probar. + +### Recomendación: +- Audite periódicamente su AppState en busca de estados y dependencias no utilizados o redundantes. +- Refactorice las grandes estructuras de AppState para mantenerlas limpias y manejables. + +## 3. Pruebe su AppState + +Al igual que otros aspectos de su aplicación, asegúrese de que su AppState sea probado a fondo. Use dependencias simuladas para aislar su AppState de las dependencias externas durante las pruebas, y confirme que cada parte de su aplicación se comporta como se espera. + +### Recomendación: +- Use XCTest o marcos similares para probar el comportamiento y las interacciones de AppState. +- Simule o cree stubs de dependencias para asegurarse de que las pruebas de AppState sean aisladas y confiables. + +## 4. Use la característica Slice con sabiduría + +La característica `Slice` le permite acceder a partes específicas del estado de un AppState, lo cual es útil para manejar estructuras de estado grandes y complejas. Sin embargo, use esta función con sabiduría para mantener un AppState limpio y bien organizado, evitando slices innecesarios que fragmenten el manejo del estado. + +### Recomendación: +- Solo use `Slice` para estados grandes o anidados donde sea necesario acceder a componentes individuales. +- Evite el exceso de slicing del estado, lo que puede llevar a confusión y a una gestión de estado fragmentada. + +## 5. Use Constantes para Valores Estáticos + +La función `@Constant` le permite definir constantes de solo lectura que se pueden compartir en toda su aplicación. Es útil para valores que permanecen sin cambios a lo largo del ciclo de vida de su aplicación, como configuraciones o datos predefinidos. Las constantes aseguran que estos valores no se modifiquen involuntariamente. + +### Recomendación: +- Use `@Constant` para valores que permanecen sin cambios, como configuraciones de la aplicación, variables de entorno o referencias estáticas. + +## 6. Modularice su AppState + +Para aplicaciones más grandes, considere dividir su AppState en módulos más pequeños y manejables. Cada módulo puede tener su propio estado y dependencias, que luego se componen en el AppState general. Esto puede hacer que su AppState sea más fácil de entender, probar y mantener. + +### Recomendación: +- Organice sus extensiones de `Application` en archivos Swift separados o incluso en módulos Swift separados, agrupados por característica o dominio. Esto modulariza naturalmente las definiciones. +- Al definir estados o dependencias usando métodos de fábrica como `state(initial:feature:id:)`, utilice el parámetro `feature` para proporcionar un espacio de nombres, por ejemplo, `state(initial: 0, feature: "UserProfile", id: "score")`. Esto ayuda a organizar y prevenir colisiones de ID si se utilizan ID manuales. +- Evite crear múltiples instancias de `Application`. Limítese a extender y usar el singleton compartido (`Application.shared`). + +## 7. Aproveche la Creación Just-In-Time + +Los valores de AppState se crean justo a tiempo, lo que significa que se instancian solo cuando se accede a ellos. Esto optimiza el uso de la memoria y asegura que los valores de AppState solo se creen cuando sea necesario. + +### Recomendación: +- Permita que los valores de AppState se creen justo a tiempo en lugar de precargar innecesariamente todos los estados y dependencias. + +## Conclusión + +Cada aplicación es única, por lo que estas mejores prácticas pueden no encajar en todas las situaciones. Siempre considere los requisitos específicos de su aplicación al decidir cómo usar AppState, y esfuércese por mantener su gestión de estado limpia, eficiente y bien probada. + +--- +Esta traducción fue generada automáticamente y puede contener errores. Si eres un hablante nativo, te agradecemos que contribuyas con correcciones a través de un Pull Request. diff --git a/documentation/es/contributing.md b/documentation/es/contributing.md new file mode 100644 index 0000000..3c735d5 --- /dev/null +++ b/documentation/es/contributing.md @@ -0,0 +1,63 @@ +# Contribuir a AppState + +¡Gracias por considerar contribuir a **AppState**! Sus contribuciones ayudan a que este proyecto sea mejor para todos. + +## Cómo Contribuir + +### 1. Reportar Errores + +Si encuentra algún error, por favor abra un issue en GitHub. Al reportar un error, por favor incluya: + +- Un título claro y descriptivo. +- Una descripción detallada del error, incluyendo los pasos para reproducirlo. +- El comportamiento esperado y lo que realmente sucedió. +- La versión de **AppState** que está utilizando. +- Cualquier captura de pantalla o registro relevante. + +### 2. Sugerir Características + +¡Las nuevas ideas son bienvenidas! Si tiene una característica que le gustaría ver agregada a **AppState**, por favor abra un issue y describa: + +- El problema que la característica resolvería. +- Cómo cree que debería funcionar la característica. +- Cualquier contexto o ejemplo adicional que ayude a ilustrar su idea. + +### 3. Enviar Pull Requests + +Si desea contribuir con código a **AppState**, siga estos pasos: + +1. **Haga un Fork del Repositorio**: Cree un fork personal del repositorio de **AppState** en GitHub. +2. **Clone su Fork**: Clone su fork a su máquina local: + ```bash + git clone https://github.com/your-username/AppState.git + ``` +3. **Cree una Nueva Rama**: Cree una nueva rama para su característica o corrección de errores: + ```bash + git checkout -b mi-rama-de-caracteristica + ``` +4. **Realice Cambios**: Implemente sus cambios en la nueva rama. +5. **Pruebe sus Cambios**: Asegúrese de que sus cambios pasen todas las pruebas. Agregue nuevas pruebas si es necesario. +6. **Confirme sus Cambios**: Confirme sus cambios con un mensaje de confirmación descriptivo: + ```bash + git commit -m "Agregar mi nueva característica" + ``` +7. **Envíe a GitHub**: Envíe su rama a su fork de GitHub: + ```bash + git push origin mi-rama-de-caracteristica + ``` +8. **Cree un Pull Request**: Vaya al repositorio de **AppState** en GitHub y cree un pull request desde su rama. + +### 4. Estilo de Código + +Por favor, siga las pautas de estilo de codificación utilizadas en el proyecto **AppState**. Un estilo de código consistente ayuda a que el código base sea más mantenible y fácil de revisar. + +### 5. Licencia + +Al contribuir a **AppState**, usted acepta que sus contribuciones estarán licenciadas bajo la misma licencia que el proyecto: [LICENCIA](https://github.com/0xLeif/AppState/blob/main/LICENSE). + +## ¡Gracias! + +Sus contribuciones son muy valoradas y apreciadas. ¡Gracias por ayudar a mejorar **AppState**! + +--- +Esta traducción fue generada automáticamente y puede contener errores. Si eres un hablante nativo, te agradecemos que contribuyas con correcciones a través de un Pull Request. diff --git a/documentation/es/faq.md b/documentation/es/faq.md new file mode 100644 index 0000000..f6ab487 --- /dev/null +++ b/documentation/es/faq.md @@ -0,0 +1,43 @@ +# Preguntas Frecuentes + +Esta breve sección de preguntas frecuentes aborda las preguntas comunes que los desarrolladores pueden tener al usar **AppState**. + +## ¿Cómo reinicio un valor de estado? + +Para los estados persistentes como `StoredState`, `FileState` y `SyncState`, puede reiniciarlos a sus valores iniciales utilizando las funciones estáticas `reset` en el tipo `Application`. + +Por ejemplo, para reiniciar un `StoredState`: +```swift +extension Application { + var hasCompletedOnboarding: StoredState { storedState(initial: false, id: "onboarding_complete") } +} + +// En algún lugar de su código +Application.reset(storedState: \.hasCompletedOnboarding) +``` +Esto restablecerá el valor en `UserDefaults` a `false`. Existen funciones `reset` similares para `FileState`, `SyncState` y `SecureState`. + +Para un `State` no persistente, puede reiniciarlo de la misma manera que los estados persistentes: +```swift +extension Application { + var counter: State { state(initial: 0) } +} + +// En algún lugar de su código +Application.reset(\.counter) +``` + +## ¿Puedo usar AppState con tareas asíncronas? + +Sí. Los valores de `State` y de dependencia son seguros para hilos y funcionan sin problemas con Swift Concurrency. Puede acceder a ellos y modificarlos dentro de funciones `async` sin necesidad de bloqueos adicionales. + +## ¿Dónde debo definir los estados y las dependencias? + +Mantenga todos sus estados y dependencias en extensiones de `Application`. Esto asegura una única fuente de verdad y facilita el descubrimiento de todos los valores disponibles. + +## ¿Es AppState compatible con Combine? + +Puede usar AppState junto con Combine puenteando los cambios de `State` a publicadores. Observe un valor de `State` y envíe actualizaciones a través de un `PassthroughSubject` u otro publicador de Combine si es necesario. + +--- +Esta traducción fue generada automáticamente y puede contener errores. Si eres un hablante nativo, te agradecemos que contribuyas con correcciones a través de un Pull Request. diff --git a/documentation/es/installation.md b/documentation/es/installation.md new file mode 100644 index 0000000..fb87385 --- /dev/null +++ b/documentation/es/installation.md @@ -0,0 +1,87 @@ +# Guía de Instalación + +Esta guía lo guiará a través del proceso de instalación de **AppState** en su proyecto de Swift utilizando Swift Package Manager. + +## Swift Package Manager + +**AppState** se puede integrar fácilmente en su proyecto utilizando Swift Package Manager. Siga los pasos a continuación para agregar **AppState** como una dependencia. + +### Paso 1: Actualice su Archivo `Package.swift` + +Agregue **AppState** a la sección de `dependencies` de su archivo `Package.swift`: + +```swift +dependencies: [ + .package(url: "https://github.com/0xLeif/AppState.git", from: "2.2.0") +] +``` + +### Paso 2: Agregue AppState a su Objetivo + +Incluya AppState en las dependencias de su objetivo: + +```swift +.target( + name: "YourTarget", + dependencies: ["AppState"] +) +``` + +### Paso 3: Compile su Proyecto + +Una vez que haya agregado AppState a su archivo `Package.swift`, compile su proyecto para obtener la dependencia e integrarla en su base de código. + +``` +swift build +``` + +### Paso 4: Importe AppState en su Código + +Ahora, puede comenzar a usar AppState en su proyecto importándolo en la parte superior de sus archivos de Swift: + +```swift +import AppState +``` + +## Xcode + +Si prefiere agregar **AppState** directamente a través de Xcode, siga estos pasos: + +### Paso 1: Abra su Proyecto de Xcode + +Abra su proyecto o espacio de trabajo de Xcode. + +### Paso 2: Agregue una Dependencia de Paquete de Swift + +1. Navegue hasta el navegador de proyectos y seleccione el archivo de su proyecto. +2. En el editor de proyectos, seleccione su objetivo y luego vaya a la pestaña "Swift Packages". +3. Haga clic en el botón "+" para agregar una dependencia de paquete. + +### Paso 3: Ingrese la URL del Repositorio + +En el cuadro de diálogo "Choose Package Repository", ingrese la siguiente URL: `https://github.com/0xLeif/AppState.git` + +Luego haga clic en "Next". + +### Paso 4: Especifique la Versión + +Elija la versión que desea utilizar. Se recomienda seleccionar la opción "Up to Next Major Version" y especificar `2.0.0` como el límite inferior. Luego haga clic en "Next". + +### Paso 5: Agregue el Paquete + +Xcode obtendrá el paquete y le presentará opciones para agregar **AppState** a su objetivo. Asegúrese de seleccionar el objetivo correcto y haga clic en "Finish". + +### Paso 6: Importe `AppState` en su Código + +Ahora puede importar **AppState** en la parte superior de sus archivos de Swift: + +```swift +import AppState +``` + +## Próximos Pasos + +Con AppState instalado, puede pasar a la [Descripción General del Uso](usage-overview.md) para ver cómo implementar las características clave en su proyecto. + +--- +Esta traducción fue generada automáticamente y puede contener errores. Si eres un hablante nativo, te agradecemos que contribuyas con correcciones a través de un Pull Request. diff --git a/documentation/es/migration-considerations.md b/documentation/es/migration-considerations.md new file mode 100644 index 0000000..48c14aa --- /dev/null +++ b/documentation/es/migration-considerations.md @@ -0,0 +1,81 @@ +# Consideraciones sobre la Migración + +Al actualizar su modelo de datos, especialmente para datos persistentes o sincronizados, debe manejar la compatibilidad con versiones anteriores para evitar posibles problemas al cargar datos antiguos. Aquí hay algunos puntos importantes a tener en cuenta: + +## 1. Agregar Campos no Opcionales +Si agrega nuevos campos no opcionales a su modelo, la decodificación de datos antiguos (que no contendrán esos campos) puede fallar. Para evitar esto: +- Considere dar valores predeterminados a los nuevos campos. +- Haga que los nuevos campos sean opcionales para garantizar la compatibilidad con versiones anteriores de su aplicación. + +### Ejemplo: +```swift +struct Settings: Codable { + var text: String + var isDarkMode: Bool + var newField: String? // El nuevo campo es opcional +} +``` + +## 2. Cambios en el Formato de Datos +Si modifica la estructura de un modelo (por ejemplo, cambiando un tipo de `Int` a `String`), el proceso de decodificación podría fallar al leer datos antiguos. Planifique una migración fluida mediante: +- La creación de una lógica de migración para convertir los formatos de datos antiguos a la nueva estructura. +- El uso del inicializador personalizado de `Decodable` para manejar datos antiguos y asignarlos a su nuevo modelo. + +### Ejemplo: +```swift +struct Settings: Codable { + var text: String + var isDarkMode: Bool + var version: Int + + // Lógica de decodificación personalizada para versiones anteriores + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.text = try container.decode(String.self, forKey: .text) + self.isDarkMode = try container.decode(Bool.self, forKey: .isDarkMode) + self.version = (try? container.decode(Int.self, forKey: .version)) ?? 1 // Valor predeterminado para datos antiguos + } +} +``` + +## 3. Manejo de Campos Eliminados u Obsoletos +Si elimina un campo del modelo, asegúrese de que las versiones antiguas de la aplicación aún puedan decodificar los nuevos datos sin bloquearse. Puede: +- Ignorar los campos adicionales al decodificar. +- Usar decodificadores personalizados para manejar datos antiguos y administrar los campos obsoletos correctamente. + +## 4. Versionado de sus Modelos + +El versionado de sus modelos le permite manejar los cambios en su estructura de datos a lo largo del tiempo. Al mantener un número de versión como parte de su modelo, puede implementar fácilmente una lógica de migración para convertir los formatos de datos antiguos a los nuevos. Este enfoque garantiza que su aplicación pueda manejar estructuras de datos antiguas mientras realiza una transición fluida a las nuevas versiones. + +- **Por qué es Importante el Versionado**: Cuando los usuarios actualizan su aplicación, es posible que todavía tengan datos antiguos persistentes en sus dispositivos. El versionado ayuda a su aplicación a reconocer el formato de los datos y a aplicar la lógica de migración correcta. +- **Cómo Usarlo**: Agregue un campo `version` a su modelo y verifíquelo durante el proceso de decodificación para determinar si se necesita una migración. + +### Ejemplo: +```swift +struct Settings: Codable { + var version: Int + var text: String + var isDarkMode: Bool + + // Manejar la lógica de decodificación específica de la versión + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.version = try container.decode(Int.self, forKey: .version) + self.text = try container.decode(String.self, forKey: .text) + self.isDarkMode = try container.decode(Bool.self, forKey: .isDarkMode) + + // Si se migra desde una versión anterior, aplique las transformaciones necesarias aquí + if version < 2 { + // Migrar datos antiguos al nuevo formato + } + } +} +``` + +- **Mejor Práctica**: Comience con un campo `version` desde el principio. Cada vez que actualice la estructura de su modelo, incremente la versión y maneje la lógica de migración necesaria. + +## 5. Pruebas de Migración +Siempre pruebe su migración a fondo simulando la carga de datos antiguos con nuevas versiones de su modelo para asegurarse de que su aplicación se comporte como se espera. + +--- +Esta traducción fue generada automáticamente y puede contener errores. Si eres un hablante nativo, te agradecemos que contribuyas con correcciones a través de un Pull Request. diff --git a/documentation/es/starting-to-use-syncstate.md b/documentation/es/starting-to-use-syncstate.md new file mode 100644 index 0000000..5f3ac39 --- /dev/null +++ b/documentation/es/starting-to-use-syncstate.md @@ -0,0 +1,25 @@ +Para utilizar SyncState, primero deberá configurar las capacidades y los derechos de iCloud en su proyecto de Xcode. Aquí hay una introducción para guiarlo a través del proceso: + +### Configuración de las capacidades de iCloud: + +1. Abra su proyecto de Xcode y ajuste los identificadores de paquete para los destinos de macOS e iOS para que coincidan con los suyos. +2. A continuación, debe agregar la capacidad de iCloud a su proyecto. Para hacer esto, seleccione su proyecto en el Navegador de proyectos, luego seleccione su destino. En la barra de pestañas en la parte superior del área del editor, haga clic en "Signing & Capabilities". +3. En el panel Capacidades, active iCloud haciendo clic en el interruptor de la fila de iCloud. Debería ver que el interruptor se mueve a la posición de encendido. +4. Una vez que haya habilitado iCloud, debe habilitar el almacenamiento de clave-valor. Puede hacerlo marcando la casilla de verificación "Key-Value storage". + +### Actualización de los derechos: + +1. Ahora deberá actualizar su archivo de derechos. Abra el archivo de derechos para su destino. +2. Asegúrese de que el valor del Almacén de clave-valor de iCloud coincida con su ID de almacén de clave-valor único. Su ID único debe seguir el formato `$(TeamIdentifierPrefix)`. El valor predeterminado debería ser algo así como `$(TeamIdentifierPrefix)$(CFBundleIdentifier)`. Esto está bien para aplicaciones de una sola plataforma, pero si su aplicación está en varios sistemas operativos de Apple, es importante que las partes de la ID del almacén de clave-valor sean las mismas para ambos destinos. + +### Configuración de los dispositivos: + +Además de configurar el proyecto en sí, también debe preparar los dispositivos que ejecutarán el proyecto. + +- Asegúrese de que iCloud Drive esté habilitado en los dispositivos iOS y macOS. +- Inicie sesión en ambos dispositivos con la misma cuenta de iCloud. + +Si tiene alguna pregunta o encuentra algún problema, no dude en contactarnos o reportar un issue. + +--- +Esta traducción fue generada automáticamente y puede contener errores. Si eres un hablante nativo, te agradecemos que contribuyas con correcciones a través de un Pull Request. diff --git a/documentation/es/syncstate-implementation.md b/documentation/es/syncstate-implementation.md new file mode 100644 index 0000000..e9ffd86 --- /dev/null +++ b/documentation/es/syncstate-implementation.md @@ -0,0 +1,84 @@ +# Implementación de SyncState en AppState + +Esta guía cubre cómo configurar SyncState en su aplicación, incluyendo la configuración de las capacidades de iCloud y la comprensión de las posibles limitaciones. + +## 1. Configuración de las Capacidades de iCloud + +Para usar SyncState en su aplicación, primero debe habilitar iCloud en su proyecto y configurar el almacenamiento de clave-valor. + +### Pasos para Habilitar iCloud y el Almacenamiento de Clave-Valor: + +1. Abra su proyecto de Xcode y navegue a la configuración de su proyecto. +2. En la pestaña "Signing & Capabilities", seleccione su objetivo (iOS o macOS). +3. Haga clic en el botón "+ Capability" y elija "iCloud" de la lista. +4. Habilite la opción "Key-Value storage" en la configuración de iCloud. Esto permite que su aplicación almacene y sincronice pequeñas cantidades de datos usando iCloud. + +### Configuración del Archivo de Entitlements: + +1. En su proyecto de Xcode, busque o cree el **archivo de entitlements** para su aplicación. +2. Asegúrese de que el Almacenamiento de Clave-Valor de iCloud esté configurado correctamente en el archivo de entitlements con el contenedor de iCloud correcto. + +Ejemplo en el archivo de entitlements: + +```xml +com.apple.developer.ubiquity-kvstore-identifier +$(TeamIdentifierPrefix)com.yourdomain.app +``` + +Asegúrese de que el valor de la cadena coincida con el contenedor de iCloud asociado a su proyecto. + +## 2. Uso de SyncState en su Aplicación + +Una vez que iCloud esté habilitado, puede usar `SyncState` en su aplicación para sincronizar datos entre dispositivos. + +### Ejemplo de Uso de SyncState: + +```swift +import AppState +import SwiftUI + +extension Application { + var syncValue: SyncState { + syncState(id: "syncValue") + } +} + +struct ContentView: View { + @SyncState(\.syncValue) private var syncValue: Int? + + var body: some View { + VStack { + if let syncValue = syncValue { + Text("SyncValue: \(syncValue)") + } else { + Text("No SyncValue") + } + + Button("Update SyncValue") { + syncValue = Int.random(in: 0..<100) + } + } + } +} +``` + +En este ejemplo, el estado de sincronización se guardará en iCloud y se sincronizará en todos los dispositivos que hayan iniciado sesión en la misma cuenta de iCloud. + +## 3. Limitaciones y Mejores Prácticas + +SyncState utiliza `NSUbiquitousKeyValueStore`, que tiene algunas limitaciones: + +- **Límite de Almacenamiento**: SyncState está diseñado para pequeñas cantidades de datos. El límite de almacenamiento total es de 1 MB, y cada par de clave-valor está limitado a alrededor de 1 MB. +- **Sincronización**: Los cambios realizados en el SyncState no se sincronizan instantáneamente entre dispositivos. Puede haber un ligero retraso en la sincronización, y la sincronización de iCloud puede verse afectada ocasionalmente por las condiciones de la red. + +### Mejores Prácticas: + +- **Use SyncState para Datos Pequeños**: Asegúrese de que solo se sincronicen datos pequeños como las preferencias del usuario o la configuración usando SyncState. +- **Maneje los fallos de SyncState de forma elegante**: Use valores predeterminados o mecanismos de manejo de errores para tener en cuenta los posibles retrasos o fallas en la sincronización. + +## 4. Conclusión + +Al configurar correctamente iCloud y comprender las limitaciones de SyncState, puede aprovechar su poder para sincronizar datos entre dispositivos. Asegúrese de usar SyncState solo para fragmentos de datos pequeños y críticos para evitar posibles problemas con los límites de almacenamiento de iCloud. + +--- +Esta traducción fue generada automáticamente y puede contener errores. Si eres un hablante nativo, te agradecemos que contribuyas con correcciones a través de un Pull Request. diff --git a/documentation/es/usage-constant.md b/documentation/es/usage-constant.md new file mode 100644 index 0000000..46aad24 --- /dev/null +++ b/documentation/es/usage-constant.md @@ -0,0 +1,87 @@ +# Uso de Constantes + +`Constant` en la biblioteca **AppState** proporciona acceso de solo lectura a los valores dentro del estado de su aplicación. Funciona de manera similar a `Slice`, pero asegura que los valores a los que se accede sean inmutables. Esto hace que `Constant` sea ideal para acceder a valores que de otro modo podrían ser mutables pero que deben permanecer de solo lectura en ciertos contextos. + +## Características Clave + +- **Acceso de Solo Lectura**: Las constantes proporcionan acceso al estado mutable, pero los valores no se pueden modificar. +- **Ámbito de Aplicación**: Al igual que `Slice`, `Constant` se define dentro de la extensión de `Application` y tiene como ámbito el acceso a partes específicas del estado. +- **Seguro para Hilos**: `Constant` garantiza un acceso seguro al estado en entornos concurrentes. + +## Ejemplo de Uso + +### Definir una Constante en la Aplicación + +Así es como se define una `Constant` en la extensión de `Application` para acceder a un valor de solo lectura: + +```swift +import AppState +import SwiftUI + +struct ExampleValue { + var username: String? + var isLoading: Bool + let value: String + var mutableValue: String +} + +extension Application { + var exampleValue: State { + state( + initial: ExampleValue( + username: "Leif", + isLoading: false, + value: "value", + mutableValue: "" + ) + ) + } +} +``` + +### Acceder a la Constante en una Vista de SwiftUI + +En una vista de SwiftUI, puede usar el property wrapper `@Constant` para acceder al estado constante de solo lectura: + +```swift +import AppState +import SwiftUI + +struct ExampleView: View { + @Constant(\.exampleValue, \.value) var constantValue: String + + var body: some View { + Text("Valor Constante: \(constantValue)") + } +} +``` + +### Acceso de Solo Lectura al Estado Mutable + +Incluso si el valor es mutable en otro lugar, cuando se accede a través de `@Constant`, el valor se vuelve inmutable: + +```swift +import AppState +import SwiftUI + +struct ExampleView: View { + @Constant(\.exampleValue, \.mutableValue) var constantMutableValue: String + + var body: some View { + Text("Valor Mutable de Solo Lectura: \(constantMutableValue)") + } +} +``` + +## Mejores Prácticas + +- **Usar para Acceso de Solo Lectura**: Use `Constant` para acceder a partes del estado que no deben modificarse en ciertos contextos, incluso si son mutables en otro lugar. +- **Seguro para Hilos**: Al igual que otros componentes de AppState, `Constant` garantiza un acceso seguro al estado para hilos. +- **Usar `OptionalConstant` para Valores Opcionales**: Si la parte del estado a la que está accediendo puede ser `nil`, use `OptionalConstant` para manejar de forma segura la ausencia de un valor. + +## Conclusión + +`Constant` y `OptionalConstant` proporcionan una forma eficiente de acceder a partes específicas del estado de su aplicación de solo lectura. Aseguran que los valores que de otro modo podrían ser mutables se traten como inmutables cuando se accede a ellos dentro de una vista, garantizando la seguridad y la claridad en su código. + +--- +Esta traducción fue generada automáticamente y puede contener errores. Si eres un hablante nativo, te agradecemos que contribuyas con correcciones a través de un Pull Request. diff --git a/documentation/es/usage-filestate.md b/documentation/es/usage-filestate.md new file mode 100644 index 0000000..df5e39d --- /dev/null +++ b/documentation/es/usage-filestate.md @@ -0,0 +1,96 @@ +# Uso de FileState + +`FileState` es un componente de la biblioteca **AppState** que le permite almacenar y recuperar datos persistentes utilizando el sistema de archivos. Es útil para almacenar datos grandes u objetos complejos que necesitan guardarse entre lanzamientos de la aplicación y restaurarse cuando sea necesario. + +## Características Clave + +- **Almacenamiento Persistente**: Los datos almacenados con `FileState` persisten entre lanzamientos de la aplicación. +- **Manejo de Datos Grandes**: A diferencia de `StoredState`, `FileState` es ideal para manejar datos más grandes o complejos. +- **Seguro para Hilos**: Al igual que otros componentes de AppState, `FileState` garantiza un acceso seguro a los datos en entornos concurrentes. + +## Ejemplo de Uso + +### Almacenar y Recuperar Datos con FileState + +A continuación, se muestra cómo definir un `FileState` en la extensión de `Application` para almacenar y recuperar un objeto grande: + +```swift +import AppState +import SwiftUI + +struct UserProfile: Codable { + var name: String + var age: Int +} + +extension Application { + @MainActor + var userProfile: FileState { + fileState(initial: UserProfile(name: "Guest", age: 25), filename: "userProfile") + } +} + +struct FileStateExampleView: View { + @FileState(\.userProfile) var userProfile: UserProfile + + var body: some View { + VStack { + Text("Nombre: \(userProfile.name), Edad: \(userProfile.age)") + Button("Actualizar Perfil") { + userProfile = UserProfile(name: "UpdatedName", age: 30) + } + } + } +} +``` + +### Manejo de Datos Grandes con FileState + +Cuando necesite manejar conjuntos de datos u objetos más grandes, `FileState` garantiza que los datos se almacenen de manera eficiente en el sistema de archivos de la aplicación. Esto es útil para escenarios como el almacenamiento en caché o el almacenamiento sin conexión. + +```swift +import AppState +import SwiftUI + +extension Application { + @MainActor + var largeDataset: FileState<[String]> { + fileState(initial: [], filename: "largeDataset") + } +} + +struct LargeDataView: View { + @FileState(\.largeDataset) var largeDataset: [String] + + var body: some View { + List(largeDataset, id: \.self) { item in + Text(item) + } + } +} +``` + +### Consideraciones sobre la Migración + +Al actualizar su modelo de datos, es importante tener en cuenta los posibles desafíos de migración, especialmente cuando se trabaja con datos persistentes utilizando **StoredState**, **FileState** o **SyncState**. Sin un manejo adecuado de la migración, cambios como agregar nuevos campos o modificar formatos de datos pueden causar problemas al cargar datos antiguos. + +Aquí hay algunos puntos clave a tener en cuenta: +- **Agregar Nuevos Campos no Opcionales**: Asegúrese de que los nuevos campos sean opcionales o tengan valores predeterminados para mantener la compatibilidad con versiones anteriores. +- **Manejo de Cambios en el Formato de Datos**: Si la estructura de su modelo cambia, implemente una lógica de decodificación personalizada para admitir formatos antiguos. +- **Versionado de sus Modelos**: Use un campo `version` en sus modelos para ayudar con las migraciones y aplicar la lógica según la versión de los datos. + +Para obtener más información sobre cómo administrar las migraciones y evitar posibles problemas, consulte la [Guía de Consideraciones sobre la Migración](migration-considerations.md). + + +## Mejores Prácticas + +- **Usar para Datos Grandes o Complejos**: Si está almacenando datos grandes u objetos complejos, `FileState` es ideal sobre `StoredState`. +- **Acceso Seguro para Hilos**: Al igual que otros componentes de **AppState**, `FileState` garantiza que se acceda a los datos de forma segura incluso cuando varias tareas interactúan con los datos almacenados. +- **Combinar con Codable**: Cuando trabaje con tipos de datos personalizados, asegúrese de que se ajusten a `Codable` para simplificar la codificación y decodificación hacia y desde el sistema de archivos. + +## Conclusión + +`FileState` es una herramienta poderosa para manejar datos persistentes en su aplicación, permitiéndole almacenar y recuperar objetos más grandes o complejos de una manera segura para hilos y persistente. Funciona sin problemas con el protocolo `Codable` de Swift, asegurando que sus datos puedan ser serializados y deserializados fácilmente para un almacenamiento a largo plazo. + +--- +Esta traducción fue generada automáticamente y puede contener errores. Si eres un hablante nativo, te agradecemos que contribuyas con correcciones a través de un Pull Request. diff --git a/documentation/es/usage-observeddependency.md b/documentation/es/usage-observeddependency.md new file mode 100644 index 0000000..83e9490 --- /dev/null +++ b/documentation/es/usage-observeddependency.md @@ -0,0 +1,135 @@ +# Uso de ObservedDependency + +`ObservedDependency` es un componente de la biblioteca **AppState** que le permite usar dependencias que se ajustan a `ObservableObject`. Esto es útil cuando desea que la dependencia notifique a sus vistas de SwiftUI sobre los cambios, haciendo que sus vistas sean reactivas y dinámicas. + +## Características Clave + +- **Dependencias Observables**: Use dependencias que se ajusten a `ObservableObject`, permitiendo que la dependencia actualice automáticamente sus vistas cuando su estado cambie. +- **Actualizaciones de IU Reactivas**: Las vistas de SwiftUI se actualizan automáticamente cuando la dependencia observada publica cambios. +- **Seguro para Hilos**: Al igual que otros componentes de AppState, `ObservedDependency` garantiza un acceso seguro a la dependencia observada para hilos. + +## Ejemplo de Uso + +### Definir una Dependencia Observable + +A continuación, se muestra cómo definir un servicio observable como una dependencia en la extensión de `Application`: + +```swift +import AppState +import SwiftUI + +@MainActor +class ObservableService: ObservableObject { + @Published var count: Int = 0 +} + +extension Application { + @MainActor + var observableService: Dependency { + dependency(ObservableService()) + } +} +``` + +### Usar la Dependencia Observada en una Vista de SwiftUI + +En su vista de SwiftUI, puede acceder a la dependencia observable usando el property wrapper `@ObservedDependency`. El objeto observado actualiza automáticamente la vista cada vez que su estado cambia. + +```swift +import AppState +import SwiftUI + +struct ObservedDependencyExampleView: View { + @ObservedDependency(\.observableService) var service: ObservableService + + var body: some View { + VStack { + Text("Conteo: \(service.count)") + Button("Incrementar Conteo") { + service.count += 1 + } + } + } +} +``` + +### Caso de Prueba + +El siguiente caso de prueba demuestra la interacción con `ObservedDependency`: + +```swift +import XCTest +@testable import AppState + +@MainActor +fileprivate class ObservableService: ObservableObject { + @Published var count: Int + + init() { + count = 0 + } +} + +fileprivate extension Application { + @MainActor + var observableService: Dependency { + dependency(ObservableService()) + } +} + +@MainActor +fileprivate struct ExampleDependencyWrapper { + @ObservedDependency(\.observableService) var service + + func test() { + service.count += 1 + } +} + +final class ObservedDependencyTests: XCTestCase { + @MainActor + func testDependency() async { + let example = ExampleDependencyWrapper() + + XCTAssertEqual(example.service.count, 0) + + example.test() + + XCTAssertEqual(example.service.count, 1) + } +} +``` + +### Actualizaciones de IU Reactivas + +Dado que la dependencia se ajusta a `ObservableObject`, cualquier cambio en su estado activará una actualización de la IU en la vista de SwiftUI. Puede vincular el estado directamente a elementos de la IU como un `Picker`: + +```swift +import AppState +import SwiftUI + +struct ReactiveView: View { + @ObservedDependency(\.observableService) var service: ObservableService + + var body: some View { + Picker("Seleccionar Conteo", selection: $service.count) { + ForEach(0..<10) { count in + Text("\(count)").tag(count) + } + } + } +} +``` + +## Mejores Prácticas + +- **Usar para Servicios Observables**: `ObservedDependency` es ideal cuando su dependencia necesita notificar a las vistas sobre los cambios, especialmente para los servicios que proporcionan actualizaciones de datos o de estado. +- **Aprovechar las Propiedades Publicadas**: Asegúrese de que su dependencia use propiedades `@Published` para activar actualizaciones en sus vistas de SwiftUI. +- **Seguro para Hilos**: Al igual que otros componentes de AppState, `ObservedDependency` garantiza un acceso y modificaciones seguros para hilos al servicio observable. + +## Conclusión + +`ObservedDependency` es una herramienta poderosa para gestionar dependencias observables dentro de su aplicación. Al aprovechar el protocolo `ObservableObject` de Swift, garantiza que sus vistas de SwiftUI permanezcan reactivas y actualizadas con los cambios en el servicio o recurso. + +--- +Esta traducción fue generada automáticamente y puede contener errores. Si eres un hablante nativo, te agradecemos que contribuyas con correcciones a través de un Pull Request. diff --git a/documentation/es/usage-overview.md b/documentation/es/usage-overview.md new file mode 100644 index 0000000..52d3b40 --- /dev/null +++ b/documentation/es/usage-overview.md @@ -0,0 +1,215 @@ +# Descripción General del Uso + +Esta descripción general proporciona una introducción rápida al uso de los componentes clave de la biblioteca **AppState** dentro de una `View` de SwiftUI. Cada sección incluye ejemplos simples que se ajustan al alcance de una estructura de vista de SwiftUI. + +## Definición de Valores en la Extensión de Application + +Para definir el estado o las dependencias de toda la aplicación, debe extender el objeto `Application`. Esto le permite centralizar todo el estado de su aplicación en un solo lugar. A continuación, se muestra un ejemplo de cómo extender `Application` para crear varios estados y dependencias: + +```swift +import AppState + +extension Application { + var user: State { + state(initial: User(name: "Guest", isLoggedIn: false)) + } + + var userPreferences: StoredState { + storedState(initial: "Default Preferences", id: "userPreferences") + } + + var darkModeEnabled: SyncState { + syncState(initial: false, id: "darkModeEnabled") + } + + var userToken: SecureState { + secureState(id: "userToken") + } + + @MainActor + var largeDataset: FileState<[String]> { + fileState(initial: [], filename: "largeDataset") + } +} +``` + +## State + +`State` le permite definir un estado de toda la aplicación al que se puede acceder y modificar en cualquier parte de su aplicación. + +### Ejemplo + +```swift +import AppState +import SwiftUI + +struct ContentView: View { + @AppState(\.user) var user: User + + var body: some View { + VStack { + Text("¡Hola, \(user.name)!") + Button("Iniciar sesión") { + user.isLoggedIn.toggle() + } + } + } +} +``` + +## StoredState + +`StoredState` persiste el estado usando `UserDefaults` para garantizar que los valores se guarden entre lanzamientos de la aplicación. + +### Ejemplo + +```swift +import AppState +import SwiftUI + +struct PreferencesView: View { + @StoredState(\.userPreferences) var userPreferences: String + + var body: some View { + VStack { + Text("Preferencias: \(userPreferences)") + Button("Actualizar Preferencias") { + userPreferences = "Updated Preferences" + } + } + } +} +``` + +## SyncState + +`SyncState` sincroniza el estado de la aplicación en múltiples dispositivos usando iCloud. + +### Ejemplo + +```swift +import AppState +import SwiftUI + +struct SyncSettingsView: View { + @SyncState(\.darkModeEnabled) var isDarkModeEnabled: Bool + + var body: some View { + VStack { + Toggle("Modo Oscuro", isOn: $isDarkModeEnabled) + } + } +} +``` + +## FileState + +`FileState` se utiliza para almacenar datos más grandes o complejos de forma persistente utilizando el sistema de archivos, lo que lo hace ideal para almacenar en caché o guardar datos que no se ajustan a las limitaciones de `UserDefaults`. + +### Ejemplo + +```swift +import AppState +import SwiftUI + +struct LargeDataView: View { + @FileState(\.largeDataset) var largeDataset: [String] + + var body: some View { + List(largeDataset, id: \.self) { item in + Text(item) + } + } +} +``` + +## SecureState + +`SecureState` almacena datos confidenciales de forma segura en el Llavero. + +### Ejemplo + +```swift +import AppState +import SwiftUI + +struct SecureView: View { + @SecureState(\.userToken) var userToken: String? + + var body: some View { + VStack { + if let token = userToken { + Text("Token de usuario: \(token)") + } else { + Text("No se encontró ningún token.") + } + Button("Establecer Token") { + userToken = "secure_token_value" + } + } + } +} +``` + +## Constant + +`Constant` proporciona acceso inmutable y de solo lectura a los valores dentro del estado de su aplicación, garantizando la seguridad al acceder a valores que no deben modificarse. + +### Ejemplo + +```swift +import AppState +import SwiftUI + +struct ExampleView: View { + @Constant(\.user, \.name) var name: String + + var body: some View { + Text("Nombre de usuario: \(name)") + } +} +``` + +## Slicing State + +`Slice` y `OptionalSlice` le permiten acceder a partes específicas del estado de su aplicación. + +### Ejemplo + +```swift +import AppState +import SwiftUI + +struct SlicingView: View { + @Slice(\.user, \.name) var name: String + + var body: some View { + VStack { + Text("Nombre de usuario: \(name)") + Button("Actualizar Nombre de Usuario") { + name = "NewUsername" + } + } + } +} +``` + +## Mejores Prácticas + +- **Use `AppState` en Vistas de SwiftUI**: Los property wrappers como `@AppState`, `@StoredState`, `@FileState`, `@SecureState`, y otros están diseñados para ser utilizados dentro del alcance de las vistas de SwiftUI. +- **Defina el Estado en la Extensión de Application**: Centralice la gestión del estado extendiendo `Application` para definir el estado y las dependencias de su aplicación. +- **Actualizaciones Reactivas**: SwiftUI actualiza automáticamente las vistas cuando cambia el estado, por lo que no necesita actualizar manualmente la interfaz de usuario. +- **[Guía de Mejores Prácticas](best-practices.md)**: Para un desglose detallado de las mejores prácticas al usar AppState. + +## Próximos Pasos + +Después de familiarizarse con el uso básico, puede explorar temas más avanzados: + +- Explore el uso de **FileState** para persistir grandes cantidades de datos en archivos en la [Guía de Uso de FileState](usage-filestate.md). +- Aprenda sobre **Constantes** y cómo usarlas para valores inmutables en el estado de su aplicación en la [Guía de Uso de Constantes](usage-constant.md). +- Investigue cómo se usa **Dependency** en AppState para manejar servicios compartidos y vea ejemplos en la [Guía de Uso de Dependencia de Estado](usage-state-dependency.md). +- Profundice en técnicas avanzadas de **SwiftUI** como el uso de `ObservedDependency` para gestionar dependencias observables en las vistas en la [Guía de Uso de ObservedDependency](usage-observeddependency.md). +- Para técnicas de uso más avanzadas, como la creación Just-In-Time y la precarga de dependencias, consulte la [Guía de Uso Avanzado](advanced-usage.md). + +--- +Esta traducción fue generada automáticamente y puede contener errores. Si eres un hablante nativo, te agradecemos que contribuyas con correcciones a través de un Pull Request. diff --git a/documentation/es/usage-securestate.md b/documentation/es/usage-securestate.md new file mode 100644 index 0000000..6bc9139 --- /dev/null +++ b/documentation/es/usage-securestate.md @@ -0,0 +1,68 @@ +# Uso de SecureState + +`SecureState` es un componente de la biblioteca **AppState** que le permite almacenar datos confidenciales de forma segura en el Llavero. Es más adecuado para almacenar pequeñas piezas de datos como tokens o contraseñas que necesitan ser encriptadas de forma segura. + +## Características Clave + +- **Almacenamiento Seguro**: Los datos almacenados con `SecureState` se encriptan y se guardan de forma segura en el Llavero. +- **Persistencia**: Los datos permanecen persistentes entre los lanzamientos de la aplicación, lo que permite la recuperación segura de valores confidenciales. + +## Limitaciones del Llavero + +Aunque `SecureState` es muy seguro, tiene ciertas limitaciones: + +- **Tamaño de Almacenamiento Limitado**: El Llavero está diseñado para pequeñas piezas de datos. No es adecuado para almacenar archivos o conjuntos de datos grandes. +- **Rendimiento**: Acceder al Llavero es más lento que acceder a `UserDefaults`, por lo que debe usarlo solo cuando sea necesario para almacenar de forma segura datos confidenciales. + +## Ejemplo de Uso + +### Almacenar un Token Seguro + +```swift +import AppState +import SwiftUI + +extension Application { + var userToken: SecureState { + secureState(id: "userToken") + } +} + +struct SecureView: View { + @SecureState(\.userToken) var userToken: String? + + var body: some View { + VStack { + if let token = userToken { + Text("Token de usuario: \(token)") + } else { + Text("No se encontró ningún token.") + } + Button("Establecer Token") { + userToken = "secure_token_value" + } + } + } +} +``` + +### Manejo de la Ausencia de Datos Seguros + +Al acceder al Llavero por primera vez, o si no hay ningún valor almacenado, `SecureState` devolverá `nil`. Asegúrese de manejar este escenario correctamente: + +```swift +if let token = userToken { + print("Token: \(token)") +} else { + print("No hay ningún token disponible.") +} +``` + +## Mejores Prácticas + +- **Usar para Datos Pequeños**: El Llavero debe usarse para almacenar pequeñas piezas de información confidencial como tokens, contraseñas y claves. +- **Evitar Grandes Conjuntos de Datos**: Si necesita almacenar grandes conjuntos de datos de forma segura, considere usar encriptación basada en archivos u otros métodos, ya que el Llavero no está diseñado para el almacenamiento de grandes datos. +- **Manejar nil**: Siempre maneje los casos en que el Llavero devuelve `nil` cuando no hay ningún valor presente. + +--- +Esta traducción fue generada automáticamente y puede contener errores. Si eres un hablante nativo, te agradecemos que contribuyas con correcciones a través de un Pull Request. diff --git a/documentation/es/usage-slice.md b/documentation/es/usage-slice.md new file mode 100644 index 0000000..d88e5d5 --- /dev/null +++ b/documentation/es/usage-slice.md @@ -0,0 +1,94 @@ +# Uso de Slice y OptionalSlice + +`Slice` y `OptionalSlice` son componentes de la biblioteca **AppState** que le permiten acceder a partes específicas del estado de su aplicación. Son útiles cuando necesita manipular u observar una parte de una estructura de estado más compleja. + +## Descripción General + +- **Slice**: Le permite acceder y modificar una parte específica de un objeto `State` existente. +- **OptionalSlice**: Funciona de manera similar a `Slice` pero está diseñado para manejar valores opcionales, como cuando parte de su estado puede o no ser `nil`. + +### Características Clave + +- **Acceso Selectivo al Estado**: Acceda solo a la parte del estado que necesita. +- **Seguridad de Hilos**: Al igual que con otros tipos de gestión de estado en **AppState**, `Slice` y `OptionalSlice` son seguros para hilos. +- **Reactividad**: Las vistas de SwiftUI se actualizan cuando cambia el slice del estado, asegurando que su IU permanezca reactiva. + +## Ejemplo de Uso + +### Usando Slice + +En este ejemplo, usamos `Slice` para acceder y actualizar una parte específica del estado, en este caso, el `username` de un objeto `User` más complejo almacenado en el estado de la aplicación. + +```swift +import AppState +import SwiftUI + +struct User { + var username: String + var email: String +} + +extension Application { + var user: State { + state(initial: User(username: "Guest", email: "guest@example.com")) + } +} + +struct SlicingView: View { + @Slice(\.user, \.username) var username: String + + var body: some View { + VStack { + Text("Nombre de usuario: \(username)") + Button("Actualizar Nombre de Usuario") { + username = "NewUsername" + } + } + } +} +``` + +### Usando OptionalSlice + +`OptionalSlice` es útil cuando parte de su estado puede ser `nil`. En este ejemplo, el objeto `User` en sí mismo puede ser `nil`, por lo que usamos `OptionalSlice` para manejar este caso de forma segura. + +```swift +import AppState +import SwiftUI + +extension Application { + var user: State { + state(initial: nil) + } +} + +struct OptionalSlicingView: View { + @OptionalSlice(\.user, \.username) var username: String? + + var body: some View { + VStack { + if let username = username { + Text("Nombre de usuario: \(username)") + } else { + Text("No hay nombre de usuario disponible") + } + Button("Establecer Nombre de Usuario") { + username = "UpdatedUsername" + } + } + } +} +``` + +## Mejores Prácticas + +- **Use `Slice` para el estado no opcional**: Si su estado está garantizado que no es opcional, use `Slice` para acceder a él y actualizarlo. +- **Use `OptionalSlice` para el estado opcional**: Si su estado o parte del estado es opcional, use `OptionalSlice` para manejar los casos en que el valor pueda ser `nil`. +- **Seguridad de Hilos**: Al igual que con `State`, `Slice` y `OptionalSlice` son seguros para hilos y están diseñados para funcionar con el modelo de concurrencia de Swift. + +## Conclusión + +`Slice` y `OptionalSlice` proporcionan formas poderosas de acceder y modificar partes específicas de su estado de una manera segura para hilos. Al aprovechar estos componentes, puede simplificar la gestión del estado en aplicaciones más complejas, asegurando que su IU se mantenga reactiva y actualizada. + +--- +Esta traducción fue generada automáticamente y puede contener errores. Si eres un hablante nativo, te agradecemos que contribuyas con correcciones a través de un Pull Request. diff --git a/documentation/es/usage-state-dependency.md b/documentation/es/usage-state-dependency.md new file mode 100644 index 0000000..9c32341 --- /dev/null +++ b/documentation/es/usage-state-dependency.md @@ -0,0 +1,136 @@ +# Uso de Estado y Dependencia + +**AppState** proporciona herramientas poderosas para administrar el estado de toda la aplicación e inyectar dependencias en las vistas de SwiftUI. Al centralizar su estado y dependencias, puede asegurarse de que su aplicación se mantenga consistente y mantenible. + +## Descripción General + +- **Estado**: Representa un valor que se puede compartir en toda la aplicación. Los valores de estado se pueden modificar y observar dentro de sus vistas de SwiftUI. +- **Dependencia**: Representa un recurso o servicio compartido que se puede inyectar y acceder dentro de las vistas de SwiftUI. + +### Características Clave + +- **Estado Centralizado**: Defina y administre el estado de toda la aplicación en un solo lugar. +- **Inyección de Dependencias**: Inyecte y acceda a servicios y recursos compartidos en diferentes componentes de su aplicación. + +## Ejemplo de Uso + +### Definir el Estado de la Aplicación + +Para definir el estado de toda la aplicación, extienda el objeto `Application` y declare las propiedades de estado. + +```swift +import AppState + +struct User { + var name: String + var isLoggedIn: Bool +} + +extension Application { + var user: State { + state(initial: User(name: "Guest", isLoggedIn: false)) + } +} +``` + +### Acceder y Modificar el Estado en una Vista + +Puede acceder y modificar los valores de estado directamente dentro de una vista de SwiftUI usando el property wrapper `@AppState`. + +```swift +import AppState +import SwiftUI + +struct ContentView: View { + @AppState(\.user) var user: User + + var body: some View { + VStack { + Text("¡Hola, \(user.name)!") + Button("Iniciar sesión") { + user.name = "John Doe" + user.isLoggedIn = true + } + } + } +} +``` + +### Definir Dependencias + +Puede definir recursos compartidos, como un servicio de red, como dependencias en el objeto `Application`. Estas dependencias se pueden inyectar en las vistas de SwiftUI. + +```swift +import AppState + +protocol NetworkServiceType { + func fetchData() -> String +} + +class NetworkService: NetworkServiceType { + func fetchData() -> String { + return "Data from network" + } +} + +extension Application { + var networkService: Dependency { + dependency(NetworkService()) + } +} +``` + +### Acceder a las Dependencias en una Vista + +Acceda a las dependencias dentro de una vista de SwiftUI usando el property wrapper `@AppDependency`. Esto le permite inyectar servicios como un servicio de red en su vista. + +```swift +import AppState +import SwiftUI + +struct NetworkView: View { + @AppDependency(\.networkService) var networkService: NetworkServiceType + + var body: some View { + VStack { + Text("Datos: \(networkService.fetchData())") + } + } +} +``` + +### Combinar Estado y Dependencias en una Vista + +El estado y las dependencias pueden trabajar juntos para construir una lógica de aplicación más compleja. Por ejemplo, puede obtener datos de un servicio y actualizar el estado: + +```swift +import AppState +import SwiftUI + +struct CombinedView: View { + @AppState(\.user) var user: User + @AppDependency(\.networkService) var networkService: NetworkServiceType + + var body: some View { + VStack { + Text("Usuario: \(user.name)") + Button("Obtener Datos") { + user.name = networkService.fetchData() + user.isLoggedIn = true + } + } + } +} +``` + +### Mejores Prácticas + +- **Centralizar el Estado**: Mantenga el estado de toda su aplicación en un solo lugar para evitar la duplicación y garantizar la consistencia. +- **Usar Dependencias para Servicios Compartidos**: Inyecte dependencias como servicios de red, bases de datos u otros recursos compartidos para evitar un acoplamiento estrecho entre los componentes. + +## Conclusión + +Con **AppState**, puede administrar el estado de toda la aplicación e inyectar dependencias compartidas directamente en sus vistas de SwiftUI. Este patrón ayuda a mantener su aplicación modular y mantenible. Explore otras características de la biblioteca **AppState**, como [SecureState](usage-securestate.md) y [SyncState](usage-syncstate.md), para mejorar aún más la gestión del estado de su aplicación. + +--- +Esta traducción fue generada automáticamente y puede contener errores. Si eres un hablante nativo, te agradecemos que contribuyas con correcciones a través de un Pull Request. diff --git a/documentation/es/usage-storedstate.md b/documentation/es/usage-storedstate.md new file mode 100644 index 0000000..17b2075 --- /dev/null +++ b/documentation/es/usage-storedstate.md @@ -0,0 +1,75 @@ +# Uso de StoredState + +`StoredState` es un componente de la biblioteca **AppState** que le permite almacenar y persistir pequeñas cantidades de datos utilizando `UserDefaults`. Es ideal para almacenar datos ligeros y no confidenciales que deben persistir entre los lanzamientos de la aplicación. + +## Descripción General + +- **StoredState** se basa en `UserDefaults`, lo que significa que es rápido y eficiente para almacenar pequeñas cantidades de datos (como las preferencias del usuario o la configuración de la aplicación). +- Los datos guardados en **StoredState** persisten entre las sesiones de la aplicación, lo que le permite restaurar el estado de la aplicación al iniciarla. + +### Características Clave + +- **Almacenamiento Persistente**: Los datos guardados en `StoredState` permanecen disponibles entre los lanzamientos de la aplicación. +- **Manejo de Datos Pequeños**: Se utiliza mejor para datos ligeros como preferencias, interruptores o configuraciones pequeñas. +- **Seguro para Hilos**: `StoredState` garantiza que el acceso a los datos permanezca seguro en entornos concurrentes. + +## Ejemplo de Uso + +### Definir un StoredState + +Puede definir un **StoredState** extendiendo el objeto `Application` y declarando la propiedad de estado: + +```swift +import AppState + +extension Application { + var userPreferences: StoredState { + storedState(initial: "Default Preferences", id: "userPreferences") + } +} +``` + +### Acceder y Modificar StoredState en una Vista + +Puede acceder y modificar los valores de **StoredState** dentro de las vistas de SwiftUI utilizando el property wrapper `@StoredState`: + +```swift +import AppState +import SwiftUI + +struct PreferencesView: View { + @StoredState(\.userPreferences) var userPreferences: String + + var body: some View { + VStack { + Text("Preferencias: \(userPreferences)") + Button("Actualizar Preferencias") { + userPreferences = "Updated Preferences" + } + } + } +} +``` + +## Manejo de la Migración de Datos + +A medida que su aplicación evoluciona, es posible que actualice los modelos que se persisten a través de **StoredState**. Al actualizar su modelo de datos, asegúrese de la compatibilidad con versiones anteriores. Por ejemplo, puede agregar nuevos campos o versionar su modelo para manejar la migración. + +Para obtener más información, consulte la [Guía de Consideraciones sobre la Migración](migration-considerations.md). + +### Consideraciones sobre la Migración + +- **Agregar Nuevos Campos no Opcionales**: Asegúrese de que los nuevos campos sean opcionales o tengan valores predeterminados para mantener la compatibilidad con versiones anteriores. +- **Versionado de Modelos**: Si su modelo de datos cambia con el tiempo, incluya un campo de `version` para administrar diferentes versiones de sus datos persistentes. + +## Mejores Prácticas + +- **Usar para Datos Pequeños**: Almacene datos ligeros y no confidenciales que necesiten persistir entre los lanzamientos de la aplicación, como las preferencias del usuario. +- **Considere Alternativas para Datos más Grandes**: Si necesita almacenar grandes cantidades de datos, considere usar **FileState** en su lugar. + +## Conclusión + +**StoredState** es una forma simple y eficiente de persistir pequeñas piezas de datos utilizando `UserDefaults`. Es ideal para guardar preferencias y otras configuraciones pequeñas entre los lanzamientos de la aplicación, al tiempo que proporciona un acceso seguro y una fácil integración con SwiftUI. Para necesidades de persistencia más complejas, explore otras características de **AppState** como [FileState](usage-filestate.md) o [SyncState](usage-syncstate.md). + +--- +Esta traducción fue generada automáticamente y puede contener errores. Si eres un hablante nativo, te agradecemos que contribuyas con correcciones a través de un Pull Request. diff --git a/documentation/es/usage-syncstate.md b/documentation/es/usage-syncstate.md new file mode 100644 index 0000000..2196c46 --- /dev/null +++ b/documentation/es/usage-syncstate.md @@ -0,0 +1,159 @@ +# Uso de SyncState + +`SyncState` es un componente de la biblioteca **AppState** que le permite sincronizar el estado de la aplicación en múltiples dispositivos usando iCloud. Esto es especialmente útil para mantener consistentes las preferencias del usuario, la configuración u otros datos importantes en todos los dispositivos. + +## Descripción General + +`SyncState` aprovecha el `NSUbiquitousKeyValueStore` de iCloud para mantener pequeñas cantidades de datos sincronizadas en todos los dispositivos. Esto lo hace ideal para sincronizar el estado de la aplicación ligero, como las preferencias o la configuración del usuario. + +### Características Clave + +- **Sincronización con iCloud**: Sincroniza automáticamente el estado en todos los dispositivos que hayan iniciado sesión en la misma cuenta de iCloud. +- **Almacenamiento Persistente**: Los datos se almacenan de forma persistente en iCloud, lo que significa que persistirán incluso si la aplicación se cierra o se reinicia. +- **Sincronización Casi en Tiempo Real**: Los cambios en el estado se propagan a otros dispositivos casi instantáneamente. + +> **Nota**: `SyncState` es compatible con watchOS 9.0 y versiones posteriores. + +## Ejemplo de Uso + +### Modelo de Datos + +Supongamos que tenemos una estructura llamada `Settings` que se ajusta a `Codable`: + +```swift +struct Settings: Codable { + var text: String + var isShowingSheet: Bool + var isDarkMode: Bool +} +``` + +### Definir un SyncState + +Puede definir un `SyncState` extendiendo el objeto `Application` y declarando las propiedades de estado que deben sincronizarse: + +```swift +extension Application { + var settings: SyncState { + syncState( + initial: Settings( + text: "Hello, World!", + isShowingSheet: false, + isDarkMode: false + ), + id: "settings" + ) + } +} +``` + +### Manejo de Cambios Externos + +Para asegurarse de que la aplicación responda a los cambios externos de iCloud, anule la función `didChangeExternally` creando una subclase personalizada de `Application`: + +```swift +class CustomApplication: Application { + override func didChangeExternally(notification: Notification) { + super.didChangeExternally(notification: notification) + + DispatchQueue.main.async { + self.objectWillChange.send() + } + } +} +``` + +### Creación de Vistas para Modificar y Sincronizar el Estado + +En el siguiente ejemplo, tenemos dos vistas: `ContentView` y `ContentViewInnerView`. Estas vistas comparten y sincronizan el estado de `Settings` entre ellas. `ContentView` permite al usuario modificar el `text` y alternar `isDarkMode`, mientras que `ContentViewInnerView` muestra el mismo texto y lo actualiza cuando se toca. + +```swift +struct ContentView: View { + @SyncState(\.settings) private var settings: Settings + + var body: some View { + VStack { + TextField("", text: $settings.text) + + Button(settings.isDarkMode ? "Light" : "Dark") { + settings.isDarkMode.toggle() + } + + Button("Show") { settings.isShowingSheet = true } + } + .preferredColorScheme(settings.isDarkMode ? .dark : .light) + .sheet(isPresented: $settings.isShowingSheet, content: ContentViewInnerView.init) + } +} + +struct ContentViewInnerView: View { + @Slice(\.settings, \.text) private var text: String + + var body: some View { + Text("\(text)") + .onTapGesture { + text = Date().formatted() + } + } +} +``` + +### Configuración de la Aplicación + +Finalmente, configure la aplicación en la estructura `@main`. En la inicialización, promueva la aplicación personalizada, habilite el registro y cargue la dependencia de la tienda de iCloud para la sincronización: + +```swift +@main +struct SyncStateExampleApp: App { + init() { + Application + .promote(to: CustomApplication.self) + .logging(isEnabled: true) + .load(dependency: \.icloudStore) + } + + var body: some Scene { + WindowGroup { + ContentView() + } + } +} +``` + +### Habilitar el Almacenamiento de Clave-Valor de iCloud + +Para habilitar la sincronización de iCloud, asegúrese de seguir esta guía para habilitar la capacidad de almacenamiento de clave-valor de iCloud: [Comenzando a usar SyncState](starting-to-use-syncstate.md). + +### SyncState: Notas sobre el Almacenamiento de iCloud + +Aunque `SyncState` permite una sincronización fácil, es importante recordar las limitaciones de `NSUbiquitousKeyValueStore`: + +- **Límite de Almacenamiento**: Puede almacenar hasta 1 MB de datos en iCloud usando `NSUbiquitousKeyValueStore`, con un límite de tamaño de valor por clave de 1 MB. + +### Consideraciones sobre la Migración + +Al actualizar su modelo de datos, es importante tener en cuenta los posibles desafíos de migración, especialmente cuando se trabaja con datos persistentes utilizando **StoredState**, **FileState** o **SyncState**. Sin un manejo adecuado de la migración, cambios como agregar nuevos campos o modificar formatos de datos pueden causar problemas al cargar datos antiguos. + +Aquí hay algunos puntos clave a tener en cuenta: +- **Agregar Nuevos Campos no Opcionales**: Asegúrese de que los nuevos campos sean opcionales o tengan valores predeterminados para mantener la compatibilidad con versiones anteriores. +- **Manejo de Cambios en el Formato de Datos**: Si la estructura de su modelo cambia, implemente una lógica de decodificación personalizada para admitir formatos antiguos. +- **Versionado de sus Modelos**: Use un campo `version` en sus modelos para ayudar con las migraciones y aplicar la lógica según la versión de los datos. + +Para obtener más información sobre cómo administrar las migraciones y evitar posibles problemas, consulte la [Guía de Consideraciones sobre la Migración](migration-considerations.md). + +## Guía de Implementación de SyncState + +Para obtener instrucciones detalladas sobre cómo configurar iCloud y configurar SyncState en su proyecto, consulte la [Guía de Implementación de SyncState](syncstate-implementation.md). + +## Mejores Prácticas + +- **Use para Datos Pequeños y Críticos**: `SyncState` es ideal para sincronizar pequeñas e importantes piezas de estado, como las preferencias del usuario, la configuración o los indicadores de funciones. +- **Monitoree el Almacenamiento de iCloud**: Asegúrese de que su uso de `SyncState` se mantenga dentro de los límites de almacenamiento de iCloud para evitar problemas de sincronización de datos. +- **Maneje las Actualizaciones Externas**: Si su aplicación necesita responder a los cambios de estado iniciados en otro dispositivo, anule la función `didChangeExternally` para actualizar el estado de la aplicación en tiempo real. + +## Conclusión + +`SyncState` proporciona una forma poderosa de sincronizar pequeñas cantidades de estado de la aplicación en todos los dispositivos a través de iCloud. Es ideal para garantizar que las preferencias del usuario y otros datos clave permanezcan consistentes en todos los dispositivos que hayan iniciado sesión en la misma cuenta de iCloud. Para casos de uso más avanzados, explore otras características de **AppState**, como [SecureState](usage-securestate.md) y [FileState](usage-filestate.md). + +--- +Esta traducción fue generada automáticamente y puede contener errores. Si eres un hablante nativo, te agradecemos que contribuyas con correcciones a través de un Pull Request. diff --git a/documentation/fr/advanced-usage.md b/documentation/fr/advanced-usage.md new file mode 100644 index 0000000..6cb0e04 --- /dev/null +++ b/documentation/fr/advanced-usage.md @@ -0,0 +1,181 @@ +# Utilisation Avancée d'AppState + +Ce guide couvre des sujets avancés sur l'utilisation de **AppState**, y compris la création Juste-à-Temps, le préchargement des dépendances, la gestion efficace de l'état et des dépendances, et la comparaison de **AppState** avec l'**Environnement de SwiftUI**. + +## 1. Création Juste-à-Temps + +Les valeurs AppState, telles que `State`, `Dependency`, `StoredState` et `SyncState`, sont créées juste à temps. Cela signifie qu'elles ne sont instanciées que lors de leur premier accès, ce qui améliore l'efficacité et les performances de votre application. + +### Exemple + +```swift +extension Application { + var defaultState: State { + state(initial: 0) // La valeur n'est pas créée tant qu'elle n'est pas consultée + } +} +``` + +Dans cet exemple, `defaultState` n'est pas créé avant sa première consultation, ce qui optimise l'utilisation des ressources. + +## 2. Préchargement des Dépendances + +Dans certains cas, vous pouvez vouloir précharger certaines dépendances pour vous assurer qu'elles sont disponibles au démarrage de votre application. AppState fournit une fonction `load` qui précharge les dépendances. + +### Exemple + +```swift +extension Application { + var databaseClient: Dependency { + dependency(DatabaseClient()) + } +} + +// Précharger lors de l'initialisation de l'application +Application.load(dependency: \.databaseClient) +``` + +Dans cet exemple, `databaseClient` est préchargé lors de l'initialisation de l'application, garantissant qu'il est disponible lorsque nécessaire dans vos vues. + +## 3. Gestion de l'État et des Dépendances + +### 3.1 État et Dépendances Partagés à Travers l'Application + +Vous pouvez définir un état ou des dépendances partagés dans une partie de votre application et y accéder dans une autre partie en utilisant des identifiants uniques. + +### Exemple + +```swift +private extension Application { + var stateValue: State { + state(initial: 0, id: "stateValue") + } + + var dependencyValue: Dependency { + dependency(SomeType(), id: "dependencyValue") + } +} +``` + +Cela vous permet d'accéder au même `State` ou `Dependency` ailleurs en utilisant le même identifiant. + +```swift +private extension Application { + var theSameStateValue: State { + state(initial: 0, id: "stateValue") + } + + var theSameDependencyValue: Dependency { + dependency(SomeType(), id: "dependencyValue") + } +} +``` + +Bien que cette approche soit valide pour partager l'état et les dépendances à travers l'application en réutilisant le même `id` de chaîne, elle est généralement déconseillée. Elle repose sur la gestion manuelle de ces identifiants de chaîne, ce qui peut entraîner : +- Des collisions d'identifiants accidentelles si le même identifiant est utilisé pour différents états/dépendances prévus. +- Une difficulté à suivre où un état/dépendance est défini par rapport à son accès. +- Une réduction de la clarté et de la maintenabilité du code. +La valeur `initial` fournie dans les définitions ultérieures avec le même identifiant sera ignorée si l'état/dépendance a déjà été initialisé lors de son premier accès. Ce comportement est plus un effet secondaire du fonctionnement de la mise en cache basée sur l'identifiant dans AppState, plutôt qu'un modèle principal recommandé pour définir des données partagées. Préférez définir les états et les dépendances comme des propriétés calculées uniques dans les extensions `Application` (qui génèrent automatiquement des identifiants internes uniques si aucun `id` explicite n'est fourni à la méthode de fabrique). + +### 3.2 Accès Restreint à l'État et aux Dépendances + +Pour restreindre l'accès, utilisez un identifiant unique comme un UUID pour vous assurer que seules les bonnes parties de l'application peuvent accéder à des états ou des dépendances spécifiques. + +### Exemple + +```swift +private extension Application { + var restrictedState: State { + state(initial: nil, id: UUID().uuidString) + } + + var restrictedDependency: Dependency { + dependency(SomeType(), id: UUID().uuidString) + } +} +``` + +### 3.3 Identifiants Uniques pour les États et les Dépendances + +Lorsqu'aucun identifiant n'est fourni, AppState génère un identifiant par défaut basé sur l'emplacement dans le code source. Cela garantit que chaque `State` ou `Dependency` est unique et protégé contre les accès non intentionnels. + +### Exemple + +```swift +extension Application { + var defaultState: State { + state(initial: 0) // AppState génère un identifiant unique + } + + var defaultDependency: Dependency { + dependency(SomeType()) // AppState génère un identifiant unique + } +} +``` + +### 3.4 Accès Privé au Fichier pour l'État et les Dépendances + +Pour un accès encore plus restreint au sein du même fichier Swift, utilisez le niveau d'accès `fileprivate` pour protéger les états et les dépendances contre tout accès externe. + +### Exemple + +```swift +fileprivate extension Application { + var fileprivateState: State { + state(initial: 0) + } + + var fileprivateDependency: Dependency { + dependency(SomeType()) + } +} +``` + +### 3.5 Comprendre le Mécanisme de Stockage d'AppState + +AppState utilise un cache unifié pour stocker `State`, `Dependency`, `StoredState` et `SyncState`. Cela garantit que ces types de données sont gérés de manière efficace dans toute votre application. + +Par défaut, AppState attribue une valeur de nom "App", ce qui garantit que toutes les valeurs associées à un module sont liées à ce nom. Cela rend plus difficile l'accès à ces états et dépendances depuis d'autres modules. + +## 4. AppState vs Environnement de SwiftUI + +AppState et l'Environnement de SwiftUI offrent tous deux des moyens de gérer l'état partagé et les dépendances dans votre application, mais ils diffèrent par leur portée, leurs fonctionnalités et leurs cas d'utilisation. + +### 4.1 Environnement de SwiftUI + +L'Environnement de SwiftUI est un mécanisme intégré qui vous permet de transmettre des données partagées à travers une hiérarchie de vues. Il est idéal pour transmettre des données auxquelles de nombreuses vues ont besoin d'accéder, mais il présente des limites en ce qui concerne la gestion d'états plus complexes. + +**Points forts :** +- Simple à utiliser et bien intégré avec SwiftUI. +- Idéal pour les données légères qui doivent être partagées entre plusieurs vues dans une hiérarchie. + +**Limites :** +- Les données ne sont disponibles que dans la hiérarchie de vues spécifique. L'accès aux mêmes données à travers différentes hiérarchies de vues n'est pas possible sans travail supplémentaire. +- Moins de contrôle sur la sécurité des threads et la persistance par rapport à AppState. +- Absence de mécanismes de persistance ou de synchronisation intégrés. + +### 4.2 AppState + +AppState fournit un système plus puissant et flexible pour la gestion de l'état à travers toute l'application, avec des capacités de sécurité des threads, de persistance et d'injection de dépendances. + +**Points forts :** +- Gestion centralisée de l'état, accessible dans toute l'application, pas seulement dans des hiérarchies de vues spécifiques. +- Mécanismes de persistance intégrés (`StoredState`, `FileState` et `SyncState`). +- Garanties de sécurité des types et des threads, assurant que l'état est accédé et modifié correctement. +- Peut gérer une gestion d'état et de dépendances plus complexe. + +**Limites :** +- Nécessite plus de configuration par rapport à l'Environnement de SwiftUI. +- Un peu moins intégré avec SwiftUI par rapport à Environment, bien qu'il fonctionne toujours bien dans les applications SwiftUI. + +### 4.3 Quand Utiliser Chaque + +- Utilisez l'**Environnement de SwiftUI** lorsque vous avez des données simples qui doivent être partagées à travers une hiérarchie de vues, comme les paramètres utilisateur ou les préférences de thème. +- Utilisez **AppState** lorsque vous avez besoin d'une gestion centralisée de l'état, de la persistance ou d'un état plus complexe qui doit être accessible dans toute l'application. + +## Conclusion + +En utilisant ces techniques avancées, telles que la création juste à temps, le préchargement, la gestion de l'état et des dépendances, et en comprenant les différences entre AppState et l'Environnement de SwiftUI, vous pouvez créer des applications efficaces et économes en ressources avec **AppState**. + +--- +Cette traduction a été générée automatiquement et peut contenir des erreurs. Si vous êtes un locuteur natif, nous vous serions reconnaissants de contribuer avec des corrections via une Pull Request. diff --git a/documentation/fr/best-practices.md b/documentation/fr/best-practices.md new file mode 100644 index 0000000..477f20e --- /dev/null +++ b/documentation/fr/best-practices.md @@ -0,0 +1,65 @@ +# Meilleures Pratiques pour l'Utilisation d'AppState + +Ce guide fournit les meilleures pratiques pour vous aider à utiliser AppState de manière efficace et efficiente dans vos applications Swift. + +## 1. Utilisez AppState avec Parcimonie + +AppState est polyvalent et convient à la fois à la gestion de l'état partagé et localisé. Il est idéal pour les données qui doivent être partagées entre plusieurs composants, persister à travers les vues ou les sessions utilisateur, ou être gérées au niveau du composant. Cependant, une utilisation excessive peut entraîner une complexité inutile. + +### Recommandation : +- Utilisez AppState pour les données qui ont vraiment besoin d'être à l'échelle de l'application, partagées entre des composants distants, ou qui nécessitent les fonctionnalités spécifiques de persistance/synchronisation d'AppState. +- Pour l'état qui est local à une seule vue SwiftUI ou à une hiérarchie de vues proche, préférez les outils intégrés de SwiftUI comme `@State`, `@StateObject`, `@ObservedObject`, ou `@EnvironmentObject`. + +## 2. Maintenez un AppState Propre + +À mesure que votre application s'étend, votre AppState peut devenir plus complexe. Révisez et refactorisez régulièrement votre AppState pour supprimer les états et les dépendances inutilisés. Garder votre AppState propre le rend plus simple à comprendre, à maintenir et à tester. + +### Recommandation : +- Auditez périodiquement votre AppState pour détecter les états et les dépendances inutilisés ou redondants. +- Refactorisez les grandes structures AppState pour les garder propres et gérables. + +## 3. Testez Votre AppState + +Comme d'autres aspects de votre application, assurez-vous que votre AppState est testé de manière approfondie. Utilisez des dépendances fictives pour isoler votre AppState des dépendances externes pendant les tests, et confirmez que chaque partie de votre application se comporte comme prévu. + +### Recommandation : +- Utilisez XCTest ou des frameworks similaires pour tester le comportement et les interactions d'AppState. +- Simulez ou créez des stubs de dépendances pour vous assurer que les tests d'AppState sont isolés et fiables. + +## 4. Utilisez la Fonctionnalité de Slice à Bon Escient + +La fonctionnalité `Slice` vous permet d'accéder à des parties spécifiques de l'état d'un AppState, ce qui est utile pour gérer des structures d'état volumineuses et complexes. Cependant, utilisez cette fonctionnalité à bon escient pour maintenir un AppState propre et bien organisé, en évitant les slices inutiles qui fragmentent la gestion de l'état. + +### Recommandation : +- N'utilisez `Slice` que pour les états volumineux ou imbriqués où l'accès à des composants individuels est nécessaire. +- Évitez de sur-slicer l'état, ce qui peut entraîner de la confusion et une gestion de l'état fragmentée. + +## 5. Utilisez des Constantes pour les Valeurs Statiques + +La fonctionnalité `@Constant` vous permet de définir des constantes en lecture seule qui peuvent être partagées dans toute votre application. Elle est utile pour les valeurs qui restent inchangées tout au long du cycle de vie de votre application, comme les paramètres de configuration ou les données prédéfinies. Les constantes garantissent que ces valeurs ne sont pas modifiées involontairement. + +### Recommandation : +- Utilisez `@Constant` pour les valeurs qui restent inchangées, telles que les configurations de l'application, les variables d'environnement ou les références statiques. + +## 6. Modularisez Votre AppState + +Pour les applications plus volumineuses, envisagez de diviser votre AppState en modules plus petits et plus gérables. Chaque module peut avoir son propre état et ses propres dépendances, qui sont ensuite composés dans l'AppState global. Cela peut rendre votre AppState plus facile à comprendre, à tester et à maintenir. + +### Recommandation : +- Organisez vos extensions `Application` dans des fichiers Swift distincts ou même des modules Swift distincts, regroupés par fonctionnalité ou par domaine. Cela modularise naturellement les définitions. +- Lors de la définition d'états ou de dépendances à l'aide de méthodes de fabrique comme `state(initial:feature:id:)`, utilisez le paramètre `feature` pour fournir un espace de noms, par exemple, `state(initial: 0, feature: "UserProfile", id: "score")`. Cela aide à organiser et à prévenir les collisions d'ID si des ID manuels sont utilisés. +- Évitez de créer plusieurs instances de `Application`. Tenez-vous-en à l'extension et à l'utilisation du singleton partagé (`Application.shared`). + +## 7. Tirez Parti de la Création Juste-à-Temps + +Les valeurs AppState sont créées juste à temps, ce qui signifie qu'elles ne sont instanciées que lorsqu'on y accède. Cela optimise l'utilisation de la mémoire et garantit que les valeurs AppState ne sont créées que lorsque cela est nécessaire. + +### Recommandation : +- Permettez aux valeurs AppState d'être créées juste à temps plutôt que de précharger inutilement tous les états et dépendances. + +## Conclusion + +Chaque application est unique, donc ces meilleures pratiques peuvent ne pas convenir à toutes les situations. Tenez toujours compte des exigences spécifiques de votre application lorsque vous décidez comment utiliser AppState, et efforcez-vous de maintenir votre gestion de l'état propre, efficace et bien testée. + +--- +Cette traduction a été générée automatiquement et peut contenir des erreurs. Si vous êtes un locuteur natif, nous vous serions reconnaissants de contribuer avec des corrections via une Pull Request. diff --git a/documentation/fr/contributing.md b/documentation/fr/contributing.md new file mode 100644 index 0000000..d221948 --- /dev/null +++ b/documentation/fr/contributing.md @@ -0,0 +1,63 @@ +# Contribuer à AppState + +Merci d'envisager de contribuer à **AppState** ! Vos contributions aident à améliorer ce projet pour tout le monde. + +## Comment Contribuer + +### 1. Signaler des Bugs + +Si vous rencontrez des bugs, veuillez ouvrir une issue sur GitHub. Lorsque vous signalez un bug, veuillez inclure : + +- Un titre clair et descriptif. +- Une description détaillée du bug, y compris les étapes pour le reproduire. +- Le comportement attendu et ce qui s'est réellement passé. +- La version de **AppState** que vous utilisez. +- Toutes les captures d'écran ou journaux pertinents. + +### 2. Suggérer des Fonctionnalités + +Les nouvelles idées sont les bienvenues ! Si vous avez une fonctionnalité que vous aimeriez voir ajoutée à **AppState**, veuillez ouvrir une issue et décrire : + +- Le problème que la fonctionnalité résoudrait. +- Comment vous pensez que la fonctionnalité devrait fonctionner. +- Tout contexte ou exemple supplémentaire qui aiderait à illustrer votre idée. + +### 3. Soumettre des Pull Requests + +Si vous souhaitez contribuer du code à **AppState**, suivez ces étapes : + +1. **Forker le Dépôt**: Créez un fork personnel du dépôt **AppState** sur GitHub. +2. **Cloner Votre Fork**: Clonez votre fork sur votre machine locale : + ```bash + git clone https://github.com/your-username/AppState.git + ``` +3. **Créer une Nouvelle Branche**: Créez une nouvelle branche pour votre fonctionnalité ou votre correction de bug : + ```bash + git checkout -b ma-branche-de-fonctionnalite + ``` +4. **Effectuer des Modifications**: Implémentez vos modifications dans la nouvelle branche. +5. **Tester Vos Modifications**: Assurez-vous que vos modifications passent tous les tests. Ajoutez de nouveaux tests si nécessaire. +6. **Commiter Vos Modifications**: Commitez vos modifications avec un message de commit descriptif : + ```bash + git commit -m "Ajouter ma nouvelle fonctionnalité" + ``` +7. **Pousser vers GitHub**: Poussez votre branche vers votre fork GitHub : + ```bash + git push origin ma-branche-de-fonctionnalite + ``` +8. **Créer une Pull Request**: Allez sur le dépôt **AppState** sur GitHub et créez une pull request à partir de votre branche. + +### 4. Style de Code + +Veuillez suivre les directives de style de codage utilisées dans le projet **AppState**. Un style de code cohérent aide à rendre la base de code plus maintenable et plus facile à examiner. + +### 5. Licence + +En contribuant à **AppState**, vous acceptez que vos contributions soient sous licence sous la même licence que le projet : [LICENCE](https://github.com/0xLeif/AppState/blob/main/LICENSE). + +## Merci ! + +Vos contributions sont très précieuses et appréciées. Merci d'aider à améliorer **AppState** ! + +--- +Cette traduction a été générée automatiquement et peut contenir des erreurs. Si vous êtes un locuteur natif, nous vous serions reconnaissants de contribuer avec des corrections via une Pull Request. diff --git a/documentation/fr/faq.md b/documentation/fr/faq.md new file mode 100644 index 0000000..3bcc3f0 --- /dev/null +++ b/documentation/fr/faq.md @@ -0,0 +1,43 @@ +# Foire Aux Questions + +Cette courte FAQ répond aux questions courantes que les développeurs peuvent se poser lors de l'utilisation de **AppState**. + +## Comment réinitialiser une valeur d'état ? + +Pour les états persistants comme `StoredState`, `FileState` et `SyncState`, vous pouvez les réinitialiser à leurs valeurs initiales en utilisant les fonctions statiques `reset` sur le type `Application`. + +Par exemple, pour réinitialiser un `StoredState` : +```swift +extension Application { + var hasCompletedOnboarding: StoredState { storedState(initial: false, id: "onboarding_complete") } +} + +// Quelque part dans votre code +Application.reset(storedState: \.hasCompletedOnboarding) +``` +Cela réinitialisera la valeur dans `UserDefaults` à `false`. Des fonctions `reset` similaires existent pour `FileState`, `SyncState` et `SecureState`. + +Pour un `State` non persistant, vous pouvez le réinitialiser de la même manière que les états persistants : +```swift +extension Application { + var counter: State { state(initial: 0) } +} + +// Quelque part dans votre code +Application.reset(\.counter) +``` + +## Puis-je utiliser AppState avec des tâches asynchrones ? + +Oui. Les valeurs de `State` et de dépendance sont thread-safe et fonctionnent de manière transparente avec Swift Concurrency. Vous pouvez y accéder et les modifier à l'intérieur des fonctions `async` sans verrouillage supplémentaire. + +## Où dois-je définir les états et les dépendances ? + +Conservez tous vos états et dépendances dans des extensions de `Application`. Cela garantit une source unique de vérité et facilite la découverte de toutes les valeurs disponibles. + +## AppState est-il compatible avec Combine ? + +Vous pouvez utiliser AppState avec Combine en pontant les changements de `State` vers des publicateurs. Observez une valeur `State` et envoyez des mises à jour via un `PassthroughSubject` ou un autre publicateur Combine si nécessaire. + +--- +Cette traduction a été générée automatiquement et peut contenir des erreurs. Si vous êtes un locuteur natif, nous vous serions reconnaissants de contribuer avec des corrections via une Pull Request. diff --git a/documentation/fr/installation.md b/documentation/fr/installation.md new file mode 100644 index 0000000..b047dcf --- /dev/null +++ b/documentation/fr/installation.md @@ -0,0 +1,87 @@ +# Guide d'Installation + +Ce guide vous expliquera comment installer **AppState** dans votre projet Swift à l'aide du Swift Package Manager. + +## Swift Package Manager + +**AppState** peut être facilement intégré à votre projet à l'aide du Swift Package Manager. Suivez les étapes ci-dessous pour ajouter **AppState** en tant que dépendance. + +### Étape 1 : Mettez à jour votre fichier `Package.swift` + +Ajoutez **AppState** à la section `dependencies` de votre fichier `Package.swift` : + +```swift +dependencies: [ + .package(url: "https://github.com/0xLeif/AppState.git", from: "2.2.0") +] +``` + +### Étape 2 : Ajoutez AppState à votre cible + +Incluez AppState dans les dépendances de votre cible : + +```swift +.target( + name: "YourTarget", + dependencies: ["AppState"] +) +``` + +### Étape 3 : Compilez votre projet + +Une fois que vous avez ajouté AppState à votre fichier `Package.swift`, compilez votre projet pour récupérer la dépendance et l'intégrer à votre base de code. + +``` +swift build +``` + +### Étape 4 : Importez AppState dans votre code + +Maintenant, vous pouvez commencer à utiliser AppState dans votre projet en l'important en haut de vos fichiers Swift : + +```swift +import AppState +``` + +## Xcode + +Si vous préférez ajouter **AppState** directement via Xcode, suivez ces étapes : + +### Étape 1 : Ouvrez votre projet Xcode + +Ouvrez votre projet ou espace de travail Xcode. + +### Étape 2 : Ajoutez une dépendance de package Swift + +1. Accédez au navigateur de projet et sélectionnez votre fichier de projet. +2. Dans l'éditeur de projet, sélectionnez votre cible, puis allez à l'onglet "Swift Packages". +3. Cliquez sur le bouton "+" pour ajouter une dépendance de package. + +### Étape 3 : Entrez l'URL du dépôt + +Dans la boîte de dialogue "Choose Package Repository", entrez l'URL suivante : `https://github.com/0xLeif/AppState.git` + +Puis cliquez sur "Suivant". + +### Étape 4 : Spécifiez la version + +Choisissez la version que vous souhaitez utiliser. Il est recommandé de sélectionner l'option "Up to Next Major Version" et de spécifier `2.0.0` comme limite inférieure. Puis cliquez sur "Suivant". + +### Étape 5 : Ajoutez le package + +Xcode récupérera le package et vous présentera des options pour ajouter **AppState** à votre cible. Assurez-vous de sélectionner la bonne cible et cliquez sur "Terminer". + +### Étape 6 : Importez `AppState` dans votre code + +Vous pouvez maintenant importer **AppState** en haut de vos fichiers Swift : + +```swift +import AppState +``` + +## Prochaines Étapes + +Une fois AppState installé, vous pouvez passer à l'[Aperçu de l'utilisation](usage-overview.md) pour voir comment implémenter les fonctionnalités clés dans votre projet. + +--- +Cette traduction a été générée automatiquement et peut contenir des erreurs. Si vous êtes un locuteur natif, nous vous serions reconnaissants de contribuer avec des corrections via une Pull Request. diff --git a/documentation/fr/migration-considerations.md b/documentation/fr/migration-considerations.md new file mode 100644 index 0000000..1cfbe47 --- /dev/null +++ b/documentation/fr/migration-considerations.md @@ -0,0 +1,81 @@ +# Considérations sur la Migration + +Lorsque vous mettez à jour votre modèle de données, en particulier pour les données persistantes ou synchronisées, vous devez gérer la compatibilité ascendante pour éviter les problèmes potentiels lors du chargement de données anciennes. Voici quelques points importants à garder à l'esprit : + +## 1. Ajout de Champs non Optionnels +Si vous ajoutez de nouveaux champs non optionnels à votre modèle, le décodage des anciennes données (qui ne contiendront pas ces champs) peut échouer. Pour éviter cela : +- Envisagez de donner des valeurs par défaut aux nouveaux champs. +- Rendez les nouveaux champs optionnels pour garantir la compatibilité avec les anciennes versions de votre application. + +### Exemple : +```swift +struct Settings: Codable { + var text: String + var isDarkMode: Bool + var newField: String? // Le nouveau champ est optionnel +} +``` + +## 2. Changements de Format de Données +Si vous modifiez la structure d'un modèle (par exemple, en changeant un type de `Int` à `String`), le processus de décodage peut échouer lors de la lecture des anciennes données. Planifiez une migration en douceur en : +- Créant une logique de migration pour convertir les anciens formats de données vers la nouvelle structure. +- Utilisant l'initialiseur personnalisé de `Decodable` pour gérer les anciennes données et les mapper sur votre nouveau modèle. + +### Exemple : +```swift +struct Settings: Codable { + var text: String + var isDarkMode: Bool + var version: Int + + // Logique de décodage personnalisée pour les anciennes versions + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.text = try container.decode(String.self, forKey: .text) + self.isDarkMode = try container.decode(Bool.self, forKey: .isDarkMode) + self.version = (try? container.decode(Int.self, forKey: .version)) ?? 1 // Valeur par défaut pour les anciennes données + } +} +``` + +## 3. Gestion des Champs Supprimés ou Obsolètes +Si vous supprimez un champ du modèle, assurez-vous que les anciennes versions de l'application peuvent toujours décoder les nouvelles données sans planter. Vous pouvez : +- Ignorer les champs supplémentaires lors du décodage. +- Utiliser des décodeurs personnalisés pour gérer les anciennes données et gérer correctement les champs obsolètes. + +## 4. Versionnement de Vos Modèles + +Le versionnement de vos modèles vous permet de gérer les changements dans votre structure de données au fil du temps. En conservant un numéro de version dans votre modèle, vous pouvez facilement mettre en œuvre une logique de migration pour convertir les anciens formats de données en nouveaux. Cette approche garantit que votre application peut gérer les anciennes structures de données tout en passant en douceur aux nouvelles versions. + +- **Pourquoi le Versionnement est Important** : Lorsque les utilisateurs mettent à jour leur application, ils peuvent encore avoir des données plus anciennes persistantes sur leurs appareils. Le versionnement aide votre application à reconnaître le format des données et à appliquer la logique de migration correcte. +- **Comment l'Utiliser** : Ajoutez un champ `version` à votre modèle et vérifiez-le pendant le processus de décodage pour déterminer si une migration est nécessaire. + +### Exemple : +```swift +struct Settings: Codable { + var version: Int + var text: String + var isDarkMode: Bool + + // Gérer la logique de décodage spécifique à la version + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.version = try container.decode(Int.self, forKey: .version) + self.text = try container.decode(String.self, forKey: .text) + self.isDarkMode = try container.decode(Bool.self, forKey: .isDarkMode) + + // Si vous migrez depuis une ancienne version, appliquez les transformations nécessaires ici + if version < 2 { + // Migrer les anciennes données vers le nouveau format + } + } +} +``` + +- **Meilleure Pratique** : Commencez avec un champ `version` dès le début. Chaque fois que vous mettez à jour la structure de votre modèle, incrémentez la version et gérez la logique de migration nécessaire. + +## 5. Test de la Migration +Testez toujours votre migration de manière approfondie en simulant le chargement d'anciennes données avec de nouvelles versions de votre modèle pour vous assurer que votre application se comporte comme prévu. + +--- +Cette traduction a été générée automatiquement et peut contenir des erreurs. Si vous êtes un locuteur natif, nous vous serions reconnaissants de contribuer avec des corrections via une Pull Request. diff --git a/documentation/fr/starting-to-use-syncstate.md b/documentation/fr/starting-to-use-syncstate.md new file mode 100644 index 0000000..dbe5734 --- /dev/null +++ b/documentation/fr/starting-to-use-syncstate.md @@ -0,0 +1,25 @@ +Pour utiliser SyncState, vous devrez d'abord configurer les fonctionnalités et les autorisations iCloud dans votre projet Xcode. Voici une introduction pour vous guider tout au long du processus : + +### Configuration des fonctionnalités iCloud : + +1. Ouvrez votre projet Xcode et ajustez les identifiants de lot pour les cibles macOS et iOS afin qu'ils correspondent aux vôtres. +2. Ensuite, vous devez ajouter la fonctionnalité iCloud à votre projet. Pour ce faire, sélectionnez votre projet dans le navigateur de projets, puis sélectionnez votre cible. Dans la barre d'onglets en haut de la zone de l'éditeur, cliquez sur « Signing & Capabilities ». +3. Dans le volet Capacités, activez iCloud en cliquant sur le commutateur de la ligne iCloud. Vous devriez voir le commutateur passer en position Activé. +4. Une fois que vous avez activé iCloud, vous devez activer le stockage clé-valeur. Vous pouvez le faire en cochant la case « Stockage clé-valeur ». + +### Mise à jour des autorisations : + +1. Vous devrez maintenant mettre à jour votre fichier d'autorisations. Ouvrez le fichier d'autorisations de votre cible. +2. Assurez-vous que la valeur du magasin clé-valeur iCloud correspond à votre ID de magasin clé-valeur unique. Votre ID unique doit respecter le format `$(TeamIdentifierPrefix)`. La valeur par défaut doit être quelque chose comme `$(TeamIdentifierPrefix)$(CFBundleIdentifier)`. C'est très bien pour les applications à plate-forme unique, mais si votre application se trouve sur plusieurs systèmes d'exploitation Apple, il est important que les parties de l'ID du magasin clé-valeur soient les mêmes pour les deux cibles. + +### Configuration des appareils : + +En plus de configurer le projet lui-même, vous devez également préparer les appareils qui exécuteront le projet. + +- Assurez-vous qu'iCloud Drive est activé sur les appareils iOS et macOS. +- Connectez-vous aux deux appareils avec le même compte iCloud. + +Si vous avez des questions ou rencontrez des problèmes, n'hésitez pas à nous contacter ou à soumettre un problème. + +--- +Cette traduction a été générée automatiquement et peut contenir des erreurs. Si vous êtes un locuteur natif, nous vous serions reconnaissants de contribuer avec des corrections via une Pull Request. diff --git a/documentation/fr/syncstate-implementation.md b/documentation/fr/syncstate-implementation.md new file mode 100644 index 0000000..aa56239 --- /dev/null +++ b/documentation/fr/syncstate-implementation.md @@ -0,0 +1,84 @@ +# Implémentation de SyncState dans AppState + +Ce guide explique comment configurer SyncState dans votre application, y compris la configuration des capacités iCloud et la compréhension des limitations potentielles. + +## 1. Configuration des Capacités iCloud + +Pour utiliser SyncState dans votre application, vous devez d'abord activer iCloud dans votre projet et configurer le stockage clé-valeur. + +### Étapes pour Activer iCloud et le Stockage Clé-Valeur : + +1. Ouvrez votre projet Xcode et accédez aux paramètres de votre projet. +2. Sous l'onglet "Signing & Capabilities", sélectionnez votre cible (iOS ou macOS). +3. Cliquez sur le bouton "+ Capability" et choisissez "iCloud" dans la liste. +4. Activez l'option "Key-Value storage" dans les paramètres iCloud. Cela permet à votre application de stocker et de synchroniser de petites quantités de données à l'aide d'iCloud. + +### Configuration du Fichier d'Autorisations : + +1. Dans votre projet Xcode, trouvez ou créez le **fichier d'autorisations** pour votre application. +2. Assurez-vous que le stockage clé-valeur iCloud est correctement configuré dans le fichier d'autorisations avec le bon conteneur iCloud. + +Exemple dans le fichier d'autorisations : + +```xml +com.apple.developer.ubiquity-kvstore-identifier +$(TeamIdentifierPrefix)com.yourdomain.app +``` + +Assurez-vous que la valeur de la chaîne correspond au conteneur iCloud associé à votre projet. + +## 2. Utilisation de SyncState dans Votre Application + +Une fois iCloud activé, vous pouvez utiliser `SyncState` dans votre application pour synchroniser les données entre les appareils. + +### Exemple d'Utilisation de SyncState : + +```swift +import AppState +import SwiftUI + +extension Application { + var syncValue: SyncState { + syncState(id: "syncValue") + } +} + +struct ContentView: View { + @SyncState(\.syncValue) private var syncValue: Int? + + var body: some View { + VStack { + if let syncValue = syncValue { + Text("SyncValue: \(syncValue)") + } else { + Text("No SyncValue") + } + + Button("Update SyncValue") { + syncValue = Int.random(in: 0..<100) + } + } + } +} +``` + +Dans cet exemple, l'état de synchronisation sera enregistré sur iCloud et synchronisé sur tous les appareils connectés au même compte iCloud. + +## 3. Limitations et Meilleures Pratiques + +SyncState utilise `NSUbiquitousKeyValueStore`, qui présente certaines limitations : + +- **Limite de Stockage** : SyncState est conçu pour de petites quantités de données. La limite de stockage totale est de 1 Mo, et chaque paire clé-valeur est limitée à environ 1 Mo. +- **Synchronisation** : Les modifications apportées à SyncState ne sont pas synchronisées instantanément entre les appareils. Il peut y avoir un léger délai de synchronisation, et la synchronisation iCloud peut parfois être affectée par les conditions du réseau. + +### Meilleures Pratiques : + +- **Utilisez SyncState pour les Petites Données** : Assurez-vous que seules de petites données comme les préférences utilisateur ou les paramètres sont synchronisées à l'aide de SyncState. +- **Gérez les Échecs de SyncState avec Élégance** : Utilisez des valeurs par défaut ou des mécanismes de gestion des erreurs pour tenir compte des retards ou des échecs de synchronisation potentiels. + +## 4. Conclusion + +En configurant correctement iCloud et en comprenant les limitations de SyncState, vous pouvez tirer parti de sa puissance pour synchroniser des données entre les appareils. Assurez-vous de n'utiliser SyncState que pour de petites données critiques afin d'éviter les problèmes potentiels liés aux limites de stockage d'iCloud. + +--- +Cette traduction a été générée automatiquement et peut contenir des erreurs. Si vous êtes un locuteur natif, nous vous serions reconnaissants de contribuer avec des corrections via une Pull Request. diff --git a/documentation/fr/usage-constant.md b/documentation/fr/usage-constant.md new file mode 100644 index 0000000..8f84dca --- /dev/null +++ b/documentation/fr/usage-constant.md @@ -0,0 +1,87 @@ +# Utilisation de Constant + +`Constant` dans la bibliothèque **AppState** fournit un accès en lecture seule aux valeurs de l'état de votre application. Il fonctionne de manière similaire à `Slice`, mais garantit que les valeurs consultées sont immuables. Cela rend `Constant` idéal pour accéder à des valeurs qui pourraient autrement être mutables mais qui doivent rester en lecture seule dans certains contextes. + +## Fonctionnalités Clés + +- **Accès en Lecture Seule**: Les constantes permettent d'accéder à un état mutable, mais les valeurs ne peuvent pas être modifiées. +- **Portée Limitée à l'Application**: Comme `Slice`, `Constant` est défini dans l'extension `Application` et sa portée est limitée à l'accès à des parties spécifiques de l'état. +- **Thread-Safe**: `Constant` garantit un accès sécurisé à l'état dans les environnements concurrents. + +## Exemple d'Utilisation + +### Définir une Constante dans l'Application + +Voici comment définir une `Constant` dans l'extension `Application` pour accéder à une valeur en lecture seule : + +```swift +import AppState +import SwiftUI + +struct ExampleValue { + var username: String? + var isLoading: Bool + let value: String + var mutableValue: String +} + +extension Application { + var exampleValue: State { + state( + initial: ExampleValue( + username: "Leif", + isLoading: false, + value: "value", + mutableValue: "" + ) + ) + } +} +``` + +### Accéder à la Constante dans une Vue SwiftUI + +Dans une vue SwiftUI, vous pouvez utiliser le property wrapper `@Constant` pour accéder à l'état constant en lecture seule : + +```swift +import AppState +import SwiftUI + +struct ExampleView: View { + @Constant(\.exampleValue, \.value) var constantValue: String + + var body: some View { + Text("Valeur Constante : \(constantValue)") + } +} +``` + +### Accès en Lecture Seule à un État Mutable + +Même si la valeur est mutable ailleurs, lorsqu'elle est consultée via `@Constant`, la valeur devient immuable : + +```swift +import AppState +import SwiftUI + +struct ExampleView: View { + @Constant(\.exampleValue, \.mutableValue) var constantMutableValue: String + + var body: some View { + Text("Valeur Mutable en Lecture Seule : \(constantMutableValue)") + } +} +``` + +## Meilleures Pratiques + +- **Utiliser pour un Accès en Lecture Seule**: Utilisez `Constant` pour accéder aux parties de l'état qui ne doivent pas être modifiées dans certains contextes, même si elles sont mutables ailleurs. +- **Thread-Safe**: Comme les autres composants d'AppState, `Constant` garantit un accès thread-safe à l'état. +- **Utiliser `OptionalConstant` pour les Valeurs Optionnelles**: Si la partie de l'état que vous consultez peut être `nil`, utilisez `OptionalConstant` pour gérer en toute sécurité l'absence de valeur. + +## Conclusion + +`Constant` et `OptionalConstant` offrent un moyen efficace d'accéder à des parties spécifiques de l'état de votre application en lecture seule. Ils garantissent que les valeurs qui pourraient autrement être mutables sont traitées comme immuables lorsqu'elles sont consultées dans une vue, assurant ainsi la sécurité et la clarté de votre code. + +--- +Cette traduction a été générée automatiquement et peut contenir des erreurs. Si vous êtes un locuteur natif, nous vous serions reconnaissants de contribuer avec des corrections via une Pull Request. diff --git a/documentation/fr/usage-filestate.md b/documentation/fr/usage-filestate.md new file mode 100644 index 0000000..83a9377 --- /dev/null +++ b/documentation/fr/usage-filestate.md @@ -0,0 +1,96 @@ +# Utilisation de FileState + +`FileState` est un composant de la bibliothèque **AppState** qui vous permet de stocker et de récupérer des données persistantes à l'aide du système de fichiers. Il est utile pour stocker des données volumineuses ou des objets complexes qui doivent être sauvegardés entre les lancements de l'application et restaurés en cas de besoin. + +## Fonctionnalités Clés + +- **Stockage Persistant** : Les données stockées à l'aide de `FileState` persistent entre les lancements de l'application. +- **Gestion des Données Volumineuses** : Contrairement à `StoredState`, `FileState` est idéal pour gérer des données plus volumineuses ou plus complexes. +- **Thread-Safe** : Comme les autres composants d'AppState, `FileState` garantit un accès sécurisé aux données dans les environnements concurrents. + +## Exemple d'Utilisation + +### Stocker et Récupérer des Données avec FileState + +Voici comment définir un `FileState` dans l'extension `Application` pour stocker et récupérer un objet volumineux : + +```swift +import AppState +import SwiftUI + +struct UserProfile: Codable { + var name: String + var age: Int +} + +extension Application { + @MainActor + var userProfile: FileState { + fileState(initial: UserProfile(name: "Guest", age: 25), filename: "userProfile") + } +} + +struct FileStateExampleView: View { + @FileState(\.userProfile) var userProfile: UserProfile + + var body: some View { + VStack { + Text("Nom : \(userProfile.name), Âge : \(userProfile.age)") + Button("Mettre à jour le profil") { + userProfile = UserProfile(name: "UpdatedName", age: 30) + } + } + } +} +``` + +### Gérer des Données Volumineuses avec FileState + +Lorsque vous devez gérer des ensembles de données ou des objets plus volumineux, `FileState` garantit que les données sont stockées efficacement dans le système de fichiers de l'application. Ceci est utile pour des scénarios comme la mise en cache ou le stockage hors ligne. + +```swift +import AppState +import SwiftUI + +extension Application { + @MainActor + var largeDataset: FileState<[String]> { + fileState(initial: [], filename: "largeDataset") + } +} + +struct LargeDataView: View { + @FileState(\.largeDataset) var largeDataset: [String] + + var body: some View { + List(largeDataset, id: \.self) { item in + Text(item) + } + } +} +``` + +### Considérations sur la Migration + +Lors de la mise à jour de votre modèle de données, il est important de tenir compte des défis potentiels de la migration, en particulier lorsque vous travaillez avec des données persistantes à l'aide de **StoredState**, **FileState** ou **SyncState**. Sans une gestion appropriée de la migration, des changements tels que l'ajout de nouveaux champs ou la modification des formats de données peuvent entraîner des problèmes lors du chargement des anciennes données. + +Voici quelques points clés à garder à l'esprit : +- **Ajout de Nouveaux Champs Non Optionnels** : Assurez-vous que les nouveaux champs sont soit optionnels, soit qu'ils ont des valeurs par défaut pour maintenir la compatibilité ascendante. +- **Gestion des Changements de Format de Données** : Si la structure de votre modèle change, implémentez une logique de décodage personnalisée pour prendre en charge les anciens formats. +- **Versionnement de Vos Modèles** : Utilisez un champ `version` dans vos modèles pour aider aux migrations et appliquer une logique en fonction de la version des données. + +Pour en savoir plus sur la gestion des migrations et éviter les problèmes potentiels, consultez le [Guide des Considérations sur la Migration](migration-considerations.md). + + +## Meilleures Pratiques + +- **Utiliser pour les Données Volumineuses ou Complexes** : Si vous stockez des données volumineuses ou des objets complexes, `FileState` est préférable à `StoredState`. +- **Accès Thread-Safe** : Comme les autres composants de **AppState**, `FileState` garantit que les données sont accessibles en toute sécurité même lorsque plusieurs tâches interagissent avec les données stockées. +- **Combiner avec Codable** : Lorsque vous travaillez avec des types de données personnalisés, assurez-vous qu'ils sont conformes à `Codable` pour simplifier l'encodage et le décodage vers et depuis le système de fichiers. + +## Conclusion + +`FileState` est un outil puissant pour gérer les données persistantes dans votre application, vous permettant de stocker et de récupérer des objets plus volumineux ou plus complexes de manière thread-safe et persistante. Il fonctionne de manière transparente avec le protocole `Codable` de Swift, garantissant que vos données peuvent être facilement sérialisées et désérialisées pour un stockage à long terme. + +--- +Cette traduction a été générée automatiquement et peut contenir des erreurs. Si vous êtes un locuteur natif, nous vous serions reconnaissants de contribuer avec des corrections via une Pull Request. diff --git a/documentation/fr/usage-observeddependency.md b/documentation/fr/usage-observeddependency.md new file mode 100644 index 0000000..0ae34f0 --- /dev/null +++ b/documentation/fr/usage-observeddependency.md @@ -0,0 +1,135 @@ +# Utilisation de ObservedDependency + +`ObservedDependency` est un composant de la bibliothèque **AppState** qui vous permet d'utiliser des dépendances conformes à `ObservableObject`. Ceci est utile lorsque vous souhaitez que la dépendance notifie vos vues SwiftUI des changements, rendant vos vues réactives et dynamiques. + +## Fonctionnalités Clés + +- **Dépendances Observables** : Utilisez des dépendances conformes à `ObservableObject`, permettant à la dépendance de mettre à jour automatiquement vos vues lorsque son état change. +- **Mises à Jour d'IU Réactives** : Les vues SwiftUI se mettent à jour automatiquement lorsque des changements sont publiés par la dépendance observée. +- **Thread-Safe** : Comme les autres composants d'AppState, `ObservedDependency` garantit un accès thread-safe à la dépendance observée. + +## Exemple d'Utilisation + +### Définir une Dépendance Observable + +Voici comment définir un service observable en tant que dépendance dans l'extension `Application` : + +```swift +import AppState +import SwiftUI + +@MainActor +class ObservableService: ObservableObject { + @Published var count: Int = 0 +} + +extension Application { + @MainActor + var observableService: Dependency { + dependency(ObservableService()) + } +} +``` + +### Utiliser la Dépendance Observée dans une Vue SwiftUI + +Dans votre vue SwiftUI, vous pouvez accéder à la dépendance observable à l'aide du property wrapper `@ObservedDependency`. L'objet observé met automatiquement à jour la vue chaque fois que son état change. + +```swift +import AppState +import SwiftUI + +struct ObservedDependencyExampleView: View { + @ObservedDependency(\.observableService) var service: ObservableService + + var body: some View { + VStack { + Text("Compte : \(service.count)") + Button("Incrémenter le Compte") { + service.count += 1 + } + } + } +} +``` + +### Cas de Test + +Le cas de test suivant démontre l'interaction avec `ObservedDependency` : + +```swift +import XCTest +@testable import AppState + +@MainActor +fileprivate class ObservableService: ObservableObject { + @Published var count: Int + + init() { + count = 0 + } +} + +fileprivate extension Application { + @MainActor + var observableService: Dependency { + dependency(ObservableService()) + } +} + +@MainActor +fileprivate struct ExampleDependencyWrapper { + @ObservedDependency(\.observableService) var service + + func test() { + service.count += 1 + } +} + +final class ObservedDependencyTests: XCTestCase { + @MainActor + func testDependency() async { + let example = ExampleDependencyWrapper() + + XCTAssertEqual(example.service.count, 0) + + example.test() + + XCTAssertEqual(example.service.count, 1) + } +} +``` + +### Mises à Jour d'IU Réactives + +Étant donné que la dépendance est conforme à `ObservableObject`, toute modification de son état déclenchera une mise à jour de l'IU dans la vue SwiftUI. Vous pouvez lier directement l'état à des éléments d'IU comme un `Picker` : + +```swift +import AppState +import SwiftUI + +struct ReactiveView: View { + @ObservedDependency(\.observableService) var service: ObservableService + + var body: some View { + Picker("Sélectionner le Compte", selection: $service.count) { + ForEach(0..<10) { count in + Text("\(count)").tag(count) + } + } + } +} +``` + +## Meilleures Pratiques + +- **Utiliser pour les Services Observables** : `ObservedDependency` est idéal lorsque votre dépendance doit notifier les vues des changements, en particulier pour les services qui fournissent des mises à jour de données ou d'état. +- **Tirer Parti des Propriétés Publiées** : Assurez-vous que votre dépendance utilise des propriétés `@Published` pour déclencher des mises à jour dans vos vues SwiftUI. +- **Thread-Safe** : Comme les autres composants d'AppState, `ObservedDependency` garantit un accès et des modifications thread-safe au service observable. + +## Conclusion + +`ObservedDependency` est un outil puissant pour gérer les dépendances observables au sein de votre application. En tirant parti du protocole `ObservableObject` de Swift, il garantit que vos vues SwiftUI restent réactives et à jour avec les changements dans le service ou la ressource. + +--- +Cette traduction a été générée automatiquement et peut contenir des erreurs. Si vous êtes un locuteur natif, nous vous serions reconnaissants de contribuer avec des corrections via une Pull Request. diff --git a/documentation/fr/usage-overview.md b/documentation/fr/usage-overview.md new file mode 100644 index 0000000..1a93197 --- /dev/null +++ b/documentation/fr/usage-overview.md @@ -0,0 +1,215 @@ +# Aperçu de l'Utilisation + +Cet aperçu fournit une introduction rapide à l'utilisation des composants clés de la bibliothèque **AppState** dans une `View` SwiftUI. Chaque section comprend des exemples simples qui s'inscrivent dans le cadre d'une structure de vue SwiftUI. + +## Définition des Valeurs dans l'Extension Application + +Pour définir un état ou des dépendances à l'échelle de l'application, vous devez étendre l'objet `Application`. Cela vous permet de centraliser tout l'état de votre application en un seul endroit. Voici un exemple de la manière d'étendre `Application` pour créer divers états et dépendances : + +```swift +import AppState + +extension Application { + var user: State { + state(initial: User(name: "Guest", isLoggedIn: false)) + } + + var userPreferences: StoredState { + storedState(initial: "Default Preferences", id: "userPreferences") + } + + var darkModeEnabled: SyncState { + syncState(initial: false, id: "darkModeEnabled") + } + + var userToken: SecureState { + secureState(id: "userToken") + } + + @MainActor + var largeDataset: FileState<[String]> { + fileState(initial: [], filename: "largeDataset") + } +} +``` + +## State + +`State` vous permet de définir un état à l'échelle de l'application qui peut être accédé et modifié n'importe où dans votre application. + +### Exemple + +```swift +import AppState +import SwiftUI + +struct ContentView: View { + @AppState(\.user) var user: User + + var body: some View { + VStack { + Text("Bonjour, \(user.name)!") + Button("Se connecter") { + user.isLoggedIn.toggle() + } + } + } +} +``` + +## StoredState + +`StoredState` persiste l'état en utilisant `UserDefaults` pour garantir que les valeurs sont sauvegardées entre les lancements de l'application. + +### Exemple + +```swift +import AppState +import SwiftUI + +struct PreferencesView: View { + @StoredState(\.userPreferences) var userPreferences: String + + var body: some View { + VStack { + Text("Préférences : \(userPreferences)") + Button("Mettre à jour les préférences") { + userPreferences = "Updated Preferences" + } + } + } +} +``` + +## SyncState + +`SyncState` synchronise l'état de l'application sur plusieurs appareils à l'aide d'iCloud. + +### Exemple + +```swift +import AppState +import SwiftUI + +struct SyncSettingsView: View { + @SyncState(\.darkModeEnabled) var isDarkModeEnabled: Bool + + var body: some View { + VStack { + Toggle("Mode Sombre", isOn: $isDarkModeEnabled) + } + } +} +``` + +## FileState + +`FileState` est utilisé pour stocker des données plus volumineuses ou plus complexes de manière persistante à l'aide du système de fichiers, ce qui le rend idéal pour la mise en cache ou la sauvegarde de données qui ne rentrent pas dans les limites de `UserDefaults`. + +### Exemple + +```swift +import AppState +import SwiftUI + +struct LargeDataView: View { + @FileState(\.largeDataset) var largeDataset: [String] + + var body: some View { + List(largeDataset, id: \.self) { item in + Text(item) + } + } +} +``` + +## SecureState + +`SecureState` stocke les données sensibles de manière sécurisée dans le Trousseau. + +### Exemple + +```swift +import AppState +import SwiftUI + +struct SecureView: View { + @SecureState(\.userToken) var userToken: String? + + var body: some View { + VStack { + if let token = userToken { + Text("Jeton utilisateur : \(token)") + } else { + Text("Aucun jeton trouvé.") + } + Button("Définir le jeton") { + userToken = "secure_token_value" + } + } + } +} +``` + +## Constant + +`Constant` fournit un accès immuable et en lecture seule aux valeurs de l'état de votre application, garantissant la sécurité lors de l'accès à des valeurs qui ne doivent pas être modifiées. + +### Exemple + +```swift +import AppState +import SwiftUI + +struct ExampleView: View { + @Constant(\.user, \.name) var name: String + + var body: some View { + Text("Nom d'utilisateur : \(name)") + } +} +``` + +## Slicing State + +`Slice` et `OptionalSlice` vous permettent d'accéder à des parties spécifiques de l'état de votre application. + +### Exemple + +```swift +import AppState +import SwiftUI + +struct SlicingView: View { + @Slice(\.user, \.name) var name: String + + var body: some View { + VStack { + Text("Nom d'utilisateur : \(name)") + Button("Mettre à jour le nom d'utilisateur") { + name = "NewUsername" + } + } + } +} +``` + +## Meilleures Pratiques + +- **Utilisez `AppState` dans les Vues SwiftUI** : Les property wrappers comme `@AppState`, `@StoredState`, `@FileState`, `@SecureState`, et d'autres sont conçus pour être utilisés dans le cadre des vues SwiftUI. +- **Définissez l'État dans l'Extension Application** : Centralisez la gestion de l'état en étendant `Application` pour définir l'état et les dépendances de votre application. +- **Mises à Jour Réactives** : SwiftUI met automatiquement à jour les vues lorsque l'état change, vous n'avez donc pas besoin de rafraîchir manuellement l'interface utilisateur. +- **[Guide des Meilleures Pratiques](best-practices.md)** : Pour une description détaillée des meilleures pratiques lors de l'utilisation d'AppState. + +## Prochaines Étapes + +Après vous être familiarisé avec l'utilisation de base, vous pouvez explorer des sujets plus avancés : + +- Explorez l'utilisation de **FileState** pour persister de grandes quantités de données dans des fichiers dans le [Guide d'Utilisation de FileState](usage-filestate.md). +- Apprenez-en davantage sur les **Constantes** et comment les utiliser pour des valeurs immuables dans l'état de votre application dans le [Guide d'Utilisation des Constantes](usage-constant.md). +- Examinez comment **Dependency** est utilisé dans AppState pour gérer les services partagés, et consultez des exemples dans le [Guide d'Utilisation de la Dépendance d'État](usage-state-dependency.md). +- Approfondissez les techniques avancées de **SwiftUI** comme l'utilisation de `ObservedDependency` pour gérer les dépendances observables dans les vues dans le [Guide d'Utilisation de ObservedDependency](usage-observeddependency.md). +- Pour des techniques d'utilisation plus avancées, comme la création Juste-à-Temps et le préchargement des dépendances, consultez le [Guide d'Utilisation Avancée](advanced-usage.md). + +--- +Cette traduction a été générée automatiquement et peut contenir des erreurs. Si vous êtes un locuteur natif, nous vous serions reconnaissants de contribuer avec des corrections via une Pull Request. diff --git a/documentation/fr/usage-securestate.md b/documentation/fr/usage-securestate.md new file mode 100644 index 0000000..15537c9 --- /dev/null +++ b/documentation/fr/usage-securestate.md @@ -0,0 +1,68 @@ +# Utilisation de SecureState + +`SecureState` est un composant de la bibliothèque **AppState** qui vous permet de stocker des données sensibles de manière sécurisée dans le Trousseau. Il est idéal pour stocker de petites quantités de données comme des jetons ou des mots de passe qui doivent être chiffrés de manière sécurisée. + +## Fonctionnalités Clés + +- **Stockage Sécurisé** : Les données stockées à l'aide de `SecureState` sont chiffrées et sauvegardées de manière sécurisée dans le Trousseau. +- **Persistance** : Les données restent persistantes entre les lancements de l'application, ce qui permet de récupérer en toute sécurité des valeurs sensibles. + +## Limitations du Trousseau + +Bien que `SecureState` soit très sécurisé, il présente certaines limitations : + +- **Taille de Stockage Limitée** : Le Trousseau est conçu pour de petites quantités de données. Il n'est pas adapté au stockage de fichiers volumineux ou de grands ensembles de données. +- **Performance** : L'accès au Trousseau est plus lent que l'accès à `UserDefaults`, il ne faut donc l'utiliser que lorsque cela est nécessaire pour stocker des données sensibles en toute sécurité. + +## Exemple d'Utilisation + +### Stocker un Jeton Sécurisé + +```swift +import AppState +import SwiftUI + +extension Application { + var userToken: SecureState { + secureState(id: "userToken") + } +} + +struct SecureView: View { + @SecureState(\.userToken) var userToken: String? + + var body: some View { + VStack { + if let token = userToken { + Text("Jeton utilisateur : \(token)") + } else { + Text("Aucun jeton trouvé.") + } + Button("Définir le jeton") { + userToken = "secure_token_value" + } + } + } +} +``` + +### Gérer l'Absence de Données Sécurisées + +Lors du premier accès au Trousseau, ou s'il n'y a aucune valeur stockée, `SecureState` renverra `nil`. Assurez-vous de gérer correctement ce scénario : + +```swift +if let token = userToken { + print("Jeton : \(token)") +} else { + print("Aucun jeton disponible.") +} +``` + +## Meilleures Pratiques + +- **Utiliser pour de Petites Données** : Le Trousseau doit être utilisé pour stocker de petites informations sensibles comme des jetons, des mots de passe et des clés. +- **Éviter les Grands Ensembles de Données** : Si vous devez stocker de grands ensembles de données de manière sécurisée, envisagez d'utiliser le chiffrement basé sur les fichiers ou d'autres méthodes, car le Trousseau n'est pas conçu pour le stockage de grandes quantités de données. +- **Gérer nil** : Gérez toujours les cas où le Trousseau renvoie `nil` lorsqu'aucune valeur n'est présente. + +--- +Cette traduction a été générée automatiquement et peut contenir des erreurs. Si vous êtes un locuteur natif, nous vous serions reconnaissants de contribuer avec des corrections via une Pull Request. diff --git a/documentation/fr/usage-slice.md b/documentation/fr/usage-slice.md new file mode 100644 index 0000000..f405514 --- /dev/null +++ b/documentation/fr/usage-slice.md @@ -0,0 +1,94 @@ +# Utilisation de Slice et OptionalSlice + +`Slice` et `OptionalSlice` sont des composants de la bibliothèque **AppState** qui vous permettent d'accéder à des parties spécifiques de l'état de votre application. Ils sont utiles lorsque vous devez manipuler ou observer une partie d'une structure d'état plus complexe. + +## Vue d'ensemble + +- **Slice** : Vous permet d'accéder et de modifier une partie spécifique d'un objet `State` existant. +- **OptionalSlice** : Fonctionne de la même manière que `Slice` mais est conçu pour gérer les valeurs optionnelles, par exemple lorsqu'une partie de votre état peut être `nil` ou non. + +### Fonctionnalités Clés + +- **Accès Sélectif à l'État** : N'accédez qu'à la partie de l'état dont vous avez besoin. +- **Sécurité des Threads** : Tout comme les autres types de gestion d'état dans **AppState**, `Slice` et `OptionalSlice` sont thread-safe. +- **Réactivité** : Les vues SwiftUI se mettent à jour lorsque la tranche de l'état change, garantissant que votre interface utilisateur reste réactive. + +## Exemple d'Utilisation + +### Utilisation de Slice + +Dans cet exemple, nous utilisons `Slice` pour accéder et mettre à jour une partie spécifique de l'état — dans ce cas, le `username` d'un objet `User` plus complexe stocké dans l'état de l'application. + +```swift +import AppState +import SwiftUI + +struct User { + var username: String + var email: String +} + +extension Application { + var user: State { + state(initial: User(username: "Guest", email: "guest@example.com")) + } +} + +struct SlicingView: View { + @Slice(\.user, \.username) var username: String + + var body: some View { + VStack { + Text("Nom d'utilisateur : \(username)") + Button("Mettre à jour le nom d'utilisateur") { + username = "NewUsername" + } + } + } +} +``` + +### Utilisation d'OptionalSlice + +`OptionalSlice` est utile lorsqu'une partie de votre état peut être `nil`. Dans cet exemple, l'objet `User` lui-même peut être `nil`, nous utilisons donc `OptionalSlice` pour gérer ce cas en toute sécurité. + +```swift +import AppState +import SwiftUI + +extension Application { + var user: State { + state(initial: nil) + } +} + +struct OptionalSlicingView: View { + @OptionalSlice(\.user, \.username) var username: String? + + var body: some View { + VStack { + if let username = username { + Text("Nom d'utilisateur : \(username)") + } else { + Text("Aucun nom d'utilisateur disponible") + } + Button("Définir le nom d'utilisateur") { + username = "UpdatedUsername" + } + } + } +} +``` + +## Meilleures Pratiques + +- **Utilisez `Slice` pour un état non optionnel** : Si votre état est garanti comme non optionnel, utilisez `Slice` pour y accéder et le mettre à jour. +- **Utilisez `OptionalSlice` pour un état optionnel** : Si votre état ou une partie de l'état est optionnel, utilisez `OptionalSlice` pour gérer les cas où la valeur peut être `nil`. +- **Sécurité des Threads** : Tout comme `State`, `Slice` et `OptionalSlice` sont thread-safe et conçus pour fonctionner avec le modèle de concurrence de Swift. + +## Conclusion + +`Slice` et `OptionalSlice` offrent des moyens puissants d'accéder et de modifier des parties spécifiques de votre état de manière thread-safe. En tirant parti de ces composants, vous pouvez simplifier la gestion de l'état dans des applications plus complexes, en veillant à ce que votre interface utilisateur reste réactive et à jour. + +--- +Cette traduction a été générée automatiquement et peut contenir des erreurs. Si vous êtes un locuteur natif, nous vous serions reconnaissants de contribuer avec des corrections via une Pull Request. diff --git a/documentation/fr/usage-state-dependency.md b/documentation/fr/usage-state-dependency.md new file mode 100644 index 0000000..aec99d3 --- /dev/null +++ b/documentation/fr/usage-state-dependency.md @@ -0,0 +1,136 @@ +# Utilisation de l'État et des Dépendances + +**AppState** fournit des outils puissants pour gérer l'état à l'échelle de l'application et injecter des dépendances dans les vues SwiftUI. En centralisant votre état et vos dépendances, vous pouvez vous assurer que votre application reste cohérente et maintenable. + +## Vue d'ensemble + +- **État** : Représente une valeur qui peut être partagée dans toute l'application. Les valeurs d'état peuvent être modifiées et observées dans vos vues SwiftUI. +- **Dépendance** : Représente une ressource ou un service partagé qui peut être injecté et accédé dans les vues SwiftUI. + +### Fonctionnalités Clés + +- **État Centralisé** : Définissez et gérez l'état à l'échelle de l'application en un seul endroit. +- **Injection de Dépendances** : Injectez et accédez à des services et des ressources partagés dans différents composants de votre application. + +## Exemple d'Utilisation + +### Définir l'État de l'Application + +Pour définir l'état à l'échelle de l'application, étendez l'objet `Application` et déclarez les propriétés d'état. + +```swift +import AppState + +struct User { + var name: String + var isLoggedIn: Bool +} + +extension Application { + var user: State { + state(initial: User(name: "Guest", isLoggedIn: false)) + } +} +``` + +### Accéder et Modifier l'État dans une Vue + +Vous pouvez accéder et modifier les valeurs d'état directement dans une vue SwiftUI à l'aide du property wrapper `@AppState`. + +```swift +import AppState +import SwiftUI + +struct ContentView: View { + @AppState(\.user) var user: User + + var body: some View { + VStack { + Text("Bonjour, \(user.name)!") + Button("Se connecter") { + user.name = "John Doe" + user.isLoggedIn = true + } + } + } +} +``` + +### Définir des Dépendances + +Vous pouvez définir des ressources partagées, comme un service réseau, en tant que dépendances dans l'objet `Application`. Ces dépendances peuvent être injectées dans les vues SwiftUI. + +```swift +import AppState + +protocol NetworkServiceType { + func fetchData() -> String +} + +class NetworkService: NetworkServiceType { + func fetchData() -> String { + return "Data from network" + } +} + +extension Application { + var networkService: Dependency { + dependency(NetworkService()) + } +} +``` + +### Accéder aux Dépendances dans une Vue + +Accédez aux dépendances dans une vue SwiftUI à l'aide du property wrapper `@AppDependency`. Cela vous permet d'injecter des services comme un service réseau dans votre vue. + +```swift +import AppState +import SwiftUI + +struct NetworkView: View { + @AppDependency(\.networkService) var networkService: NetworkServiceType + + var body: some View { + VStack { + Text("Données : \(networkService.fetchData())") + } + } +} +``` + +### Combiner État et Dépendances dans une Vue + +L'état et les dépendances peuvent fonctionner ensemble pour créer une logique d'application plus complexe. Par exemple, vous pouvez récupérer des données d'un service et mettre à jour l'état : + +```swift +import AppState +import SwiftUI + +struct CombinedView: View { + @AppState(\.user) var user: User + @AppDependency(\.networkService) var networkService: NetworkServiceType + + var body: some View { + VStack { + Text("Utilisateur : \(user.name)") + Button("Récupérer les données") { + user.name = networkService.fetchData() + user.isLoggedIn = true + } + } + } +} +``` + +### Meilleures Pratiques + +- **Centraliser l'État** : Gardez l'état de votre application en un seul endroit pour éviter la duplication et garantir la cohérence. +- **Utiliser les Dépendances pour les Services Partagés** : Injectez des dépendances comme des services réseau, des bases de données ou d'autres ressources partagées pour éviter un couplage étroit entre les composants. + +## Conclusion + +Avec **AppState**, vous pouvez gérer l'état à l'échelle de l'application et injecter des dépendances partagées directement dans vos vues SwiftUI. Ce modèle permet de garder votre application modulaire et maintenable. Explorez d'autres fonctionnalités de la bibliothèque **AppState**, telles que [SecureState](usage-securestate.md) et [SyncState](usage-syncstate.md), pour améliorer encore la gestion de l'état de votre application. + +--- +Cette traduction a été générée automatiquement et peut contenir des erreurs. Si vous êtes un locuteur natif, nous vous serions reconnaissants de contribuer avec des corrections via une Pull Request. diff --git a/documentation/fr/usage-storedstate.md b/documentation/fr/usage-storedstate.md new file mode 100644 index 0000000..4c967d0 --- /dev/null +++ b/documentation/fr/usage-storedstate.md @@ -0,0 +1,75 @@ +# Utilisation de StoredState + +`StoredState` est un composant de la bibliothèque **AppState** qui vous permet de stocker et de persister de petites quantités de données à l'aide de `UserDefaults`. Il est idéal pour stocker des données légères et non sensibles qui doivent persister entre les lancements de l'application. + +## Vue d'ensemble + +- **StoredState** est construit sur `UserDefaults`, ce qui signifie qu'il est rapide et efficace pour stocker de petites quantités de données (telles que les préférences de l'utilisateur ou les paramètres de l'application). +- Les données enregistrées dans **StoredState** persistent entre les sessions de l'application, ce qui vous permet de restaurer l'état de l'application au lancement. + +### Fonctionnalités Clés + +- **Stockage Persistant** : Les données enregistrées dans `StoredState` restent disponibles entre les lancements de l'application. +- **Gestion des Petites Données** : Idéal pour les données légères comme les préférences, les bascules ou les petites configurations. +- **Thread-Safe** : `StoredState` garantit que l'accès aux données reste sécurisé dans les environnements concurrents. + +## Exemple d'Utilisation + +### Définir un StoredState + +Vous pouvez définir un **StoredState** en étendant l'objet `Application` et en déclarant la propriété d'état : + +```swift +import AppState + +extension Application { + var userPreferences: StoredState { + storedState(initial: "Default Preferences", id: "userPreferences") + } +} +``` + +### Accéder et Modifier StoredState dans une Vue + +Vous pouvez accéder et modifier les valeurs de **StoredState** dans les vues SwiftUI à l'aide du property wrapper `@StoredState` : + +```swift +import AppState +import SwiftUI + +struct PreferencesView: View { + @StoredState(\.userPreferences) var userPreferences: String + + var body: some View { + VStack { + Text("Préférences : \(userPreferences)") + Button("Mettre à jour les préférences") { + userPreferences = "Updated Preferences" + } + } + } +} +``` + +## Gérer la Migration des Données + +À mesure que votre application évolue, vous pouvez mettre à jour les modèles qui sont persistants via **StoredState**. Lors de la mise à jour de votre modèle de données, assurez-vous de la compatibilité ascendante. Par exemple, vous pouvez ajouter de nouveaux champs ou versionner votre modèle pour gérer la migration. + +Pour plus d'informations, consultez le [Guide des Considérations sur la Migration](migration-considerations.md). + +### Considérations sur la Migration + +- **Ajout de Nouveaux Champs Non Optionnels** : Assurez-vous que les nouveaux champs sont soit optionnels, soit qu'ils ont des valeurs par défaut pour maintenir la compatibilité ascendante. +- **Versionnement des Modèles** : Si votre modèle de données change au fil du temps, incluez un champ `version` pour gérer les différentes versions de vos données persistantes. + +## Meilleures Pratiques + +- **Utiliser pour de Petites Données** : Stockez des données légères et non sensibles qui doivent persister entre les lancements de l'application, comme les préférences de l'utilisateur. +- **Envisager des Alternatives pour les Données plus Volumineuses** : Si vous devez stocker de grandes quantités de données, envisagez d'utiliser **FileState** à la place. + +## Conclusion + +**StoredState** est un moyen simple et efficace de persister de petites quantités de données à l'aide de `UserDefaults`. Il est idéal pour enregistrer les préférences et autres petits paramètres entre les lancements de l'application tout en offrant un accès sécurisé et une intégration facile avec SwiftUI. Pour des besoins de persistance plus complexes, explorez d'autres fonctionnalités de **AppState** comme [FileState](usage-filestate.md) ou [SyncState](usage-syncstate.md). + +--- +Cette traduction a été générée automatiquement et peut contenir des erreurs. Si vous êtes un locuteur natif, nous vous serions reconnaissants de contribuer avec des corrections via une Pull Request. diff --git a/documentation/fr/usage-syncstate.md b/documentation/fr/usage-syncstate.md new file mode 100644 index 0000000..89dc715 --- /dev/null +++ b/documentation/fr/usage-syncstate.md @@ -0,0 +1,159 @@ +# Utilisation de SyncState + +`SyncState` est un composant de la bibliothèque **AppState** qui vous permet de synchroniser l'état de l'application sur plusieurs appareils à l'aide d'iCloud. Ceci est particulièrement utile pour maintenir la cohérence des préférences utilisateur, des paramètres ou d'autres données importantes sur tous les appareils. + +## Vue d'ensemble + +`SyncState` s'appuie sur le `NSUbiquitousKeyValueStore` d'iCloud pour synchroniser de petites quantités de données sur tous les appareils. Cela le rend idéal pour synchroniser un état d'application léger tel que les préférences ou les paramètres utilisateur. + +### Fonctionnalités Clés + +- **Synchronisation iCloud** : Synchronise automatiquement l'état sur tous les appareils connectés au même compte iCloud. +- **Stockage Persistant** : Les données sont stockées de manière persistante dans iCloud, ce qui signifie qu'elles persisteront même si l'application est terminée ou redémarrée. +- **Synchronisation Quasi en Temps Réel** : Les modifications de l'état sont propagées aux autres appareils presque instantanément. + +> **Remarque** : `SyncState` est pris en charge sur watchOS 9.0 et versions ultérieures. + +## Exemple d'Utilisation + +### Modèle de Données + +Supposons que nous ayons une structure nommée `Settings` qui se conforme à `Codable` : + +```swift +struct Settings: Codable { + var text: String + var isShowingSheet: Bool + var isDarkMode: Bool +} +``` + +### Définir un SyncState + +Vous pouvez définir un `SyncState` en étendant l'objet `Application` et en déclarant les propriétés d'état qui doivent être synchronisées : + +```swift +extension Application { + var settings: SyncState { + syncState( + initial: Settings( + text: "Hello, World!", + isShowingSheet: false, + isDarkMode: false + ), + id: "settings" + ) + } +} +``` + +### Gérer les Changements Externes + +Pour s'assurer que l'application répond aux changements externes d'iCloud, surchargez la fonction `didChangeExternally` en créant une sous-classe personnalisée de `Application` : + +```swift +class CustomApplication: Application { + override func didChangeExternally(notification: Notification) { + super.didChangeExternally(notification: notification) + + DispatchQueue.main.async { + self.objectWillChange.send() + } + } +} +``` + +### Créer des Vues pour Modifier et Synchroniser l'État + +Dans l'exemple suivant, nous avons deux vues : `ContentView` et `ContentViewInnerView`. Ces vues partagent et synchronisent l'état `Settings` entre elles. `ContentView` permet à l'utilisateur de modifier le `text` et de basculer `isDarkMode`, tandis que `ContentViewInnerView` affiche le même texte et le met à jour lorsqu'il est touché. + +```swift +struct ContentView: View { + @SyncState(\.settings) private var settings: Settings + + var body: some View { + VStack { + TextField("", text: $settings.text) + + Button(settings.isDarkMode ? "Light" : "Dark") { + settings.isDarkMode.toggle() + } + + Button("Show") { settings.isShowingSheet = true } + } + .preferredColorScheme(settings.isDarkMode ? .dark : .light) + .sheet(isPresented: $settings.isShowingSheet, content: ContentViewInnerView.init) + } +} + +struct ContentViewInnerView: View { + @Slice(\.settings, \.text) private var text: String + + var body: some View { + Text("\(text)") + .onTapGesture { + text = Date().formatted() + } + } +} +``` + +### Configurer l'Application + +Enfin, configurez l'application dans la structure `@main`. Dans l'initialisation, promouvez l'application personnalisée, activez la journalisation et chargez la dépendance du magasin iCloud pour la synchronisation : + +```swift +@main +struct SyncStateExampleApp: App { + init() { + Application + .promote(to: CustomApplication.self) + .logging(isEnabled: true) + .load(dependency: \.icloudStore) + } + + var body: some Scene { + WindowGroup { + ContentView() + } + } +} +``` + +### Activer le Magasin Clé-Valeur iCloud + +Pour activer la synchronisation iCloud, assurez-vous de suivre ce guide pour activer la fonctionnalité de stockage clé-valeur iCloud : [Démarrer avec SyncState](starting-to-use-syncstate.md). + +### SyncState : Notes sur le Stockage iCloud + +Bien que `SyncState` permette une synchronisation facile, il est important de se souvenir des limitations de `NSUbiquitousKeyValueStore` : + +- **Limite de Stockage** : Vous pouvez stocker jusqu'à 1 Mo de données dans iCloud en utilisant `NSUbiquitousKeyValueStore`, avec une limite de taille de valeur par clé de 1 Mo. + +### Considérations sur la Migration + +Lors de la mise à jour de votre modèle de données, il est important de tenir compte des défis potentiels de la migration, en particulier lorsque vous travaillez avec des données persistantes à l'aide de **StoredState**, **FileState** ou **SyncState**. Sans une gestion appropriée de la migration, des changements tels que l'ajout de nouveaux champs ou la modification des formats de données peuvent entraîner des problèmes lors du chargement des anciennes données. + +Voici quelques points clés à garder à l'esprit : +- **Ajout de Nouveaux Champs Non Optionnels** : Assurez-vous que les nouveaux champs sont soit optionnels, soit qu'ils ont des valeurs par défaut pour maintenir la compatibilité ascendante. +- **Gestion des Changements de Format de Données** : Si la structure de votre modèle change, implémentez une logique de décodage personnalisée pour prendre en charge les anciens formats. +- **Versionnement de Vos Modèles** : Utilisez un champ `version` dans vos modèles pour aider aux migrations et appliquer une logique en fonction de la version des données. + +Pour en savoir plus sur la gestion des migrations et éviter les problèmes potentiels, consultez le [Guide des Considérations sur la Migration](migration-considerations.md). + +## Guide d'Implémentation de SyncState + +Pour des instructions détaillées sur la configuration d'iCloud et la configuration de SyncState dans votre projet, consultez le [Guide d'Implémentation de SyncState](syncstate-implementation.md). + +## Meilleures Pratiques + +- **Utiliser pour les Données Petites et Critiques** : `SyncState` est idéal pour synchroniser de petites et importantes pièces d'état telles que les préférences utilisateur, les paramètres ou les indicateurs de fonctionnalités. +- **Surveiller le Stockage iCloud** : Assurez-vous que votre utilisation de `SyncState` reste dans les limites de stockage d'iCloud pour éviter les problèmes de synchronisation des données. +- **Gérer les Mises à Jour Externes** : Si votre application doit répondre aux changements d'état initiés sur un autre appareil, surchargez la fonction `didChangeExternally` pour mettre à jour l'état de l'application en temps réel. + +## Conclusion + +`SyncState` offre un moyen puissant de synchroniser de petites quantités d'état d'application sur tous les appareils via iCloud. Il est idéal pour garantir que les préférences de l'utilisateur et d'autres données clés restent cohérentes sur tous les appareils connectés au même compte iCloud. Pour des cas d'utilisation plus avancés, explorez d'autres fonctionnalités de **AppState**, telles que [SecureState](usage-securestate.md) et [FileState](usage-filestate.md). + +--- +Cette traduction a été générée automatiquement et peut contenir des erreurs. Si vous êtes un locuteur natif, nous vous serions reconnaissants de contribuer avec des corrections via une Pull Request. diff --git a/documentation/hi/advanced-usage.md b/documentation/hi/advanced-usage.md new file mode 100644 index 0000000..30b39b1 --- /dev/null +++ b/documentation/hi/advanced-usage.md @@ -0,0 +1,181 @@ +# AppState का उन्नत उपयोग + +यह गाइड **AppState** का उपयोग करने के लिए उन्नत विषयों को कवर करती है, जिसमें जस्ट-इन-टाइम निर्माण, निर्भरताओं को प्रीलोड करना, स्थिति और निर्भरताओं का प्रभावी ढंग से प्रबंधन करना, और **AppState** की तुलना **SwiftUI के पर्यावरण** से करना शामिल है। + +## 1. जस्ट-इन-टाइम निर्माण + +AppState मान, जैसे `State`, `Dependency`, `StoredState`, और `SyncState`, जस्ट-इन-टाइम बनाए जाते हैं। इसका मतलब है कि वे केवल पहली बार एक्सेस किए जाने पर ही इंस्टैंशिएट होते हैं, जिससे आपके एप्लिकेशन की दक्षता और प्रदर्शन में सुधार होता है। + +### उदाहरण + +```swift +extension Application { + var defaultState: State { + state(initial: 0) // मान तब तक नहीं बनाया जाता जब तक इसे एक्सेस नहीं किया जाता + } +} +``` + +इस उदाहरण में, `defaultState` पहली बार एक्सेस किए जाने तक नहीं बनाया जाता है, जिससे संसाधन उपयोग का अनुकूलन होता है। + +## 2. निर्भरताओं को प्रीलोड करना + +कुछ मामलों में, आप कुछ निर्भरताओं को प्रीलोड करना चाह सकते हैं ताकि यह सुनिश्चित हो सके कि वे आपके एप्लिकेशन के शुरू होने पर उपलब्ध हैं। AppState एक `load` फ़ंक्शन प्रदान करता है जो निर्भरताओं को प्रीलोड करता है। + +### उदाहरण + +```swift +extension Application { + var databaseClient: Dependency { + dependency(DatabaseClient()) + } +} + +// ऐप इनिशियलाइज़ेशन में प्रीलोड करें +Application.load(dependency: \.databaseClient) +``` + +इस उदाहरण में, `databaseClient` ऐप के इनिशियलाइज़ेशन के दौरान प्रीलोड किया जाता है, यह सुनिश्चित करता है कि यह आपके दृश्यों में आवश्यकता होने पर उपलब्ध है। + +## 3. स्थिति और निर्भरता प्रबंधन + +### 3.1 पूरे एप्लिकेशन में साझा स्थिति और निर्भरताएँ + +आप अपने ऐप के एक हिस्से में साझा स्थिति या निर्भरताएँ परिभाषित कर सकते हैं और अद्वितीय आईडी का उपयोग करके दूसरे हिस्से में उन तक पहुँच सकते हैं। + +### उदाहरण + +```swift +private extension Application { + var stateValue: State { + state(initial: 0, id: "stateValue") + } + + var dependencyValue: Dependency { + dependency(SomeType(), id: "dependencyValue") + } +} +``` + +यह आपको उसी `State` या `Dependency` को कहीं और उसी आईडी का उपयोग करके एक्सेस करने की अनुमति देता है। + +```swift +private extension Application { + var theSameStateValue: State { + state(initial: 0, id: "stateValue") + } + + var theSameDependencyValue: Dependency { + dependency(SomeType(), id: "dependencyValue") + } +} +``` + +हालांकि यह दृष्टिकोण एक ही स्ट्रिंग `id` का पुन: उपयोग करके पूरे एप्लिकेशन में स्थिति और निर्भरताओं को साझा करने के लिए मान्य है, इसे आम तौर पर हतोत्साहित किया जाता है। यह इन स्ट्रिंग आईडी के मैन्युअल प्रबंधन पर निर्भर करता है, जिससे हो सकता है: +- आकस्मिक आईडी टकराव यदि एक ही आईडी का उपयोग विभिन्न इच्छित स्थितियों/निर्भरताओं के लिए किया जाता है। +- यह ट्रैक करने में कठिनाई कि स्थिति/निर्भरता कहाँ परिभाषित है बनाम कहाँ एक्सेस की गई है। +- कोड स्पष्टता और रखरखाव में कमी। +एक ही आईडी के साथ बाद की परिभाषाओं में प्रदान किया गया `initial` मान अनदेखा कर दिया जाएगा यदि स्थिति/निर्भरता को उसके पहले एक्सेस द्वारा पहले ही प्रारंभ कर दिया गया है। यह व्यवहार AppState में आईडी-आधारित कैशिंग के काम करने के तरीके का एक साइड इफेक्ट है, बजाय साझा डेटा को परिभाषित करने के लिए एक अनुशंसित प्राथमिक पैटर्न के। `Application` एक्सटेंशन में स्थितियों और निर्भरताओं को अद्वितीय संगणित गुणों के रूप में परिभाषित करना पसंद करें (जो स्वचालित रूप से अद्वितीय आंतरिक आईडी उत्पन्न करते हैं यदि फ़ैक्टरी विधि को कोई स्पष्ट `id` प्रदान नहीं किया जाता है)। + +### 3.2 प्रतिबंधित स्थिति और निर्भरता पहुँच + +पहुँच को प्रतिबंधित करने के लिए, UUID जैसी एक अद्वितीय आईडी का उपयोग करें ताकि यह सुनिश्चित हो सके कि ऐप के केवल सही हिस्से ही विशिष्ट स्थितियों या निर्भरताओं तक पहुँच सकते हैं। + +### उदाहरण + +```swift +private extension Application { + var restrictedState: State { + state(initial: nil, id: UUID().uuidString) + } + + var restrictedDependency: Dependency { + dependency(SomeType(), id: UUID().uuidString) + } +} +``` + +### 3.3 स्थितियों और निर्भरताओं के लिए अद्वितीय आईडी + +जब कोई आईडी प्रदान नहीं की जाती है, तो AppState स्रोत कोड में स्थान के आधार पर एक डिफ़ॉल्ट आईडी उत्पन्न करता है। यह सुनिश्चित करता है कि प्रत्येक `State` या `Dependency` अद्वितीय है और अनपेक्षित पहुँच से सुरक्षित है। + +### उदाहरण + +```swift +extension Application { + var defaultState: State { + state(initial: 0) // AppState एक अद्वितीय आईडी उत्पन्न करता है + } + + var defaultDependency: Dependency { + dependency(SomeType()) // AppState एक अद्वितीय आईडी उत्पन्न करता है + } +} +``` + +### 3.4 फ़ाइल-निजी स्थिति और निर्भरता पहुँच + +एक ही स्विफ्ट फ़ाइल के भीतर और भी अधिक प्रतिबंधित पहुँच के लिए, स्थितियों और निर्भरताओं को बाहरी रूप से एक्सेस किए जाने से बचाने के लिए `fileprivate` एक्सेस स्तर का उपयोग करें। + +### उदाहरण + +```swift +fileprivate extension Application { + var fileprivateState: State { + state(initial: 0) + } + + var fileprivateDependency: Dependency { + dependency(SomeType()) + } +} +``` + +### 3.5 AppState के संग्रहण तंत्र को समझना + +AppState `State`, `Dependency`, `StoredState`, और `SyncState` को संग्रहीत करने के लिए एक एकीकृत कैश का उपयोग करता है। यह सुनिश्चित करता है कि ये डेटा प्रकार आपके पूरे ऐप में कुशलतापूर्वक प्रबंधित किए जाते हैं। + +डिफ़ॉल्ट रूप से, AppState "App" के रूप में एक नाम मान निर्दिष्ट करता है, जो यह सुनिश्चित करता है कि एक मॉड्यूल से जुड़े सभी मान उस नाम से बंधे हैं। यह इन स्थितियों और निर्भरताओं को अन्य मॉड्यूलों से एक्सेस करना कठिन बना देता है। + +## 4. AppState बनाम SwiftUI का पर्यावरण + +AppState और SwiftUI का पर्यावरण दोनों आपके एप्लिकेशन में साझा स्थिति और निर्भरताओं के प्रबंधन के तरीके प्रदान करते हैं, लेकिन वे दायरे, कार्यक्षमता और उपयोग के मामलों में भिन्न होते हैं। + +### 4.1 SwiftUI का पर्यावरण + +SwiftUI का पर्यावरण एक अंतर्निहित तंत्र है जो आपको एक दृश्य पदानुक्रम के माध्यम से साझा डेटा पास करने की अनुमति देता है। यह उन डेटा को पास करने के लिए आदर्श है जिनकी कई दृश्यों को पहुँच की आवश्यकता होती है, लेकिन अधिक जटिल स्थिति प्रबंधन की बात आने पर इसकी सीमाएँ होती हैं। + +**ताकत:** +- उपयोग करने में सरल और SwiftUI के साथ अच्छी तरह से एकीकृत। +- हल्के डेटा के लिए आदर्श जिसे एक पदानुक्रम में कई दृश्यों में साझा करने की आवश्यकता होती है। + +**सीमाएं:** +- डेटा केवल विशिष्ट दृश्य पदानुक्रम के भीतर ही उपलब्ध है। अतिरिक्त काम के बिना विभिन्न दृश्य पदानुक्रमों में समान डेटा तक पहुँचना संभव नहीं है। +- AppState की तुलना में थ्रेड सुरक्षा और दृढ़ता पर कम नियंत्रण। +- अंतर्निहित दृढ़ता या सिंक्रनाइज़ेशन तंत्र की कमी। + +### 4.2 AppState + +AppState पूरे एप्लिकेशन में स्थिति के प्रबंधन के लिए एक अधिक शक्तिशाली और लचीला सिस्टम प्रदान करता है, जिसमें थ्रेड सुरक्षा, दृढ़ता और निर्भरता इंजेक्शन क्षमताएं हैं। + +**ताकत:** +- केंद्रीकृत स्थिति प्रबंधन, पूरे ऐप में सुलभ, न कि केवल विशिष्ट दृश्य पदानुक्रमों में। +- अंतर्निहित दृढ़ता तंत्र (`StoredState`, `FileState`, और `SyncState`)। +- प्रकार सुरक्षा और थ्रेड सुरक्षा गारंटी, यह सुनिश्चित करना कि स्थिति को सही ढंग से एक्सेस और संशोधित किया गया है। +- अधिक जटिल स्थिति और निर्भरता प्रबंधन को संभाल सकता है। + +**सीमाएं:** +- SwiftUI के पर्यावरण की तुलना में अधिक सेटअप और कॉन्फ़िगरेशन की आवश्यकता है। +- पर्यावरण की तुलना में SwiftUI के साथ कुछ हद तक कम एकीकृत, हालांकि अभी भी SwiftUI ऐप्स में अच्छा काम करता है। + +### 4.3 प्रत्येक का उपयोग कब करें + +- **SwiftUI का पर्यावरण** का उपयोग तब करें जब आपके पास सरल डेटा हो जिसे एक दृश्य पदानुक्रम में साझा करने की आवश्यकता हो, जैसे उपयोगकर्ता सेटिंग्स या थीमिंग प्राथमिकताएँ। +- **AppState** का उपयोग तब करें जब आपको केंद्रीकृत स्थिति प्रबंधन, दृढ़ता, या अधिक जटिल स्थिति की आवश्यकता हो जिसे पूरे ऐप में एक्सेस करने की आवश्यकता हो। + +## निष्कर्ष + +इन उन्नत तकनीकों का उपयोग करके, जैसे कि जस्ट-इन-टाइम निर्माण, प्रीलोडिंग, स्थिति और निर्भरता प्रबंधन, और AppState और SwiftUI के पर्यावरण के बीच के अंतर को समझकर, आप **AppState** के साथ कुशल और संसाधन-सचेत एप्लिकेशन बना सकते हैं। + +--- +यह अनुवाद स्वचालित रूप से उत्पन्न किया गया था और इसमें त्रुटियाँ हो सकती हैं। यदि आप एक देशी वक्ता हैं, तो हम एक पुल अनुरोध के माध्यम से सुधारों में आपके योगदान की सराहना करेंगे। diff --git a/documentation/hi/best-practices.md b/documentation/hi/best-practices.md new file mode 100644 index 0000000..c683e8d --- /dev/null +++ b/documentation/hi/best-practices.md @@ -0,0 +1,65 @@ +# AppState का उपयोग करने के लिए सर्वोत्तम प्रथाएँ + +यह मार्गदर्शिका आपको अपने स्विफ्ट अनुप्रयोगों में AppState का कुशलतापूर्वक और प्रभावी ढंग से उपयोग करने में मदद करने के लिए सर्वोत्तम प्रथाएँ प्रदान करती है। + +## 1. AppState का संयम से उपयोग करें + +AppState बहुमुखी है और साझा और स्थानीयकृत स्थिति प्रबंधन दोनों के लिए उपयुक्त है। यह उन डेटा के लिए आदर्श है जिन्हें कई घटकों में साझा करने, दृश्यों या उपयोगकर्ता सत्रों में बनाए रखने, या घटक स्तर पर प्रबंधित करने की आवश्यकता होती है। हालाँकि, अत्यधिक उपयोग से अनावश्यक जटिलता हो सकती है। + +### सिफारिश: +- AppState का उपयोग उन डेटा के लिए करें जिन्हें वास्तव में एप्लिकेशन-व्यापी होने, दूर के घटकों में साझा करने, या AppState की विशिष्ट दृढ़ता/सिंक्रनाइज़ेशन सुविधाओं की आवश्यकता होती है। +- उस स्थिति के लिए जो एकल SwiftUI दृश्य या दृश्यों के एक करीबी पदानुक्रम के लिए स्थानीय है, SwiftUI के अंतर्निहित टूल जैसे `@State`, `@StateObject`, `@ObservedObject`, या `@EnvironmentObject` को प्राथमिकता दें। + +## 2. एक स्वच्छ AppState बनाए रखें + +जैसे-जैसे आपका एप्लिकेशन फैलता है, आपका AppState जटिलता में बढ़ सकता है। अप्रयुक्त स्थितियों और निर्भरताओं को हटाने के लिए नियमित रूप से अपने AppState की समीक्षा और पुनर्रचना करें। अपने AppState को साफ रखने से इसे समझना, बनाए रखना और परीक्षण करना आसान हो जाता है। + +### सिफारिश: +- अप्रयुक्त या निरर्थक स्थितियों और निर्भरताओं के लिए समय-समय पर अपने AppState का ऑडिट करें। +- बड़े AppState संरचनाओं को साफ और प्रबंधनीय बनाए रखने के लिए पुनर्रचना करें। + +## 3. अपने AppState का परीक्षण करें + +अपने एप्लिकेशन के अन्य पहलुओं की तरह, सुनिश्चित करें कि आपका AppState अच्छी तरह से परीक्षण किया गया है। परीक्षण के दौरान अपने AppState को बाहरी निर्भरताओं से अलग करने के लिए मॉक निर्भरताओं का उपयोग करें, और पुष्टि करें कि आपके एप्लिकेशन का प्रत्येक भाग अपेक्षा के अनुरूप व्यवहार करता है। + +### सिफारिश: +- AppState व्यवहार और इंटरैक्शन का परीक्षण करने के लिए XCTest या इसी तरह के फ्रेमवर्क का उपयोग करें। +- यह सुनिश्चित करने के लिए कि AppState परीक्षण अलग और विश्वसनीय हैं, निर्भरताओं को मॉक या स्टब करें। + +## 4. स्लाइस सुविधा का बुद्धिमानी से उपयोग करें + +`Slice` सुविधा आपको AppState की स्थिति के विशिष्ट भागों तक पहुँचने की अनुमति देती है, जो बड़ी और जटिल स्थिति संरचनाओं को संभालने के लिए उपयोगी है। हालाँकि, इस सुविधा का बुद्धिमानी से उपयोग करें ताकि एक स्वच्छ और सुव्यवस्थित AppState बनाए रखा जा सके, अनावश्यक स्लाइस से बचा जा सके जो स्थिति प्रबंधन को खंडित करते हैं। + +### सिफारिश: +- `Slice` का उपयोग केवल बड़ी या नेस्टेड स्थितियों के लिए करें जहाँ व्यक्तिगत घटकों तक पहुँचना आवश्यक हो। +- स्थिति को अधिक-स्लाइस करने से बचें, जिससे भ्रम और खंडित स्थिति प्रबंधन हो सकता है। + +## 5. स्थिर मानों के लिए स्थिरांक का उपयोग करें + +`@Constant` सुविधा आपको केवल-पढ़ने के लिए स्थिरांक परिभाषित करने की अनुमति देती है जिन्हें आपके पूरे एप्लिकेशन में साझा किया जा सकता है। यह उन मानों के लिए उपयोगी है जो आपके ऐप के जीवनचक्र के दौरान अपरिवर्तित रहते हैं, जैसे कॉन्फ़िगरेशन सेटिंग्स या पूर्वनिर्धारित डेटा। स्थिरांक यह सुनिश्चित करते हैं कि ये मान अनजाने में संशोधित न हों। + +### सिफारिश: +- अपरिवर्तित रहने वाले मानों के लिए `@Constant` का उपयोग करें, जैसे ऐप कॉन्फ़िगरेशन, पर्यावरण चर, या स्थिर संदर्भ। + +## 6. अपने AppState को मॉड्यूलर करें + +बड़े अनुप्रयोगों के लिए, अपने AppState को छोटे, अधिक प्रबंधनीय मॉड्यूल में तोड़ने पर विचार करें। प्रत्येक मॉड्यूल की अपनी स्थिति और निर्भरताएँ हो सकती हैं, जिन्हें तब समग्र AppState में संयोजित किया जाता है। यह आपके AppState को समझने, परीक्षण करने और बनाए रखने में आसान बना सकता है। + +### सिफारिश: +- अपनी `Application` एक्सटेंशन को अलग-अलग स्विफ्ट फ़ाइलों या यहाँ तक कि अलग-अलग स्विफ्ट मॉड्यूल में व्यवस्थित करें, जो सुविधा या डोमेन द्वारा समूहीकृत हों। यह स्वाभाविक रूप से परिभाषाओं को मॉड्यूलर बनाता है। +- `state(initial:feature:id:)` जैसी फ़ैक्टरी विधियों का उपयोग करके स्थितियों या निर्भरताओं को परिभाषित करते समय, एक नेमस्पेस प्रदान करने के लिए `feature` पैरामीटर का उपयोग करें, उदाहरण के लिए, `state(initial: 0, feature: "UserProfile", id: "score")`। यह मैन्युअल आईडी का उपयोग किए जाने पर आईडी टकराव को व्यवस्थित करने और रोकने में मदद करता है। +- `Application` के कई उदाहरण बनाने से बचें। साझा सिंगलटन (`Application.shared`) का विस्तार और उपयोग करने से चिपके रहें। + +## 7. जस्ट-इन-टाइम निर्माण का लाभ उठाएं + +AppState मान जस्ट-इन-टाइम बनाए जाते हैं, जिसका अर्थ है कि वे केवल एक्सेस किए जाने पर ही इंस्टैंशिएट होते हैं। यह मेमोरी उपयोग को अनुकूलित करता है और यह सुनिश्चित करता है कि AppState मान केवल तभी बनाए जाएँ जब आवश्यक हो। + +### सिफारिश: +- AppState मानों को जस्ट-इन-टाइम बनाने की अनुमति दें, बजाय इसके कि सभी स्थितियों और निर्भरताओं को अनावश्यक रूप से प्रीलोड किया जाए। + +## निष्कर्ष + +प्रत्येक एप्लिकेशन अद्वितीय है, इसलिए ये सर्वोत्तम प्रथाएँ हर स्थिति में फिट नहीं हो सकती हैं। AppState का उपयोग कैसे करें, यह तय करते समय हमेशा अपने एप्लिकेशन की विशिष्ट आवश्यकताओं पर विचार करें, और अपने स्थिति प्रबंधन को स्वच्छ, कुशल और अच्छी तरह से परीक्षित रखने का प्रयास करें। + +--- +यह अनुवाद स्वचालित रूप से उत्पन्न किया गया था और इसमें त्रुटियाँ हो सकती हैं। यदि आप एक देशी वक्ता हैं, तो हम एक पुल अनुरोध के माध्यम से सुधारों में आपके योगदान की सराहना करेंगे। diff --git a/documentation/hi/contributing.md b/documentation/hi/contributing.md new file mode 100644 index 0000000..25036cf --- /dev/null +++ b/documentation/hi/contributing.md @@ -0,0 +1,63 @@ +# AppState में योगदान + +**AppState** में योगदान देने पर विचार करने के लिए धन्यवाद! आपके योगदान इस परियोजना को सभी के लिए बेहतर बनाने में मदद करते हैं। + +## कैसे योगदान करें + +### 1. बग की रिपोर्ट करना + +यदि आप किसी बग का सामना करते हैं, तो कृपया GitHub पर एक समस्या खोलें। बग की रिपोर्ट करते समय, कृपया शामिल करें: + +- एक स्पष्ट और वर्णनात्मक शीर्षक। +- बग का विस्तृत विवरण, जिसमें इसे पुन: उत्पन्न करने के चरण शामिल हैं। +- अपेक्षित व्यवहार और वास्तव में क्या हुआ। +- आप जिस **AppState** के संस्करण का उपयोग कर रहे हैं। +- कोई भी प्रासंगिक स्क्रीनशॉट या लॉग। + +### 2. सुविधाओं का सुझाव देना + +नए विचारों का स्वागत है! यदि आपके पास कोई ऐसी सुविधा है जिसे आप **AppState** में जोड़ा देखना चाहेंगे, तो कृपया एक समस्या खोलें और वर्णन करें: + +- वह समस्या जिसे सुविधा हल करेगी। +- आपको क्या लगता है कि सुविधा कैसे काम करनी चाहिए। +- कोई भी अतिरिक्त संदर्भ या उदाहरण जो आपके विचार को स्पष्ट करने में मदद करेगा। + +### 3. पुल अनुरोध सबमिट करना + +यदि आप **AppState** में कोड का योगदान करना चाहते हैं, तो इन चरणों का पालन करें: + +1. **रिपोजिटरी को फोर्क करें**: GitHub पर **AppState** रिपोजिटरी का एक व्यक्तिगत फोर्क बनाएं। +2. **अपने फोर्क को क्लोन करें**: अपने फोर्क को अपनी स्थानीय मशीन पर क्लोन करें: + ```bash + git clone https://github.com/your-username/AppState.git + ``` +3. **एक नई शाखा बनाएं**: अपनी सुविधा या बगफिक्स के लिए एक नई शाखा बनाएं: + ```bash + git checkout -b my-feature-branch + ``` +4. **परिवर्तन करें**: नई शाखा में अपने परिवर्तनों को लागू करें। +5. **अपने परिवर्तनों का परीक्षण करें**: सुनिश्चित करें कि आपके परिवर्तन सभी परीक्षण पास करते हैं। यदि आवश्यक हो तो नए परीक्षण जोड़ें। +6. **अपने परिवर्तनों को प्रतिबद्ध करें**: अपने परिवर्तनों को एक वर्णनात्मक प्रतिबद्ध संदेश के साथ प्रतिबद्ध करें: + ```bash + git commit -m "Add my new feature" + ``` +7. **GitHub पर पुश करें**: अपनी शाखा को अपने GitHub फोर्क पर पुश करें: + ```bash + git push origin my-feature-branch + ``` +8. **एक पुल अनुरोध बनाएं**: GitHub पर **AppState** रिपोजिटरी पर जाएं और अपनी शाखा से एक पुल अनुरोध बनाएं। + +### 4. कोड शैली + +कृपया **AppState** परियोजना में उपयोग किए गए कोडिंग शैली दिशानिर्देशों का पालन करें। सुसंगत कोड शैली कोडबेस को अधिक रखरखाव योग्य और समीक्षा में आसान बनाने में मदद करती है। + +### 5. लाइसेंस + +**AppState** में योगदान करके, आप सहमत हैं कि आपके योगदान को परियोजना के समान लाइसेंस के तहत लाइसेंस दिया जाएगा: [लाइसेंस](https://github.com/0xLeif/AppState/blob/main/LICENSE)। + +## धन्यवाद! + +आपके योगदान को बहुत महत्व दिया जाता है और सराहा जाता है। **AppState** को बेहतर बनाने में मदद करने के लिए धन्यवाद! + +--- +यह अनुवाद स्वचालित रूप से उत्पन्न किया गया था और इसमें त्रुटियाँ हो सकती हैं। यदि आप एक देशी वक्ता हैं, तो हम एक पुल अनुरोध के माध्यम से सुधारों में आपके योगदान की सराहना करेंगे। diff --git a/documentation/hi/faq.md b/documentation/hi/faq.md new file mode 100644 index 0000000..31ace64 --- /dev/null +++ b/documentation/hi/faq.md @@ -0,0 +1,43 @@ +# अक्सर पूछे जाने वाले प्रश्न + +यह संक्षिप्त सामान्य प्रश्नोत्तर उन आम सवालों का समाधान करता है जो डेवलपर्स को **AppState** का उपयोग करते समय हो सकते हैं। + +## मैं किसी स्थिति मान को कैसे रीसेट करूं? + +`StoredState`, `FileState`, और `SyncState` जैसे स्थायी स्थितियों के लिए, आप उन्हें `Application` प्रकार पर स्थैतिक `reset` फ़ंक्शंस का उपयोग करके उनके प्रारंभिक मानों पर रीसेट कर सकते हैं। + +उदाहरण के लिए, `StoredState` को रीसेट करने के लिए: +```swift +extension Application { + var hasCompletedOnboarding: StoredState { storedState(initial: false, id: "onboarding_complete") } +} + +// आपके कोड में कहीं +Application.reset(storedState: \.hasCompletedOnboarding) +``` +यह `UserDefaults` में मान को `false` पर रीसेट कर देगा। `FileState`, `SyncState`, और `SecureState` के लिए समान `reset` फ़ंक्शंस मौजूद हैं। + +गैर-स्थायी `State` के लिए, आप इसे स्थायी स्थितियों की तरह ही रीसेट कर सकते हैं: +```swift +extension Application { + var counter: State { state(initial: 0) } +} + +// आपके कोड में कहीं +Application.reset(\.counter) +``` + +## क्या मैं एसिंक्रोनस कार्यों के साथ AppState का उपयोग कर सकता हूं? + +हां। `State` और निर्भरता मान थ्रेड-सुरक्षित हैं और स्विफ्ट कॉन्करेंसी के साथ सहजता से काम करते हैं। आप उन्हें अतिरिक्त लॉकिंग के बिना `async` फ़ंक्शंस के अंदर एक्सेस और संशोधित कर सकते हैं। + +## मुझे स्थितियों और निर्भरताओं को कहां परिभाषित करना चाहिए? + +अपनी सभी स्थितियों और निर्भरताओं को `Application` एक्सटेंशन में रखें। यह सत्य का एक स्रोत सुनिश्चित करता है और सभी उपलब्ध मानों को खोजना आसान बनाता है। + +## क्या AppState कंबाइन के साथ संगत है? + +आप `State` परिवर्तनों को प्रकाशकों से जोड़कर AppState को कंबाइन के साथ उपयोग कर सकते हैं। एक `State` मान का निरीक्षण करें और यदि आवश्यक हो तो `PassthroughSubject` या अन्य कंबाइन प्रकाशक के माध्यम से अपडेट भेजें। + +--- +यह अनुवाद स्वचालित रूप से उत्पन्न किया गया था और इसमें त्रुटियाँ हो सकती हैं। यदि आप एक देशी वक्ता हैं, तो हम एक पुल अनुरोध के माध्यम से सुधारों में आपके योगदान की सराहना करेंगे। diff --git a/documentation/hi/installation.md b/documentation/hi/installation.md new file mode 100644 index 0000000..f20483b --- /dev/null +++ b/documentation/hi/installation.md @@ -0,0 +1,87 @@ +# स्थापना गाइड + +यह गाइड आपको स्विफ्ट पैकेज मैनेजर का उपयोग करके अपने स्विफ्ट प्रोजेक्ट में **AppState** स्थापित करने की प्रक्रिया के माध्यम से मार्गदर्शन करेगी। + +## स्विफ्ट पैकेज मैनेजर + +**AppState** को स्विफ्ट पैकेज मैनेजर का उपयोग करके आपके प्रोजेक्ट में आसानी से एकीकृत किया जा सकता है। **AppState** को एक निर्भरता के रूप में जोड़ने के लिए नीचे दिए गए चरणों का पालन करें। + +### चरण 1: अपनी `Package.swift` फ़ाइल को अपडेट करें + +**AppState** को अपनी `Package.swift` फ़ाइल के `dependencies` अनुभाग में जोड़ें: + +```swift +dependencies: [ + .package(url: "https://github.com/0xLeif/AppState.git", from: "2.2.0") +] +``` + +### चरण 2: अपने लक्ष्य में AppState जोड़ें + +अपने लक्ष्य की निर्भरताओं में AppState शामिल करें: + +```swift +.target( + name: "YourTarget", + dependencies: ["AppState"] +) +``` + +### चरण 3: अपना प्रोजेक्ट बनाएं + +एक बार जब आप AppState को अपनी `Package.swift` फ़ाइल में जोड़ लेते हैं, तो निर्भरता को लाने और इसे अपने कोडबेस में एकीकृत करने के लिए अपना प्रोजेक्ट बनाएं। + +``` +swift build +``` + +### चरण 4: अपने कोड में AppState आयात करें + +अब, आप अपने स्विफ्ट फ़ाइलों के शीर्ष पर इसे आयात करके अपने प्रोजेक्ट में AppState का उपयोग शुरू कर सकते हैं: + +```swift +import AppState +``` + +## Xcode + +यदि आप **AppState** को सीधे Xcode के माध्यम से जोड़ना पसंद करते हैं, तो इन चरणों का पालन करें: + +### चरण 1: अपना Xcode प्रोजेक्ट खोलें + +अपना Xcode प्रोजेक्ट या कार्यक्षेत्र खोलें। + +### चरण 2: एक स्विफ्ट पैकेज निर्भरता जोड़ें + +1. प्रोजेक्ट नेविगेटर पर नेविगेट करें और अपनी प्रोजेक्ट फ़ाइल चुनें। +2. प्रोजेक्ट एडिटर में, अपना लक्ष्य चुनें, और फिर "स्विफ्ट पैकेज" टैब पर जाएं। +3. पैकेज निर्भरता जोड़ने के लिए "+" बटन पर क्लिक करें। + +### चरण 3: रिपोजिटरी URL दर्ज करें + +"पैकेज रिपोजिटरी चुनें" संवाद में, निम्न URL दर्ज करें: `https://github.com/0xLeif/AppState.git` + +फिर "अगला" पर क्लिक करें। + +### चरण 4: संस्करण निर्दिष्ट करें + +वह संस्करण चुनें जिसका आप उपयोग करना चाहते हैं। "अगले प्रमुख संस्करण तक" विकल्प का चयन करने और `2.0.0` को निचली सीमा के रूप में निर्दिष्ट करने की अनुशंसा की जाती है। फिर "अगला" पर क्लिक करें। + +### चरण 5: पैकेज जोड़ें + +Xcode पैकेज लाएगा और आपको अपने लक्ष्य में **AppState** जोड़ने के विकल्प प्रस्तुत करेगा। सुनिश्चित करें कि आप सही लक्ष्य का चयन करते हैं और "समाप्त" पर क्लिक करें। + +### चरण 6: अपने कोड में `AppState` आयात करें + +अब आप अपनी स्विफ्ट फ़ाइलों के शीर्ष पर **AppState** आयात कर सकते हैं: + +```swift +import AppState +``` + +## अगले चरण + +AppState स्थापित होने के साथ, आप अपने प्रोजेक्ट में प्रमुख विशेषताओं को कैसे लागू करें यह देखने के लिए [उपयोग अवलोकन](usage-overview.md) पर जा सकते हैं। + +--- +यह अनुवाद स्वचालित रूप से उत्पन्न किया गया था और इसमें त्रुटियाँ हो सकती हैं। यदि आप एक देशी वक्ता हैं, तो हम एक पुल अनुरोध के माध्यम से सुधारों में आपके योगदान की सराहना करेंगे। diff --git a/documentation/hi/migration-considerations.md b/documentation/hi/migration-considerations.md new file mode 100644 index 0000000..5729b45 --- /dev/null +++ b/documentation/hi/migration-considerations.md @@ -0,0 +1,81 @@ +# प्रवासन संबंधी विचार + +अपने डेटा मॉडल को अपडेट करते समय, विशेष रूप से स्थायी या सिंक्रनाइज़ किए गए डेटा के लिए, आपको पुराने डेटा को लोड करते समय संभावित समस्याओं से बचने के लिए पश्चगामी संगतता को संभालना होगा। यहाँ कुछ महत्वपूर्ण बातें ध्यान में रखनी हैं: + +## 1. गैर-वैकल्पिक फ़ील्ड जोड़ना +यदि आप अपने मॉडल में नए गैर-वैकल्पिक फ़ील्ड जोड़ते हैं, तो पुराने डेटा को डीकोड करना (जिसमें वे फ़ील्ड नहीं होंगे) विफल हो सकता है। इससे बचने के लिए: +- नए फ़ील्ड को डिफ़ॉल्ट मान देने पर विचार करें। +- अपने ऐप के पुराने संस्करणों के साथ संगतता सुनिश्चित करने के लिए नए फ़ील्ड को वैकल्पिक बनाएं। + +### उदाहरण: +```swift +struct Settings: Codable { + var text: String + var isDarkMode: Bool + var newField: String? // नया फ़ील्ड वैकल्पिक है +} +``` + +## 2. डेटा प्रारूप में परिवर्तन +यदि आप किसी मॉडल की संरचना को संशोधित करते हैं (उदाहरण के लिए, प्रकार को `Int` से `String` में बदलना), तो पुराने डेटा को पढ़ते समय डीकोडिंग प्रक्रिया विफल हो सकती है। एक सहज प्रवासन की योजना बनाएं: +- पुराने डेटा प्रारूपों को नई संरचना में बदलने के लिए प्रवासन तर्क बनाना। +- पुराने डेटा को संभालने और इसे अपने नए मॉडल में मैप करने के लिए `Decodable` के कस्टम इनिशियलाइज़र का उपयोग करना। + +### उदाहरण: +```swift +struct Settings: Codable { + var text: String + var isDarkMode: Bool + var version: Int + + // पुराने संस्करणों के लिए कस्टम डीकोडिंग तर्क + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.isDarkMode = try container.decode(Bool.self, forKey: .isDarkMode) + self.text = try container.decode(String.self, forKey: .text) + self.version = (try? container.decode(Int.self, forKey: .version)) ?? 1 // पुराने डेटा के लिए डिफ़ॉल्ट + } +} +``` + +## 3. हटाए गए या पदावनत फ़ील्ड को संभालना +यदि आप मॉडल से कोई फ़ील्ड हटाते हैं, तो सुनिश्चित करें कि ऐप के पुराने संस्करण अभी भी बिना क्रैश हुए नए डेटा को डीकोड कर सकते हैं। आप: +- डीकोड करते समय अतिरिक्त फ़ील्ड को अनदेखा कर सकते हैं। +- पुराने डेटा को संभालने और पदावनत फ़ील्ड को ठीक से प्रबंधित करने के लिए कस्टम डीकोडर का उपयोग कर सकते हैं। + +## 4. अपने मॉडलों का संस्करण बनाना + +अपने मॉडलों का संस्करण बनाने से आप समय के साथ अपने डेटा संरचना में परिवर्तनों को संभाल सकते हैं। अपने मॉडल के हिस्से के रूप में एक संस्करण संख्या रखकर, आप पुराने डेटा प्रारूपों को नए में बदलने के लिए आसानी से प्रवासन तर्क लागू कर सकते हैं। यह दृष्टिकोण सुनिश्चित करता है कि आपका ऐप पुरानी डेटा संरचनाओं को संभाल सकता है, जबकि आसानी से नए संस्करणों में संक्रमण कर सकता है। + +- **संस्करण बनाना क्यों महत्वपूर्ण है**: जब उपयोगकर्ता अपने ऐप को अपडेट करते हैं, तो उनके पास अभी भी उनके उपकरणों पर पुराना डेटा संग्रहीत हो सकता है। संस्करण बनाने से आपके ऐप को डेटा के प्रारूप को पहचानने और सही प्रवासन तर्क लागू करने में मदद मिलती है। +- **कैसे उपयोग करें**: अपने मॉडल में एक `version` फ़ील्ड जोड़ें और डीकोडिंग प्रक्रिया के दौरान इसकी जाँच करें ताकि यह निर्धारित किया जा सके कि प्रवासन की आवश्यकता है या नहीं। + +### उदाहरण: +```swift +struct Settings: Codable { + var version: Int + var text: String + var isDarkMode: Bool + + // संस्करण-विशिष्ट डीकोडिंग तर्क को संभालें + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.version = try container.decode(Int.self, forKey: .version) + self.text = try container.decode(String.self, forKey: .text) + self.isDarkMode = try container.decode(Bool.self, forKey: .isDarkMode) + + // यदि किसी पुराने संस्करण से माइग्रेट कर रहे हैं, तो यहाँ आवश्यक परिवर्तन लागू करें + if version < 2 { + // पुराने डेटा को नए प्रारूप में माइग्रेट करें + } + } +} +``` + +- **सर्वोत्तम अभ्यास**: शुरू से ही `version` फ़ील्ड के साथ शुरू करें। हर बार जब आप अपनी मॉडल संरचना को अपडेट करते हैं, तो संस्करण बढ़ाएँ और आवश्यक प्रवासन तर्क को संभालें। + +## 5. प्रवासन का परीक्षण +हमेशा अपने प्रवासन का अच्छी तरह से परीक्षण करें, अपने मॉडल के नए संस्करणों के साथ पुराने डेटा को लोड करने का अनुकरण करके यह सुनिश्चित करने के लिए कि आपका ऐप अपेक्षा के अनुरूप व्यवहार करता है। + +--- +यह अनुवाद स्वचालित रूप से उत्पन्न किया गया था और इसमें त्रुटियाँ हो सकती हैं। यदि आप एक देशी वक्ता हैं, तो हम एक पुल अनुरोध के माध्यम से सुधारों में आपके योगदान की सराहना करेंगे। diff --git a/documentation/hi/starting-to-use-syncstate.md b/documentation/hi/starting-to-use-syncstate.md new file mode 100644 index 0000000..e0b2382 --- /dev/null +++ b/documentation/hi/starting-to-use-syncstate.md @@ -0,0 +1,25 @@ +SyncState का उपयोग करने के लिए, आपको सबसे पहले अपने Xcode प्रोजेक्ट में iCloud क्षमताओं और अधिकारों को सेट करना होगा। प्रक्रिया में आपका मार्गदर्शन करने के लिए यहाँ एक परिचय दिया गया है: + +### iCloud क्षमताओं को सेट करना: + +1. अपना Xcode प्रोजेक्ट खोलें और macOS और iOS दोनों लक्ष्यों के लिए बंडल पहचानकर्ताओं को अपने से मेल खाने के लिए समायोजित करें। +2. इसके बाद, आपको अपने प्रोजेक्ट में iCloud क्षमता को जोड़ना होगा। ऐसा करने के लिए, प्रोजेक्ट नेविगेटर में अपने प्रोजेक्ट का चयन करें, फिर अपने लक्ष्य का चयन करें। संपादक क्षेत्र के शीर्ष पर टैब बार में, "Signing & Capabilities" पर क्लिक करें। +3. क्षमताएँ फलक में, iCloud पंक्ति में स्विच पर क्लिक करके iCloud चालू करें। आपको स्विच को चालू स्थिति में ले जाते हुए देखना चाहिए। +4. एक बार जब आप iCloud सक्षम कर लेते हैं, तो आपको कुंजी-मूल्य संग्रहण सक्षम करने की आवश्यकता होती है। आप "Key-Value storage" चेकबॉक्स को चेक करके ऐसा कर सकते हैं। + +### अधिकारों को अद्यतन करना: + +1. अब आपको अपनी अधिकार फ़ाइल को अद्यतन करने की आवश्यकता होगी। अपने लक्ष्य के लिए अधिकार फ़ाइल खोलें। +2. सुनिश्चित करें कि iCloud कुंजी-मूल्य स्टोर मान आपकी अद्वितीय कुंजी-मूल्य स्टोर ID से मेल खाता है। आपकी अद्वितीय ID को `$(TeamIdentifierPrefix)` प्रारूप का पालन करना चाहिए। डिफ़ॉल्ट मान कुछ इस तरह होना चाहिए, `$(TeamIdentifierPrefix)$(CFBundleIdentifier)`। यह एकल प्लेटफ़ॉर्म ऐप्स के लिए ठीक है, लेकिन यदि आपका ऐप कई Apple OS पर है, तो यह महत्वपूर्ण है कि कुंजी-मूल्य स्टोर ID के भाग दोनों लक्ष्यों के लिए समान हों। + +### उपकरणों को कॉन्फ़िगर करना: + +प्रोजेक्ट को कॉन्फ़िगर करने के अलावा, आपको उन उपकरणों को भी तैयार करने की आवश्यकता है जो प्रोजेक्ट को चलाएंगे। + +- सुनिश्चित करें कि iCloud ड्राइव iOS और macOS दोनों उपकरणों पर सक्षम है। +- एक ही iCloud खाते का उपयोग करके दोनों उपकरणों में लॉग इन करें। + +यदि आपके कोई प्रश्न हैं या कोई समस्या आती है, तो बेझिझक संपर्क करें या कोई समस्या सबमिट करें। + +--- +यह अनुवाद स्वचालित रूप से उत्पन्न किया गया था और इसमें त्रुटियाँ हो सकती हैं। यदि आप एक देशी वक्ता हैं, तो हम एक पुल अनुरोध के माध्यम से सुधारों में आपके योगदान की सराहना करेंगे। diff --git a/documentation/hi/syncstate-implementation.md b/documentation/hi/syncstate-implementation.md new file mode 100644 index 0000000..9b4b42b --- /dev/null +++ b/documentation/hi/syncstate-implementation.md @@ -0,0 +1,84 @@ +# AppState में SyncState का कार्यान्वयन + +यह मार्गदर्शिका बताती है कि आप अपने एप्लिकेशन में SyncState को कैसे सेट अप और कॉन्फ़िगर करें, जिसमें iCloud क्षमताओं को सेट अप करना और संभावित सीमाओं को समझना शामिल है। + +## 1. iCloud क्षमताओं को सेट अप करना + +अपने एप्लिकेशन में SyncState का उपयोग करने के लिए, आपको पहले अपने प्रोजेक्ट में iCloud को सक्षम करना होगा और की-वैल्यू स्टोरेज को कॉन्फ़िगर करना होगा। + +### iCloud और की-वैल्यू स्टोरेज को सक्षम करने के चरण: + +1. अपना Xcode प्रोजेक्ट खोलें और अपनी प्रोजेक्ट सेटिंग्स पर नेविगेट करें। +2. "Signing & Capabilities" टैब के तहत, अपना लक्ष्य (iOS या macOS) चुनें। +3. "+ Capability" बटन पर क्लिक करें और सूची से "iCloud" चुनें। +4. iCloud सेटिंग्स के तहत "Key-Value storage" विकल्प को सक्षम करें। यह आपके ऐप को iCloud का उपयोग करके थोड़ी मात्रा में डेटा संग्रहीत और सिंक करने की अनुमति देता है। + +### एंटाइटेलमेंट फ़ाइल कॉन्फ़िगरेशन: + +1. अपने Xcode प्रोजेक्ट में, अपने ऐप के लिए **एंटाइटेलमेंट फ़ाइल** ढूंढें या बनाएं। +2. सुनिश्चित करें कि iCloud की-वैल्यू स्टोर एंटाइटेलमेंट फ़ाइल में सही iCloud कंटेनर के साथ सही ढंग से सेट है। + +एंटाइटेलमेंट फ़ाइल में उदाहरण: + +```xml +com.apple.developer.ubiquity-kvstore-identifier +$(TeamIdentifierPrefix)com.yourdomain.app +``` + +सुनिश्चित करें कि स्ट्रिंग मान आपके प्रोजेक्ट से जुड़े iCloud कंटेनर से मेल खाता है। + +## 2. अपने एप्लिकेशन में SyncState का उपयोग करना + +एक बार iCloud सक्षम हो जाने पर, आप उपकरणों के बीच डेटा को सिंक्रनाइज़ करने के लिए अपने एप्लिकेशन में `SyncState` का उपयोग कर सकते हैं। + +### उपयोग में SyncState का उदाहरण: + +```swift +import AppState +import SwiftUI + +extension Application { + var syncValue: SyncState { + syncState(id: "syncValue") + } +} + +struct ContentView: View { + @SyncState(\.syncValue) private var syncValue: Int? + + var body: some View { + VStack { + if let syncValue = syncValue { + Text("SyncValue: \(syncValue)") + } else { + Text("No SyncValue") + } + + Button("Update SyncValue") { + syncValue = Int.random(in: 0..<100) + } + } + } +} +``` + +इस उदाहरण में, सिंक स्थिति iCloud में सहेजी जाएगी और उसी iCloud खाते में लॉग इन किए गए उपकरणों के बीच सिंक्रनाइज़ की जाएगी। + +## 3. सीमाएँ और सर्वोत्तम प्रथाएँ + +SyncState `NSUbiquitousKeyValueStore` का उपयोग करता है, जिसकी कुछ सीमाएँ हैं: + +- **भंडारण सीमा**: SyncState थोड़ी मात्रा में डेटा के लिए डिज़ाइन किया गया है। कुल भंडारण सीमा 1 एमबी है, और प्रत्येक की-वैल्यू जोड़ी लगभग 1 एमबी तक सीमित है। +- **सिंक्रनाइज़ेशन**: SyncState में किए गए परिवर्तन उपकरणों के बीच तुरंत सिंक्रनाइज़ नहीं होते हैं। सिंक्रनाइज़ेशन में थोड़ी देरी हो सकती है, और iCloud सिंकिंग कभी-कभी नेटवर्क स्थितियों से प्रभावित हो सकती है। + +### सर्वोत्तम प्रथाएं: + +- **छोटे डेटा के लिए SyncState का उपयोग करें**: सुनिश्चित करें कि केवल उपयोगकर्ता वरीयताओं या सेटिंग्स जैसे छोटे डेटा को SyncState का उपयोग करके सिंक्रनाइज़ किया जाए। +- **SyncState विफलताओं को शालीनता से संभालें**: संभावित सिंक देरी या विफलताओं के लिए डिफ़ॉल्ट मानों या त्रुटि प्रबंधन तंत्रों का उपयोग करें। + +## 4. निष्कर्ष + +iCloud को ठीक से कॉन्फ़िगर करके और SyncState की सीमाओं को समझकर, आप उपकरणों के बीच डेटा को सिंक करने के लिए इसकी शक्ति का लाभ उठा सकते हैं। सुनिश्चित करें कि आप iCloud भंडारण सीमाओं के साथ संभावित समस्याओं से बचने के लिए केवल छोटे, महत्वपूर्ण डेटा के टुकड़ों के लिए SyncState का उपयोग करते हैं। + +--- +यह अनुवाद स्वचालित रूप से उत्पन्न किया गया था और इसमें त्रुटियाँ हो सकती हैं। यदि आप एक देशी वक्ता हैं, तो हम एक पुल अनुरोध के माध्यम से सुधारों में आपके योगदान की सराहना करेंगे। diff --git a/documentation/hi/usage-constant.md b/documentation/hi/usage-constant.md new file mode 100644 index 0000000..fef0416 --- /dev/null +++ b/documentation/hi/usage-constant.md @@ -0,0 +1,87 @@ +# स्थिरांक का उपयोग + +**AppState** लाइब्रेरी में `Constant` आपके एप्लिकेशन की स्थिति के भीतर मानों तक केवल-पढ़ने के लिए पहुँच प्रदान करता है। यह `Slice` के समान काम करता है, लेकिन यह सुनिश्चित करता है कि एक्सेस किए गए मान अपरिवर्तनीय हैं। यह `Constant` को उन मानों तक पहुँचने के लिए आदर्श बनाता है जो अन्यथा परिवर्तनीय हो सकते हैं लेकिन कुछ संदर्भों में केवल-पढ़ने के लिए बने रहना चाहिए। + +## मुख्य विशेषताएँ + +- **केवल-पढ़ने के लिए पहुँच**: स्थिरांक परिवर्तनीय स्थिति तक पहुँच प्रदान करते हैं, लेकिन मानों को संशोधित नहीं किया जा सकता है। +- **एप्लिकेशन के लिए स्कोप्ड**: `Slice` की तरह, `Constant` को `Application` एक्सटेंशन के भीतर परिभाषित किया गया है और स्थिति के विशिष्ट भागों तक पहुँचने के लिए स्कोप किया गया है। +- **थ्रेड-सेफ**: `Constant` समवर्ती वातावरण में स्थिति तक सुरक्षित पहुँच सुनिश्चित करता है। + +## उपयोग का उदाहरण + +### एप्लिकेशन में एक स्थिरांक को परिभाषित करना + +यहाँ बताया गया है कि केवल-पढ़ने के लिए मान तक पहुँचने के लिए `Application` एक्सटेंशन में `Constant` को कैसे परिभाषित करें: + +```swift +import AppState +import SwiftUI + +struct ExampleValue { + var username: String? + var isLoading: Bool + let value: String + var mutableValue: String +} + +extension Application { + var exampleValue: State { + state( + initial: ExampleValue( + username: "Leif", + isLoading: false, + value: "value", + mutableValue: "" + ) + ) + } +} +``` + +### SwiftUI व्यू में स्थिरांक तक पहुँचना + +SwiftUI व्यू में, आप केवल-पढ़ने के तरीके से स्थिर स्थिति तक पहुँचने के लिए `@Constant` प्रॉपर्टी रैपर का उपयोग कर सकते हैं: + +```swift +import AppState +import SwiftUI + +struct ExampleView: View { + @Constant(\.exampleValue, \.value) var constantValue: String + + var body: some View { + Text("स्थिर मान: \(constantValue)") + } +} +``` + +### परिवर्तनीय स्थिति तक केवल-पढ़ने के लिए पहुँच + +भले ही मान कहीं और परिवर्तनीय हो, जब `@Constant` के माध्यम से पहुँचा जाता है, तो मान अपरिवर्तनीय हो जाता है: + +```swift +import AppState +import SwiftUI + +struct ExampleView: View { + @Constant(\.exampleValue, \.mutableValue) var constantMutableValue: String + + var body: some View { + Text("केवल-पढ़ने के लिए परिवर्तनीय मान: \(constantMutableValue)") + } +} +``` + +## सर्वोत्तम प्रथाएं + +- **केवल-पढ़ने के लिए पहुँच के लिए उपयोग करें**: स्थिति के उन हिस्सों तक पहुँचने के लिए `Constant` का उपयोग करें जिन्हें कुछ संदर्भों में संशोधित नहीं किया जाना चाहिए, भले ही वे कहीं और परिवर्तनीय हों। +- **थ्रेड-सेफ**: अन्य AppState घटकों की तरह, `Constant` स्थिति तक थ्रेड-सुरक्षित पहुँच सुनिश्चित करता है। +- **वैकल्पिक मानों के लिए `OptionalConstant` का उपयोग करें**: यदि आप जिस स्थिति के हिस्से तक पहुँच रहे हैं वह `nil` हो सकता है, तो मान की अनुपस्थिति को सुरक्षित रूप से संभालने के लिए `OptionalConstant` का उपयोग करें। + +## निष्कर्ष + +`Constant` और `OptionalConstant` आपकी ऐप की स्थिति के विशिष्ट भागों तक केवल-पढ़ने के तरीके से पहुँचने का एक कुशल तरीका प्रदान करते हैं। वे यह सुनिश्चित करते हैं कि जो मान अन्यथा परिवर्तनीय हो सकते हैं, उन्हें एक दृश्य के भीतर एक्सेस किए जाने पर अपरिवर्तनीय माना जाता है, जिससे आपके कोड में सुरक्षा और स्पष्टता सुनिश्चित होती है। + +--- +यह अनुवाद स्वचालित रूप से उत्पन्न किया गया था और इसमें त्रुटियाँ हो सकती हैं। यदि आप एक देशी वक्ता हैं, तो हम एक पुल अनुरोध के माध्यम से सुधारों में आपके योगदान की सराहना करेंगे। diff --git a/documentation/hi/usage-filestate.md b/documentation/hi/usage-filestate.md new file mode 100644 index 0000000..2e7c9fe --- /dev/null +++ b/documentation/hi/usage-filestate.md @@ -0,0 +1,96 @@ +# FileState का उपयोग + +`FileState` **AppState** लाइब्रेरी का एक घटक है जो आपको फ़ाइल सिस्टम का उपयोग करके स्थायी डेटा को संग्रहीत और पुनर्प्राप्त करने की अनुमति देता है। यह बड़े डेटा या जटिल ऑब्जेक्ट्स को संग्रहीत करने के लिए उपयोगी है जिन्हें ऐप लॉन्च के बीच सहेजने और आवश्यकता पड़ने पर पुनर्स्थापित करने की आवश्यकता होती है। + +## मुख्य विशेषताएँ + +- **स्थायी भंडारण**: `FileState` का उपयोग करके संग्रहीत डेटा ऐप लॉन्च के बीच बना रहता है। +- **बड़े डेटा का प्रबंधन**: `StoredState` के विपरीत, `FileState` बड़े या अधिक जटिल डेटा को संभालने के लिए आदर्श है। +- **थ्रेड-सेफ**: अन्य AppState घटकों की तरह, `FileState` समवर्ती वातावरण में डेटा तक सुरक्षित पहुँच सुनिश्चित करता है। + +## उपयोग का उदाहरण + +### FileState के साथ डेटा संग्रहीत और पुनर्प्राप्त करना + +यहाँ बताया गया है कि किसी बड़े ऑब्जेक्ट को संग्रहीत और पुनर्प्राप्त करने के लिए `Application` एक्सटेंशन में `FileState` को कैसे परिभाषित करें: + +```swift +import AppState +import SwiftUI + +struct UserProfile: Codable { + var name: String + var age: Int +} + +extension Application { + @MainActor + var userProfile: FileState { + fileState(initial: UserProfile(name: "Guest", age: 25), filename: "userProfile") + } +} + +struct FileStateExampleView: View { + @FileState(\.userProfile) var userProfile: UserProfile + + var body: some View { + VStack { + Text("नाम: \(userProfile.name), आयु: \(userProfile.age)") + Button("प्रोफ़ाइल अपडेट करें") { + userProfile = UserProfile(name: "UpdatedName", age: 30) + } + } + } +} +``` + +### FileState के साथ बड़े डेटा का प्रबंधन + +जब आपको बड़े डेटासेट या ऑब्जेक्ट्स को संभालने की आवश्यकता होती है, तो `FileState` यह सुनिश्चित करता है कि डेटा ऐप के फ़ाइल सिस्टम में कुशलता से संग्रहीत हो। यह कैशिंग या ऑफ़लाइन भंडारण जैसे परिदृश्यों के लिए उपयोगी है। + +```swift +import AppState +import SwiftUI + +extension Application { + @MainActor + var largeDataset: FileState<[String]> { + fileState(initial: [], filename: "largeDataset") + } +} + +struct LargeDataView: View { + @FileState(\.largeDataset) var largeDataset: [String] + + var body: some View { + List(largeDataset, id: \.self) { item in + Text(item) + } + } +} +``` + +### प्रवासन संबंधी विचार + +अपने डेटा मॉडल को अपडेट करते समय, संभावित प्रवासन चुनौतियों का हिसाब रखना महत्वपूर्ण है, खासकर जब **StoredState**, **FileState**, या **SyncState** का उपयोग करके स्थायी डेटा के साथ काम कर रहे हों। उचित प्रवासन प्रबंधन के बिना, नए फ़ील्ड जोड़ने या डेटा प्रारूपों को संशोधित करने जैसे परिवर्तन पुराने डेटा लोड होने पर समस्याएँ पैदा कर सकते हैं। + +यहाँ कुछ मुख्य बातें ध्यान में रखनी हैं: +- **नए गैर-वैकल्पिक फ़ील्ड जोड़ना**: सुनिश्चित करें कि नए फ़ील्ड या तो वैकल्पिक हैं या पश्चगामी संगतता बनाए रखने के लिए डिफ़ॉल्ट मान हैं। +- **डेटा प्रारूप परिवर्तनों को संभालना**: यदि आपके मॉडल की संरचना बदलती है, तो पुराने प्रारूपों का समर्थन करने के लिए कस्टम डीकोडिंग तर्क लागू करें। +- **अपने मॉडलों का संस्करण बनाना**: प्रवासन में मदद करने और डेटा के संस्करण के आधार पर तर्क लागू करने के लिए अपने मॉडलों में `version` फ़ील्ड का उपयोग करें। + +प्रवासन का प्रबंधन करने और संभावित समस्याओं से बचने के तरीके के बारे में अधिक जानने के लिए, [प्रवासन संबंधी विचार मार्गदर्शिका](migration-considerations.md) देखें। + + +## सर्वोत्तम प्रथाएं + +- **बड़े या जटिल डेटा के लिए उपयोग करें**: यदि आप बड़े डेटा या जटिल ऑब्जेक्ट्स संग्रहीत कर रहे हैं, तो `FileState` `StoredState` से बेहतर है। +- **थ्रेड-सेफ एक्सेस**: **AppState** के अन्य घटकों की तरह, `FileState` यह सुनिश्चित करता है कि संग्रहीत डेटा के साथ कई कार्यों के इंटरैक्ट करने पर भी डेटा सुरक्षित रूप से एक्सेस किया जाए। +- **कोडेबल के साथ संयोजन करें**: कस्टम डेटा प्रकारों के साथ काम करते समय, सुनिश्चित करें कि वे `Codable` के अनुरूप हैं ताकि फ़ाइल सिस्टम से और के लिए एन्कोडिंग और डीकोडिंग को सरल बनाया जा सके। + +## निष्कर्ष + +`FileState` आपके ऐप में स्थायी डेटा को संभालने के लिए एक शक्तिशाली उपकरण है, जो आपको बड़े या अधिक जटिल ऑब्जेक्ट्स को थ्रेड-सुरक्षित और स्थायी तरीके से संग्रहीत और पुनर्प्राप्त करने की अनुमति देता है। यह स्विफ्ट के `Codable` प्रोटोकॉल के साथ सहजता से काम करता है, यह सुनिश्चित करता है कि आपका डेटा लंबी अवधि के भंडारण के लिए आसानी से क्रमबद्ध और डी-क्रमबद्ध किया जा सके। + +--- +यह अनुवाद स्वचालित रूप से उत्पन्न किया गया था और इसमें त्रुटियाँ हो सकती हैं। यदि आप एक देशी वक्ता हैं, तो हम एक पुल अनुरोध के माध्यम से सुधारों में आपके योगदान की सराहना करेंगे। diff --git a/documentation/hi/usage-observeddependency.md b/documentation/hi/usage-observeddependency.md new file mode 100644 index 0000000..afa10ac --- /dev/null +++ b/documentation/hi/usage-observeddependency.md @@ -0,0 +1,135 @@ +# ObservedDependency का उपयोग + +`ObservedDependency` **AppState** लाइब्रेरी का एक घटक है जो आपको `ObservableObject` के अनुरूप निर्भरताओं का उपयोग करने की अनुमति देता है। यह तब उपयोगी होता है जब आप चाहते हैं कि निर्भरता आपके SwiftUI दृश्यों को परिवर्तनों के बारे में सूचित करे, जिससे आपके दृश्य प्रतिक्रियाशील और गतिशील हो जाते हैं। + +## मुख्य विशेषताएँ + +- **अवलोकन योग्य निर्भरताएँ**: `ObservableObject` के अनुरूप निर्भरताओं का उपयोग करें, जिससे निर्भरता को अपनी स्थिति बदलने पर स्वचालित रूप से आपके दृश्यों को अपडेट करने की अनुमति मिलती है। +- **प्रतिक्रियाशील यूआई अपडेट**: जब देखे गए निर्भरता द्वारा परिवर्तन प्रकाशित किए जाते हैं तो SwiftUI दृश्य स्वचालित रूप से अपडेट हो जाते हैं। +- **थ्रेड-सेफ**: अन्य AppState घटकों की तरह, `ObservedDependency` देखी गई निर्भरता तक थ्रेड-सुरक्षित पहुँच सुनिश्चित करता है। + +## उपयोग का उदाहरण + +### एक अवलोकन योग्य निर्भरता को परिभाषित करना + +यहाँ बताया गया है कि `Application` एक्सटेंशन में एक अवलोकन योग्य सेवा को निर्भरता के रूप में कैसे परिभाषित करें: + +```swift +import AppState +import SwiftUI + +@MainActor +class ObservableService: ObservableObject { + @Published var count: Int = 0 +} + +extension Application { + @MainActor + var observableService: Dependency { + dependency(ObservableService()) + } +} +``` + +### SwiftUI व्यू में देखी गई निर्भरता का उपयोग करना + +अपने SwiftUI व्यू में, आप `@ObservedDependency` प्रॉपर्टी रैपर का उपयोग करके अवलोकन योग्य निर्भरता तक पहुँच सकते हैं। देखा गया ऑब्जेक्ट अपनी स्थिति बदलने पर स्वचालित रूप से दृश्य को अपडेट करता है। + +```swift +import AppState +import SwiftUI + +struct ObservedDependencyExampleView: View { + @ObservedDependency(\.observableService) var service: ObservableService + + var body: some View { + VStack { + Text("गणना: \(service.count)") + Button("गणना बढ़ाएँ") { + service.count += 1 + } + } + } +} +``` + +### परीक्षण मामला + +निम्नलिखित परीक्षण मामला `ObservedDependency` के साथ सहभागिता को प्रदर्शित करता है: + +```swift +import XCTest +@testable import AppState + +@MainActor +fileprivate class ObservableService: ObservableObject { + @Published var count: Int + + init() { + count = 0 + } +} + +fileprivate extension Application { + @MainActor + var observableService: Dependency { + dependency(ObservableService()) + } +} + +@MainActor +fileprivate struct ExampleDependencyWrapper { + @ObservedDependency(\.observableService) var service + + func test() { + service.count += 1 + } +} + +final class ObservedDependencyTests: XCTestCase { + @MainActor + func testDependency() async { + let example = ExampleDependencyWrapper() + + XCTAssertEqual(example.service.count, 0) + + example.test() + + XCTAssertEqual(example.service.count, 1) + } +} +``` + +### प्रतिक्रियाशील यूआई अपडेट + +चूंकि निर्भरता `ObservableObject` के अनुरूप है, इसलिए इसकी स्थिति में कोई भी परिवर्तन SwiftUI दृश्य में एक यूआई अपडेट को ट्रिगर करेगा। आप स्थिति को सीधे `Picker` जैसे यूआई तत्वों से बाँध सकते हैं: + +```swift +import AppState +import SwiftUI + +struct ReactiveView: View { + @ObservedDependency(\.observableService) var service: ObservableService + + var body: some View { + Picker("गणना चुनें", selection: $service.count) { + ForEach(0..<10) { count in + Text("\(count)").tag(count) + } + } + } +} +``` + +## सर्वोत्तम प्रथाएं + +- **अवलोकन योग्य सेवाओं के लिए उपयोग करें**: `ObservedDependency` तब आदर्श है जब आपकी निर्भरता को दृश्यों को परिवर्तनों के बारे में सूचित करने की आवश्यकता होती है, खासकर उन सेवाओं के लिए जो डेटा या स्थिति अपडेट प्रदान करती हैं। +- **प्रकाशित गुणों का लाभ उठाएं**: सुनिश्चित करें कि आपकी निर्भरता आपके SwiftUI दृश्यों में अपडेट को ट्रिगर करने के लिए `@Published` गुणों का उपयोग करती है। +- **थ्रेड-सेफ**: अन्य AppState घटकों की तरह, `ObservedDependency` अवलोकन योग्य सेवा तक थ्रेड-सुरक्षित पहुँच और संशोधनों को सुनिश्चित करता है। + +## निष्कर्ष + +`ObservedDependency` आपके ऐप के भीतर अवलोकन योग्य निर्भरताओं के प्रबंधन के लिए एक शक्तिशाली उपकरण है। स्विफ्ट के `ObservableObject` प्रोटोकॉल का लाभ उठाकर, यह सुनिश्चित करता है कि आपके SwiftUI दृश्य प्रतिक्रियाशील और सेवा या संसाधन में परिवर्तनों के साथ अद्यतित रहें। + +--- +यह अनुवाद स्वचालित रूप से उत्पन्न किया गया था और इसमें त्रुटियाँ हो सकती हैं। यदि आप एक देशी वक्ता हैं, तो हम एक पुल अनुरोध के माध्यम से सुधारों में आपके योगदान की सराहना करेंगे। diff --git a/documentation/hi/usage-overview.md b/documentation/hi/usage-overview.md new file mode 100644 index 0000000..230bc70 --- /dev/null +++ b/documentation/hi/usage-overview.md @@ -0,0 +1,215 @@ +# उपयोग का अवलोकन + +यह अवलोकन SwiftUI `View` के भीतर **AppState** लाइब्रेरी के प्रमुख घटकों का उपयोग करने का एक त्वरित परिचय प्रदान करता है। प्रत्येक अनुभाग में सरल उदाहरण शामिल हैं जो SwiftUI दृश्य संरचना के दायरे में फिट होते हैं। + +## एप्लिकेशन एक्सटेंशन में मान परिभाषित करना + +एप्लिकेशन-व्यापी स्थिति या निर्भरताओं को परिभाषित करने के लिए, आपको `Application` ऑब्जेक्ट का विस्तार करना चाहिए। यह आपको अपने ऐप की सभी स्थिति को एक ही स्थान पर केंद्रीकृत करने की अनुमति देता है। यहाँ विभिन्न स्थितियों और निर्भरताओं को बनाने के लिए `Application` का विस्तार करने का एक उदाहरण दिया गया है: + +```swift +import AppState + +extension Application { + var user: State { + state(initial: User(name: "Guest", isLoggedIn: false)) + } + + var userPreferences: StoredState { + storedState(initial: "Default Preferences", id: "userPreferences") + } + + var darkModeEnabled: SyncState { + syncState(initial: false, id: "darkModeEnabled") + } + + var userToken: SecureState { + secureState(id: "userToken") + } + + @MainActor + var largeDataset: FileState<[String]> { + fileState(initial: [], filename: "largeDataset") + } +} +``` + +## State + +`State` आपको एप्लिकेशन-व्यापी स्थिति को परिभाषित करने की अनुमति देता है जिसे आपके ऐप में कहीं भी एक्सेस और संशोधित किया जा सकता है। + +### उदाहरण + +```swift +import AppState +import SwiftUI + +struct ContentView: View { + @AppState(\.user) var user: User + + var body: some View { + VStack { + Text("नमस्ते, \(user.name)!") + Button("लॉग इन करें") { + user.isLoggedIn.toggle() + } + } + } +} +``` + +## StoredState + +`StoredState` `UserDefaults` का उपयोग करके स्थिति को बनाए रखता है ताकि यह सुनिश्चित हो सके कि मान ऐप लॉन्च के बीच सहेजे गए हैं। + +### उदाहरण + +```swift +import AppState +import SwiftUI + +struct PreferencesView: View { + @StoredState(\.userPreferences) var userPreferences: String + + var body: some View { + VStack { + Text("वरीयताएँ: \(userPreferences)") + Button("वरीयताएँ अपडेट करें") { + userPreferences = "Updated Preferences" + } + } + } +} +``` + +## SyncState + +`SyncState` iCloud का उपयोग करके कई उपकरणों में ऐप की स्थिति को सिंक्रनाइज़ करता है। + +### उदाहरण + +```swift +import AppState +import SwiftUI + +struct SyncSettingsView: View { + @SyncState(\.darkModeEnabled) var isDarkModeEnabled: Bool + + var body: some View { + VStack { + Toggle("डार्क मोड", isOn: $isDarkModeEnabled) + } + } +} +``` + +## FileState + +`FileState` का उपयोग फ़ाइल सिस्टम का उपयोग करके बड़े या अधिक जटिल डेटा को स्थायी रूप से संग्रहीत करने के लिए किया जाता है, जो इसे कैशिंग या उन डेटा को सहेजने के लिए आदर्श बनाता है जो `UserDefaults` की सीमाओं के भीतर फिट नहीं होते हैं। + +### उदाहरण + +```swift +import AppState +import SwiftUI + +struct LargeDataView: View { + @FileState(\.largeDataset) var largeDataset: [String] + + var body: some View { + List(largeDataset, id: \.self) { item in + Text(item) + } + } +} +``` + +## SecureState + +`SecureState` संवेदनशील डेटा को किचेन में सुरक्षित रूप से संग्रहीत करता है। + +### उदाहरण + +```swift +import AppState +import SwiftUI + +struct SecureView: View { + @SecureState(\.userToken) var userToken: String? + + var body: some View { + VStack { + if let token = userToken { + Text("उपयोगकर्ता टोकन: \(token)") + } else { + Text("कोई टोकन नहीं मिला।") + } + Button("टोकन सेट करें") { + userToken = "secure_token_value" + } + } + } +} +``` + +## Constant + +`Constant` आपके एप्लिकेशन की स्थिति के भीतर मानों तक अपरिवर्तनीय, केवल-पढ़ने के लिए पहुँच प्रदान करता है, उन मानों तक पहुँचते समय सुरक्षा सुनिश्चित करता है जिन्हें संशोधित नहीं किया जाना चाहिए। + +### उदाहरण + +```swift +import AppState +import SwiftUI + +struct ExampleView: View { + @Constant(\.user, \.name) var name: String + + var body: some View { + Text("उपयोगकर्ता नाम: \(name)") + } +} +``` + +## स्लाइसिंग स्टेट + +`Slice` और `OptionalSlice` आपको अपने एप्लिकेशन की स्थिति के विशिष्ट भागों तक पहुँचने की अनुमति देते हैं। + +### उदाहरण + +```swift +import AppState +import SwiftUI + +struct SlicingView: View { + @Slice(\.user, \.name) var name: String + + var body: some View { + VStack { + Text("उपयोगकर्ता नाम: \(name)") + Button("उपयोगकर्ता नाम अपडेट करें") { + name = "NewUsername" + } + } + } +} +``` + +## सर्वोत्तम प्रथाएं + +- **SwiftUI दृश्यों में `AppState` का उपयोग करें**: `@AppState`, `@StoredState`, `@FileState`, `@SecureState`, और अन्य जैसे संपत्ति रैपर SwiftUI दृश्यों के दायरे में उपयोग किए जाने के लिए डिज़ाइन किए गए हैं। +- **एप्लिकेशन एक्सटेंशन में स्थिति को परिभाषित करें**: अपने ऐप की स्थिति और निर्भरताओं को परिभाषित करने के लिए `Application` का विस्तार करके स्थिति प्रबंधन को केंद्रीकृत करें। +- **प्रतिक्रियाशील अपडेट**: जब स्थिति बदलती है तो SwiftUI स्वचालित रूप से दृश्यों को अपडेट करता है, इसलिए आपको UI को मैन्युअल रूप से रीफ्रेश करने की आवश्यकता नहीं है। +- **[सर्वोत्तम प्रथाओं के लिए गाइड](best-practices.md)**: AppState का उपयोग करते समय सर्वोत्तम प्रथाओं के विस्तृत विवरण के लिए। + +## अगले चरण + +बुनियादी उपयोग से परिचित होने के बाद, आप अधिक उन्नत विषयों का पता लगा सकते हैं: + +- [FileState उपयोग गाइड](usage-filestate.md) में फ़ाइलों में बड़ी मात्रा में डेटा को बनाए रखने के लिए **FileState** का उपयोग करने का अन्वेषण करें। +- [स्थिरांक उपयोग गाइड](usage-constant.md) में **स्थिरांक** के बारे में जानें और अपने ऐप की स्थिति में अपरिवर्तनीय मानों के लिए उनका उपयोग कैसे करें। +- [राज्य निर्भरता उपयोग गाइड](usage-state-dependency.md) में साझा सेवाओं को संभालने के लिए AppState में **निर्भरता** का उपयोग कैसे किया जाता है, इसकी जांच करें और उदाहरण देखें। +- [देखे गए निर्भरता उपयोग गाइड](usage-observeddependency.md) में दृश्यों में अवलोकन योग्य निर्भरताओं के प्रबंधन के लिए `ObservedDependency` का उपयोग करने जैसी **उन्नत SwiftUI** तकनीकों में गहराई से उतरें। +- अधिक उन्नत उपयोग तकनीकों के लिए, जैसे जस्ट-इन-टाइम निर्माण और निर्भरताओं को प्रीलोड करना, [उन्नत उपयोग गाइड](advanced-usage.md) देखें। + +--- +यह अनुवाद स्वचालित रूप से उत्पन्न किया गया था और इसमें त्रुटियाँ हो सकती हैं। यदि आप एक देशी वक्ता हैं, तो हम एक पुल अनुरोध के माध्यम से सुधारों में आपके योगदान की सराहना करेंगे। diff --git a/documentation/hi/usage-securestate.md b/documentation/hi/usage-securestate.md new file mode 100644 index 0000000..261b1f0 --- /dev/null +++ b/documentation/hi/usage-securestate.md @@ -0,0 +1,68 @@ +# SecureState का उपयोग + +`SecureState` **AppState** लाइब्रेरी का एक घटक है जो आपको संवेदनशील डेटा को कीचेन में सुरक्षित रूप से संग्रहीत करने की अनुमति देता है। यह टोकन या पासवर्ड जैसे छोटे डेटा के टुकड़ों को संग्रहीत करने के लिए सबसे उपयुक्त है जिन्हें सुरक्षित रूप से एन्क्रिप्ट करने की आवश्यकता होती है। + +## मुख्य विशेषताएँ + +- **सुरक्षित भंडारण**: `SecureState` का उपयोग करके संग्रहीत डेटा को एन्क्रिप्ट किया जाता है और कीचेन में सुरक्षित रूप से सहेजा जाता है। +- **स्थायित्व**: डेटा ऐप लॉन्च के बीच स्थायी रहता है, जिससे संवेदनशील मानों की सुरक्षित पुनर्प्राप्ति की अनुमति मिलती है। + +## कीचेन की सीमाएँ + +हालांकि `SecureState` बहुत सुरक्षित है, इसकी कुछ सीमाएँ हैं: + +- **सीमित भंडारण आकार**: कीचेन को छोटे डेटा के टुकड़ों के लिए डिज़ाइन किया गया है। यह बड़ी फ़ाइलों या डेटासेट को संग्रहीत करने के लिए उपयुक्त नहीं है। +- **प्रदर्शन**: कीचेन तक पहुँचना `UserDefaults` तक पहुँचने की तुलना में धीमा है, इसलिए इसका उपयोग केवल तभी करें जब संवेदनशील डेटा को सुरक्षित रूप से संग्रहीत करना आवश्यक हो। + +## उपयोग का उदाहरण + +### एक सुरक्षित टोकन संग्रहीत करना + +```swift +import AppState +import SwiftUI + +extension Application { + var userToken: SecureState { + secureState(id: "userToken") + } +} + +struct SecureView: View { + @SecureState(\.userToken) var userToken: String? + + var body: some View { + VStack { + if let token = userToken { + Text("उपयोगकर्ता टोकन: \(token)") + } else { + Text("कोई टोकन नहीं मिला।") + } + Button("टोकन सेट करें") { + userToken = "secure_token_value" + } + } + } +} +``` + +### सुरक्षित डेटा की अनुपस्थिति को संभालना + +पहली बार कीचेन तक पहुँचते समय, या यदि कोई मान संग्रहीत नहीं है, तो `SecureState` `nil` लौटाएगा। सुनिश्चित करें कि आप इस परिदृश्य को ठीक से संभालते हैं: + +```swift +if let token = userToken { + print("टोकन: \(token)") +} else { + print("कोई टोकन उपलब्ध नहीं है।") +} +``` + +## सर्वोत्तम प्रथाएं + +- **छोटे डेटा के लिए उपयोग करें**: कीचेन का उपयोग टोकन, पासवर्ड और कुंजी जैसी छोटी संवेदनशील जानकारी संग्रहीत करने के लिए किया जाना चाहिए। +- **बड़े डेटासेट से बचें**: यदि आपको बड़े डेटासेट को सुरक्षित रूप से संग्रहीत करने की आवश्यकता है, तो फ़ाइल-आधारित एन्क्रिप्शन या अन्य तरीकों का उपयोग करने पर विचार करें, क्योंकि कीचेन बड़े डेटा भंडारण के लिए डिज़ाइन नहीं किया गया है। +- **शून्य को संभालें**: हमेशा उन मामलों को संभालें जहां कोई मान मौजूद न होने पर कीचेन `nil` लौटाता है। + +--- +यह अनुवाद स्वचालित रूप से उत्पन्न किया गया था और इसमें त्रुटियाँ हो सकती हैं। यदि आप एक देशी वक्ता हैं, तो हम एक पुल अनुरोध के माध्यम से सुधारों में आपके योगदान की सराहना करेंगे। diff --git a/documentation/hi/usage-slice.md b/documentation/hi/usage-slice.md new file mode 100644 index 0000000..7434b21 --- /dev/null +++ b/documentation/hi/usage-slice.md @@ -0,0 +1,94 @@ +# स्लाइस और ऑप्शनलस्लाइस का उपयोग + +`स्लाइस` और `ऑप्शनलस्लाइस` **ऐपस्टेट** लाइब्रेरी के घटक हैं जो आपको अपने एप्लिकेशन की स्थिति के विशिष्ट भागों तक पहुंचने की अनुमति देते हैं। जब आपको अधिक जटिल स्थिति संरचना के किसी हिस्से में हेरफेर या निरीक्षण करने की आवश्यकता होती है तो वे उपयोगी होते हैं। + +## अवलोकन + +- **स्लाइस**: आपको किसी मौजूदा `स्टेट` ऑब्जेक्ट के किसी विशिष्ट हिस्से तक पहुंचने और उसे संशोधित करने की अनुमति देता है। +- **ऑप्शनलस्लाइस**: `स्लाइस` के समान ही काम करता है लेकिन इसे वैकल्पिक मानों को संभालने के लिए डिज़ाइन किया गया है, जैसे कि जब आपकी स्थिति का हिस्सा `nil` हो सकता है या नहीं। + +### मुख्य विशेषताएँ + +- **चयनात्मक स्थिति पहुंच**: केवल उस स्थिति के हिस्से तक पहुंचें जिसकी आपको आवश्यकता है। +- **थ्रेड सुरक्षा**: **ऐपस्टेट** में अन्य स्थिति प्रबंधन प्रकारों की तरह, `स्लाइस` और `ऑप्शनलस्लाइस` थ्रेड-सुरक्षित हैं। +- **प्रतिक्रियाशीलता**: जब स्थिति का टुकड़ा बदलता है तो SwiftUI विचार अपडेट होते हैं, यह सुनिश्चित करते हुए कि आपका UI प्रतिक्रियाशील बना रहता है। + +## उपयोग का उदाहरण + +### स्लाइस का उपयोग करना + +इस उदाहरण में, हम स्थिति के एक विशिष्ट हिस्से तक पहुंचने और उसे अपडेट करने के लिए `स्लाइस` का उपयोग करते हैं - इस मामले में, ऐप स्थिति में संग्रहीत अधिक जटिल `उपयोगकर्ता` ऑब्जेक्ट से `उपयोगकर्ता नाम`। + +```swift +import AppState +import SwiftUI + +struct User { + var username: String + var email: String +} + +extension Application { + var user: State { + state(initial: User(username: "Guest", email: "guest@example.com")) + } +} + +struct SlicingView: View { + @Slice(\.user, \.username) var username: String + + var body: some View { + VStack { + Text("उपयोगकर्ता नाम: \(username)") + Button("उपयोगकर्ता नाम अपडेट करें") { + username = "NewUsername" + } + } + } +} +``` + +### ऑप्शनलस्लाइस का उपयोग करना + +जब आपकी स्थिति का हिस्सा `nil` हो सकता है तो `ऑप्शनलस्लाइस` उपयोगी होता है। इस उदाहरण में, `उपयोगकर्ता` ऑब्जेक्ट स्वयं `nil` हो सकता है, इसलिए हम इस मामले को सुरक्षित रूप से संभालने के लिए `ऑप्शनलस्लाइस` का उपयोग करते हैं। + +```swift +import AppState +import SwiftUI + +extension Application { + var user: State { + state(initial: nil) + } +} + +struct OptionalSlicingView: View { + @OptionalSlice(\.user, \.username) var username: String? + + var body: some View { + VStack { + if let username = username { + Text("उपयोगकर्ता नाम: \(username)") + } else { + Text("कोई उपयोगकर्ता नाम उपलब्ध नहीं है") + } + Button("उपयोगकर्ता नाम सेट करें") { + username = "UpdatedUsername" + } + } + } +} +``` + +## सर्वोत्तम प्रथाएं + +- **गैर-वैकल्पिक स्थिति के लिए `स्लाइस` का उपयोग करें**: यदि आपकी स्थिति गैर-वैकल्पिक होने की गारंटी है, तो इसे एक्सेस करने और अपडेट करने के लिए `स्लाइस` का उपयोग करें। +- **वैकल्पिक स्थिति के लिए `ऑप्शनलस्लाइस` का उपयोग करें**: यदि आपकी स्थिति या स्थिति का हिस्सा वैकल्पिक है, तो उन मामलों को संभालने के लिए `ऑप्शनलस्लाइस` का उपयोग करें जहां मान `nil` हो सकता है। +- **थ्रेड सुरक्षा**: `स्टेट` की तरह, `स्लाइस` और `ऑप्शनलस्लाइस` थ्रेड-सुरक्षित हैं और स्विफ्ट के संगामिति मॉडल के साथ काम करने के लिए डिज़ाइन किए गए हैं। + +## निष्कर्ष + +`स्लाइस` और `ऑप्शनलस्लाइस` आपकी स्थिति के विशिष्ट भागों तक पहुंचने और उन्हें थ्रेड-सुरक्षित तरीके से संशोधित करने के शक्तिशाली तरीके प्रदान करते हैं। इन घटकों का लाभ उठाकर, आप अधिक जटिल अनुप्रयोगों में स्थिति प्रबंधन को सरल बना सकते हैं, यह सुनिश्चित करते हुए कि आपका UI प्रतिक्रियाशील और अद्यतित बना रहता है। + +--- +यह अनुवाद स्वचालित रूप से उत्पन्न किया गया था और इसमें त्रुटियाँ हो सकती हैं। यदि आप एक देशी वक्ता हैं, तो हम एक पुल अनुरोध के माध्यम से सुधारों में आपके योगदान की सराहना करेंगे। diff --git a/documentation/hi/usage-state-dependency.md b/documentation/hi/usage-state-dependency.md new file mode 100644 index 0000000..969068d --- /dev/null +++ b/documentation/hi/usage-state-dependency.md @@ -0,0 +1,136 @@ +# स्थिति और निर्भरता का उपयोग + +**AppState** एप्लिकेशन-व्यापी स्थिति के प्रबंधन और SwiftUI दृश्यों में निर्भरता को इंजेक्ट करने के लिए शक्तिशाली उपकरण प्रदान करता है। अपनी स्थिति और निर्भरताओं को केंद्रीकृत करके, आप यह सुनिश्चित कर सकते हैं कि आपका एप्लिकेशन सुसंगत और बनाए रखने योग्य बना रहे। + +## अवलोकन + +- **स्थिति**: एक मान का प्रतिनिधित्व करता है जिसे पूरे ऐप में साझा किया जा सकता है। स्थिति मानों को आपके SwiftUI दृश्यों के भीतर संशोधित और देखा जा सकता है। +- **निर्भरता**: एक साझा संसाधन या सेवा का प्रतिनिधित्व करता है जिसे SwiftUI दृश्यों के भीतर इंजेक्ट और एक्सेस किया जा सकता है। + +### मुख्य विशेषताएँ + +- **केंद्रीकृत स्थिति**: एप्लिकेशन-व्यापी स्थिति को एक ही स्थान पर परिभाषित और प्रबंधित करें। +- **निर्भरता इंजेक्शन**: अपने एप्लिकेशन के विभिन्न घटकों में साझा सेवाओं और संसाधनों को इंजेक्ट और एक्सेस करें। + +## उपयोग का उदाहरण + +### एप्लिकेशन स्थिति को परिभाषित करना + +एप्लिकेशन-व्यापी स्थिति को परिभाषित करने के लिए, `Application` ऑब्जेक्ट का विस्तार करें और स्थिति गुणों की घोषणा करें। + +```swift +import AppState + +struct User { + var name: String + var isLoggedIn: Bool +} + +extension Application { + var user: State { + state(initial: User(name: "Guest", isLoggedIn: false)) + } +} +``` + +### एक दृश्य में स्थिति तक पहुँचना और उसे संशोधित करना + +आप `@AppState` प्रॉपर्टी रैपर का उपयोग करके सीधे SwiftUI दृश्य के भीतर स्थिति मानों तक पहुँच और उन्हें संशोधित कर सकते हैं। + +```swift +import AppState +import SwiftUI + +struct ContentView: View { + @AppState(\.user) var user: User + + var body: some View { + VStack { + Text("नमस्ते, \(user.name)!") + Button("लॉग इन करें") { + user.name = "John Doe" + user.isLoggedIn = true + } + } + } +} +``` + +### निर्भरताओं को परिभाषित करना + +आप साझा संसाधनों, जैसे कि नेटवर्क सेवा, को `Application` ऑब्जेक्ट में निर्भरता के रूप में परिभाषित कर सकते हैं। इन निर्भरताओं को SwiftUI दृश्यों में इंजेक्ट किया जा सकता है। + +```swift +import AppState + +protocol NetworkServiceType { + func fetchData() -> String +} + +class NetworkService: NetworkServiceType { + func fetchData() -> String { + return "Data from network" + } +} + +extension Application { + var networkService: Dependency { + dependency(NetworkService()) + } +} +``` + +### एक दृश्य में निर्भरताओं तक पहुँचना + +`@AppDependency` प्रॉपर्टी रैपर का उपयोग करके SwiftUI दृश्य के भीतर निर्भरताओं तक पहुँचें। यह आपको अपनी दृश्य में नेटवर्क सेवा जैसी सेवाओं को इंजेक्ट करने की अनुमति देता है। + +```swift +import AppState +import SwiftUI + +struct NetworkView: View { + @AppDependency(\.networkService) var networkService: NetworkServiceType + + var body: some View { + VStack { + Text("डेटा: \(networkService.fetchData())") + } + } +} +``` + +### एक दृश्य में स्थिति और निर्भरताओं का संयोजन + +स्थिति और निर्भरताएँ अधिक जटिल एप्लिकेशन तर्क बनाने के लिए एक साथ काम कर सकती हैं। उदाहरण के लिए, आप किसी सेवा से डेटा प्राप्त कर सकते हैं और स्थिति को अपडेट कर सकते हैं: + +```swift +import AppState +import SwiftUI + +struct CombinedView: View { + @AppState(\.user) var user: User + @AppDependency(\.networkService) var networkService: NetworkServiceType + + var body: some View { + VStack { + Text("उपयोगकर्ता: \(user.name)") + Button("डेटा प्राप्त करें") { + user.name = networkService.fetchData() + user.isLoggedIn = true + } + } + } +} +``` + +### सर्वोत्तम प्रथाएं + +- **स्थिति को केंद्रीकृत करें**: दोहराव से बचने और स्थिरता सुनिश्चित करने के लिए अपनी एप्लिकेशन-व्यापी स्थिति को एक ही स्थान पर रखें। +- **साझा सेवाओं के लिए निर्भरताओं का उपयोग करें**: घटकों के बीच तंग युग्मन से बचने के लिए नेटवर्क सेवाओं, डेटाबेस या अन्य साझा संसाधनों जैसी निर्भरताओं को इंजेक्ट करें। + +## निष्कर्ष + +**AppState** के साथ, आप एप्लिकेशन-व्यापी स्थिति का प्रबंधन कर सकते हैं और साझा निर्भरताओं को सीधे अपने SwiftUI दृश्यों में इंजेक्ट कर सकते हैं। यह पैटर्न आपके ऐप को मॉड्यूलर और बनाए रखने योग्य रखने में मदद करता है। अपने ऐप की स्थिति प्रबंधन को और बढ़ाने के लिए **AppState** लाइब्रेरी की अन्य विशेषताओं, जैसे [SecureState](usage-securestate.md) और [SyncState](usage-syncstate.md) का अन्वेषण करें। + +--- +यह अनुवाद स्वचालित रूप से उत्पन्न किया गया था और इसमें त्रुटियाँ हो सकती हैं। यदि आप एक देशी वक्ता हैं, तो हम एक पुल अनुरोध के माध्यम से सुधारों में आपके योगदान की सराहना करेंगे। diff --git a/documentation/hi/usage-storedstate.md b/documentation/hi/usage-storedstate.md new file mode 100644 index 0000000..16d7224 --- /dev/null +++ b/documentation/hi/usage-storedstate.md @@ -0,0 +1,75 @@ +# StoredState का उपयोग + +`StoredState` **AppState** लाइब्रेरी का एक घटक है जो आपको `UserDefaults` का उपयोग करके थोड़ी मात्रा में डेटा संग्रहीत और बनाए रखने की अनुमति देता है। यह हल्के, गैर-संवेदनशील डेटा को संग्रहीत करने के लिए आदर्श है जिसे ऐप लॉन्च के बीच बनाए रखा जाना चाहिए। + +## अवलोकन + +- **StoredState** `UserDefaults` के शीर्ष पर बनाया गया है, जिसका अर्थ है कि यह थोड़ी मात्रा में डेटा (जैसे उपयोगकर्ता वरीयताएँ या ऐप सेटिंग्स) संग्रहीत करने के लिए तेज़ और कुशल है। +- **StoredState** में सहेजा गया डेटा ऐप सत्रों के बीच बना रहता है, जिससे आप लॉन्च पर एप्लिकेशन स्थिति को पुनर्स्थापित कर सकते हैं। + +### मुख्य विशेषताएँ + +- **स्थायी भंडारण**: `StoredState` में सहेजा गया डेटा ऐप लॉन्च के बीच उपलब्ध रहता है। +- **छोटे डेटा का प्रबंधन**: वरीयताओं, टॉगल या छोटी कॉन्फ़िगरेशन जैसे हल्के डेटा के लिए सबसे अच्छा उपयोग किया जाता है। +- **थ्रेड-सेफ**: `StoredState` यह सुनिश्चित करता है कि समवर्ती वातावरण में डेटा एक्सेस सुरक्षित रहे। + +## उपयोग का उदाहरण + +### एक StoredState को परिभाषित करना + +आप `Application` ऑब्जेक्ट का विस्तार करके और स्थिति संपत्ति की घोषणा करके एक **StoredState** को परिभाषित कर सकते हैं: + +```swift +import AppState + +extension Application { + var userPreferences: StoredState { + storedState(initial: "Default Preferences", id: "userPreferences") + } +} +``` + +### एक दृश्य में StoredState तक पहुँचना और उसे संशोधित करना + +आप `@StoredState` प्रॉपर्टी रैपर का उपयोग करके SwiftUI दृश्यों के भीतर **StoredState** मानों तक पहुँच और उन्हें संशोधित कर सकते हैं: + +```swift +import AppState +import SwiftUI + +struct PreferencesView: View { + @StoredState(\.userPreferences) var userPreferences: String + + var body: some View { + VStack { + Text("वरीयताएँ: \(userPreferences)") + Button("वरीयताएँ अपडेट करें") { + userPreferences = "Updated Preferences" + } + } + } +} +``` + +## डेटा माइग्रेशन को संभालना + +जैसे-जैसे आपका ऐप विकसित होता है, आप **StoredState** के माध्यम से बनाए गए मॉडल को अपडेट कर सकते हैं। अपने डेटा मॉडल को अपडेट करते समय, पश्चगामी संगतता सुनिश्चित करें। उदाहरण के लिए, आप नए फ़ील्ड जोड़ सकते हैं या माइग्रेशन को संभालने के लिए अपने मॉडल का संस्करण बना सकते हैं। + +अधिक जानकारी के लिए, [माइग्रेशन संबंधी विचार मार्गदर्शिका](migration-considerations.md) देखें। + +### माइग्रेशन संबंधी विचार + +- **नए गैर-वैकल्पिक फ़ील्ड जोड़ना**: सुनिश्चित करें कि नए फ़ील्ड या तो वैकल्पिक हैं या पश्चगामी संगतता बनाए रखने के लिए डिफ़ॉल्ट मान हैं। +- **मॉडल का संस्करण बनाना**: यदि आपका डेटा मॉडल समय के साथ बदलता है, तो अपने बनाए गए डेटा के विभिन्न संस्करणों को प्रबंधित करने के लिए एक `version` फ़ील्ड शामिल करें। + +## सर्वोत्तम प्रथाएं + +- **छोटे डेटा के लिए उपयोग करें**: हल्के, गैर-संवेदनशील डेटा को संग्रहीत करें जिसे उपयोगकर्ता वरीयताओं की तरह ऐप लॉन्च के बीच बनाए रखने की आवश्यकता है। +- **बड़े डेटा के लिए विकल्पों पर विचार करें**: यदि आपको बड़ी मात्रा में डेटा संग्रहीत करने की आवश्यकता है, तो इसके बजाय **FileState** का उपयोग करने पर विचार करें। + +## निष्कर्ष + +**StoredState** `UserDefaults` का उपयोग करके डेटा के छोटे टुकड़ों को बनाए रखने का एक सरल और कुशल तरीका है। यह वरीयताओं और अन्य छोटी सेटिंग्स को ऐप लॉन्च के बीच सहेजने के लिए आदर्श है, जबकि सुरक्षित पहुँच और SwiftUI के साथ आसान एकीकरण प्रदान करता है। अधिक जटिल दृढ़ता आवश्यकताओं के लिए, **AppState** की अन्य विशेषताओं जैसे [FileState](usage-filestate.md) या [SyncState](usage-syncstate.md) का अन्वेषण करें। + +--- +यह अनुवाद स्वचालित रूप से उत्पन्न किया गया था और इसमें त्रुटियाँ हो सकती हैं। यदि आप एक देशी वक्ता हैं, तो हम एक पुल अनुरोध के माध्यम से सुधारों में आपके योगदान की सराहना करेंगे। diff --git a/documentation/hi/usage-syncstate.md b/documentation/hi/usage-syncstate.md new file mode 100644 index 0000000..4904b72 --- /dev/null +++ b/documentation/hi/usage-syncstate.md @@ -0,0 +1,159 @@ +# SyncState का उपयोग + +`SyncState` **AppState** लाइब्रेरी का एक घटक है जो आपको iCloud का उपयोग करके कई उपकरणों में ऐप की स्थिति को सिंक्रनाइज़ करने की अनुमति देता है। यह उपयोगकर्ता की वरीयताओं, सेटिंग्स, या अन्य महत्वपूर्ण डेटा को उपकरणों में सुसंगत रखने के लिए विशेष रूप से उपयोगी है। + +## अवलोकन + +`SyncState` iCloud के `NSUbiquitousKeyValueStore` का लाभ उठाता है ताकि उपकरणों में थोड़ी मात्रा में डेटा को सिंक में रखा जा सके। यह इसे वरीयताओं या उपयोगकर्ता सेटिंग्स जैसे हल्के एप्लिकेशन स्थिति को सिंक्रनाइज़ करने के लिए आदर्श बनाता है। + +### मुख्य विशेषताएँ + +- **iCloud सिंक्रनाइज़ेशन**: एक ही iCloud खाते में लॉग इन किए गए सभी उपकरणों में स्थिति को स्वचालित रूप से सिंक करें। +- **स्थायी भंडारण**: डेटा iCloud में स्थायी रूप से संग्रहीत होता है, जिसका अर्थ है कि ऐप के समाप्त होने या पुनरारंभ होने पर भी यह बना रहेगा। +- **लगभग वास्तविक समय सिंक**: स्थिति में परिवर्तन लगभग तुरंत अन्य उपकरणों में प्रचारित किए जाते हैं। + +> **ध्यान दें**: `SyncState` watchOS 9.0 और बाद के संस्करणों पर समर्थित है। + +## उपयोग का उदाहरण + +### डेटा मॉडल + +मान लें कि हमारे पास `Settings` नामक एक संरचना है जो `Codable` के अनुरूप है: + +```swift +struct Settings: Codable { + var text: String + var isShowingSheet: Bool + var isDarkMode: Bool +} +``` + +### एक SyncState को परिभाषित करना + +आप `Application` ऑब्जेक्ट का विस्तार करके और उन स्थिति गुणों की घोषणा करके `SyncState` को परिभाषित कर सकते हैं जिन्हें सिंक किया जाना चाहिए: + +```swift +extension Application { + var settings: SyncState { + syncState( + initial: Settings( + text: "Hello, World!", + isShowingSheet: false, + isDarkMode: false + ), + id: "settings" + ) + } +} +``` + +### बाहरी परिवर्तनों को संभालना + +यह सुनिश्चित करने के लिए कि ऐप iCloud से बाहरी परिवर्तनों का जवाब देता है, एक कस्टम `Application` उपवर्ग बनाकर `didChangeExternally` फ़ंक्शन को ओवरराइड करें: + +```swift +class CustomApplication: Application { + override func didChangeExternally(notification: Notification) { + super.didChangeExternally(notification: notification) + + DispatchQueue.main.async { + self.objectWillChange.send() + } + } +} +``` + +### स्थिति को संशोधित और सिंक करने के लिए दृश्य बनाना + +निम्नलिखित उदाहरण में, हमारे पास दो दृश्य हैं: `ContentView` और `ContentViewInnerView`। ये दृश्य उनके बीच `Settings` स्थिति को साझा और सिंक करते हैं। `ContentView` उपयोगकर्ता को `text` को संशोधित करने और `isDarkMode` को टॉगल करने की अनुमति देता है, जबकि `ContentViewInnerView` वही पाठ प्रदर्शित करता है और टैप किए जाने पर इसे अपडेट करता है। + +```swift +struct ContentView: View { + @SyncState(\.settings) private var settings: Settings + + var body: some View { + VStack { + TextField("", text: $settings.text) + + Button(settings.isDarkMode ? "Light" : "Dark") { + settings.isDarkMode.toggle() + } + + Button("Show") { settings.isShowingSheet = true } + } + .preferredColorScheme(settings.isDarkMode ? .dark : .light) + .sheet(isPresented: $settings.isShowingSheet, content: ContentViewInnerView.init) + } +} + +struct ContentViewInnerView: View { + @Slice(\.settings, \.text) private var text: String + + var body: some View { + Text("\(text)") + .onTapGesture { + text = Date().formatted() + } + } +} +``` + +### ऐप सेट करना + +अंत में, `@main` संरचना में एप्लिकेशन सेट करें। इनिशियलाइज़ेशन में, कस्टम एप्लिकेशन को बढ़ावा दें, लॉगिंग सक्षम करें, और सिंक्रनाइज़ेशन के लिए iCloud स्टोर निर्भरता लोड करें: + +```swift +@main +struct SyncStateExampleApp: App { + init() { + Application + .promote(to: CustomApplication.self) + .logging(isEnabled: true) + .load(dependency: \.icloudStore) + } + + var body: some Scene { + WindowGroup { + ContentView() + } + } +} +``` + +### iCloud की-वैल्यू स्टोर सक्षम करना + +iCloud सिंकिंग सक्षम करने के लिए, सुनिश्चित करें कि आप iCloud कुंजी-मूल्य संग्रहण क्षमता को सक्षम करने के लिए इस गाइड का पालन करते हैं: [SyncState का उपयोग शुरू करना](starting-to-use-syncstate.md). + +### SyncState: iCloud संग्रहण पर नोट्स + +जबकि `SyncState` आसान सिंक्रनाइज़ेशन की अनुमति देता है, `NSUbiquitousKeyValueStore` की सीमाओं को याद रखना महत्वपूर्ण है: + +- **भंडारण सीमा**: आप `NSUbiquitousKeyValueStore` का उपयोग करके iCloud में 1 एमबी तक डेटा संग्रहीत कर सकते हैं, प्रति-कुंजी मान आकार सीमा 1 एमबी है। + +### प्रवासन संबंधी विचार + +अपने डेटा मॉडल को अपडेट करते समय, संभावित प्रवासन चुनौतियों का हिसाब रखना महत्वपूर्ण है, खासकर जब **StoredState**, **FileState**, या **SyncState** का उपयोग करके स्थायी डेटा के साथ काम कर रहे हों। उचित प्रवासन प्रबंधन के बिना, नए फ़ील्ड जोड़ने या डेटा प्रारूपों को संशोधित करने जैसे परिवर्तन पुराने डेटा लोड होने पर समस्याएँ पैदा कर सकते हैं। + +यहाँ कुछ मुख्य बातें ध्यान में रखनी हैं: +- **नए गैर-वैकल्पिक फ़ील्ड जोड़ना**: सुनिश्चित करें कि नए फ़ील्ड या तो वैकल्पिक हैं या पश्चगामी संगतता बनाए रखने के लिए डिफ़ॉल्ट मान हैं। +- **डेटा प्रारूप परिवर्तनों को संभालना**: यदि आपके मॉडल की संरचना बदलती है, तो पुराने प्रारूपों का समर्थन करने के लिए कस्टम डीकोडिंग तर्क लागू करें। +- **अपने मॉडलों का संस्करण बनाना**: प्रवासन में मदद करने और डेटा के संस्करण के आधार पर तर्क लागू करने के लिए अपने मॉडलों में `version` फ़ील्ड का उपयोग करें। + +प्रवासन का प्रबंधन करने और संभावित समस्याओं से बचने के तरीके के बारे में अधिक जानने के लिए, [प्रवासन संबंधी विचार मार्गदर्शिका](migration-considerations.md) देखें। + +## SyncState कार्यान्वयन गाइड + +iCloud को कॉन्फ़िगर करने और अपने प्रोजेक्ट में SyncState को सेट करने के बारे में विस्तृत निर्देशों के लिए, [SyncState कार्यान्वयन गाइड](syncstate-implementation.md) देखें। + +## सर्वोत्तम प्रथाएं + +- **छोटे, महत्वपूर्ण डेटा के लिए उपयोग करें**: `SyncState` उपयोगकर्ता वरीयताओं, सेटिंग्स, या सुविधा झंडे जैसे राज्य के छोटे, महत्वपूर्ण टुकड़ों को सिंक्रनाइज़ करने के लिए आदर्श है। +- **iCloud संग्रहण की निगरानी करें**: सुनिश्चित करें कि डेटा सिंक समस्याओं को रोकने के लिए `SyncState` का आपका उपयोग iCloud संग्रहण सीमाओं के भीतर रहता है। +- **बाहरी अपडेट को संभालें**: यदि आपके ऐप को किसी अन्य डिवाइस पर शुरू किए गए स्थिति परिवर्तनों का जवाब देने की आवश्यकता है, तो ऐप की स्थिति को वास्तविक समय में अपडेट करने के लिए `didChangeExternally` फ़ंक्शन को ओवरराइड करें। + +## निष्कर्ष + +`SyncState` iCloud के माध्यम से उपकरणों में थोड़ी मात्रा में एप्लिकेशन स्थिति को सिंक्रनाइज़ करने का एक शक्तिशाली तरीका प्रदान करता है। यह सुनिश्चित करने के लिए आदर्श है कि उपयोगकर्ता वरीयताएँ और अन्य प्रमुख डेटा एक ही iCloud खाते में लॉग इन किए गए सभी उपकरणों में सुसंगत रहें। अधिक उन्नत उपयोग के मामलों के लिए, **AppState** की अन्य विशेषताओं, जैसे [SecureState](usage-securestate.md) और [FileState](usage-filestate.md) का अन्वेषण करें। + +--- +यह अनुवाद स्वचालित रूप से उत्पन्न किया गया था और इसमें त्रुटियाँ हो सकती हैं। यदि आप एक देशी वक्ता हैं, तो हम एक पुल अनुरोध के माध्यम से सुधारों में आपके योगदान की सराहना करेंगे। diff --git a/documentation/pt/advanced-usage.md b/documentation/pt/advanced-usage.md new file mode 100644 index 0000000..3c0e72a --- /dev/null +++ b/documentation/pt/advanced-usage.md @@ -0,0 +1,181 @@ +# Uso Avançado do AppState + +Este guia aborda tópicos avançados para o uso do **AppState**, incluindo criação Just-In-Time, pré-carregamento de dependências, gerenciamento eficaz de estados e dependências, e comparação do **AppState** com o **Ambiente do SwiftUI**. + +## 1. Criação Just-In-Time + +Os valores do AppState, como `State`, `Dependency`, `StoredState` e `SyncState`, são criados just-in-time. Isso significa que eles são instanciados apenas quando acessados pela primeira vez, melhorando a eficiência e o desempenho de sua aplicação. + +### Exemplo + +```swift +extension Application { + var defaultState: State { + state(initial: 0) // O valor não é criado até ser acessado + } +} +``` + +Neste exemplo, `defaultState` não é criado até ser acessado pela primeira vez, otimizando o uso de recursos. + +## 2. Pré-carregamento de Dependências + +Em alguns casos, você pode querer pré-carregar certas dependências para garantir que elas estejam disponíveis quando sua aplicação for iniciada. O AppState fornece uma função `load` que pré-carrega as dependências. + +### Exemplo + +```swift +extension Application { + var databaseClient: Dependency { + dependency(DatabaseClient()) + } +} + +// Pré-carregar na inicialização do aplicativo +Application.load(dependency: \.databaseClient) +``` + +Neste exemplo, `databaseClient` é pré-carregado durante a inicialização do aplicativo, garantindo que ele esteja disponível quando necessário em suas visualizações. + +## 3. Gerenciamento de Estado e Dependências + +### 3.1 Estado e Dependências Compartilhados em Toda a Aplicação + +Você pode definir um estado ou dependências compartilhadas em uma parte de sua aplicação e acessá-los em outra parte usando IDs exclusivos. + +### Exemplo + +```swift +private extension Application { + var stateValue: State { + state(initial: 0, id: "stateValue") + } + + var dependencyValue: Dependency { + dependency(SomeType(), id: "dependencyValue") + } +} +``` + +Isso permite que você acesse o mesmo `State` ou `Dependency` em outro lugar, usando o mesmo ID. + +```swift +private extension Application { + var theSameStateValue: State { + state(initial: 0, id: "stateValue") + } + + var theSameDependencyValue: Dependency { + dependency(SomeType(), id: "dependencyValue") + } +} +``` + +Embora essa abordagem seja válida para compartilhar estados e dependências em toda a aplicação, reutilizando o mesmo `id` de string, geralmente é desencorajada. Ela depende do gerenciamento manual desses IDs de string, o que pode levar a: +- Colisões acidentais de ID se o mesmo ID for usado para diferentes estados/dependências pretendidos. +- Dificuldade em rastrear onde um estado/dependência é definido versus acessado. +- Redução da clareza e manutenibilidade do código. +O valor `initial` fornecido em definições subsequentes com o mesmo ID será ignorado se o estado/dependência já tiver sido inicializado pelo seu primeiro acesso. Esse comportamento é mais um efeito colateral de como o cache baseado em ID funciona no AppState, em vez de um padrão primário recomendado para definir dados compartilhados. Prefira definir estados e dependências como propriedades computadas exclusivas em extensões de `Application` (que geram automaticamente IDs internos exclusivos se nenhum `id` explícito for fornecido ao método de fábrica). + +### 3.2 Acesso Restrito a Estado e Dependências + +Para restringir o acesso, use um ID exclusivo como um UUID para garantir que apenas as partes corretas da aplicação possam acessar estados ou dependências específicos. + +### Exemplo + +```swift +private extension Application { + var restrictedState: State { + state(initial: nil, id: UUID().uuidString) + } + + var restrictedDependency: Dependency { + dependency(SomeType(), id: UUID().uuidString) + } +} +``` + +### 3.3 IDs Exclusivos para Estados e Dependências + +Quando nenhum ID é fornecido, o AppState gera um ID padrão com base na localização no código-fonte. Isso garante que cada `State` ou `Dependency` seja exclusivo e protegido contra acessos não intencionais. + +### Exemplo + +```swift +extension Application { + var defaultState: State { + state(initial: 0) // O AppState gera um ID exclusivo + } + + var defaultDependency: Dependency { + dependency(SomeType()) // O AppState gera um ID exclusivo + } +} +``` + +### 3.4 Acesso a Estado e Dependências Privado ao Arquivo + +Para um acesso ainda mais restrito dentro do mesmo arquivo Swift, use o nível de acesso `fileprivate` para proteger os estados e as dependências de serem acessados externamente. + +### Exemplo + +```swift +fileprivate extension Application { + var fileprivateState: State { + state(initial: 0) + } + + var fileprivateDependency: Dependency { + dependency(SomeType()) + } +} +``` + +### 3.5 Entendendo o Mecanismo de Armazenamento do AppState + +O AppState usa um cache unificado para armazenar `State`, `Dependency`, `StoredState` e `SyncState`. Isso garante que esses tipos de dados sejam gerenciados de forma eficiente em toda a sua aplicação. + +Por padrão, o AppState atribui um valor de nome como "App", o que garante que todos os valores associados a um módulo estejam vinculados a esse nome. Isso torna mais difícil o acesso a esses estados e dependências de outros módulos. + +## 4. AppState vs Ambiente do SwiftUI + +O AppState e o Ambiente do SwiftUI oferecem maneiras de gerenciar o estado compartilhado e as dependências em sua aplicação, mas eles diferem em escopo, funcionalidade e casos de uso. + +### 4.1 Ambiente do SwiftUI + +O Ambiente do SwiftUI é um mecanismo integrado que permite passar dados compartilhados por uma hierarquia de visualizações. É ideal para passar dados aos quais muitas visualizações precisam de acesso, mas tem limitações quando se trata de um gerenciamento de estado mais complexo. + +**Pontos fortes:** +- Simples de usar e bem integrado com o SwiftUI. +- Ideal para dados leves que precisam ser compartilhados entre várias visualizações em uma hierarquia. + +**Limitações:** +- Os dados estão disponíveis apenas dentro da hierarquia de visualizações específica. Acessar os mesmos dados em diferentes hierarquias de visualizações não é possível sem trabalho adicional. +- Menos controle sobre a segurança de threads e a persistência em comparação com o AppState. +- Falta de mecanismos de persistência ou sincronização integrados. + +### 4.2 AppState + +O AppState fornece um sistema mais poderoso e flexível para gerenciar o estado em toda a aplicação, com capacidades de segurança de threads, persistência e injeção de dependências. + +**Pontos fortes:** +- Gerenciamento de estado centralizado, acessível em toda a aplicação, não apenas em hierarquias de visualizações específicas. +- Mecanismos de persistência integrados (`StoredState`, `FileState` e `SyncState`). +- Garantias de segurança de tipos e de threads, garantindo que o estado seja acessado e modificado corretamente. +- Pode lidar com um gerenciamento de estado e dependências mais complexo. + +**Limitações:** +- Requer mais configuração em comparação com o Ambiente do SwiftUI. +- Um pouco menos integrado com o SwiftUI em comparação com o Environment, embora ainda funcione bem em aplicações SwiftUI. + +### 4.3 Quando Usar Cada Um + +- Use o **Ambiente do SwiftUI** quando tiver dados simples que precisam ser compartilhados em uma hierarquia de visualizações, como configurações do usuário ou preferências de tema. +- Use o **AppState** quando precisar de gerenciamento de estado centralizado, persistência ou um estado mais complexo que precise ser acessado em toda a aplicação. + +## Conclusão + +Ao usar essas técnicas avançadas, como criação just-in-time, pré-carregamento, gerenciamento de estados e dependências, e entender as diferenças entre o AppState e o Ambiente do SwiftUI, você pode construir aplicações eficientes e conscientes dos recursos com o **AppState**. + +--- +Esta tradução foi gerada automaticamente e pode conter erros. Se você é um falante nativo, agradecemos suas contribuições com correções por meio de um Pull Request. diff --git a/documentation/pt/best-practices.md b/documentation/pt/best-practices.md new file mode 100644 index 0000000..a62c454 --- /dev/null +++ b/documentation/pt/best-practices.md @@ -0,0 +1,65 @@ +# Melhores Práticas para Usar o AppState + +Este guia fornece as melhores práticas para ajudá-lo a usar o AppState de forma eficiente e eficaz em suas aplicações Swift. + +## 1. Use o AppState com Moderação + +O AppState é versátil e adequado tanto para o gerenciamento de estado compartilhado quanto localizado. É ideal para dados que precisam ser compartilhados entre múltiplos componentes, persistir através de visualizações ou sessões de usuário, ou ser gerenciados no nível do componente. No entanto, o uso excessivo pode levar a uma complexidade desnecessária. + +### Recomendação: +- Use o AppState para dados que realmente precisam ser de toda a aplicação, compartilhados entre componentes distantes, ou que exijam as funcionalidades específicas de persistência/sincronização do AppState. +- Para o estado que é local a uma única visualização SwiftUI ou a uma hierarquia próxima de visualizações, prefira as ferramentas integradas do SwiftUI como `@State`, `@StateObject`, `@ObservedObject`, ou `@EnvironmentObject`. + +## 2. Mantenha um AppState Limpo + +À medida que sua aplicação se expande, seu AppState pode crescer em complexidade. Revise e refatore regularmente seu AppState para remover estados e dependências não utilizados. Manter seu AppState limpo torna mais simples de entender, manter e testar. + +### Recomendação: +- Audite periodicamente seu AppState em busca de estados e dependências não utilizados ou redundantes. +- Refatore grandes estruturas de AppState para mantê-las limpas e gerenciáveis. + +## 3. Teste seu AppState + +Assim como outros aspectos de sua aplicação, certifique-se de que seu AppState seja testado exaustivamente. Use dependências simuladas para isolar seu AppState de dependências externas durante os testes, e confirme que cada parte de sua aplicação se comporta como esperado. + +### Recomendação: +- Use o XCTest ou frameworks semelhantes para testar o comportamento e as interações do AppState. +- Simule ou crie stubs de dependências para garantir que os testes do AppState sejam isolados e confiáveis. + +## 4. Use o Recurso de Slice com Sabedoria + +O recurso `Slice` permite que você acesse partes específicas do estado de um AppState, o que é útil para lidar com estruturas de estado grandes e complexas. No entanto, use este recurso com sabedoria para manter um AppState limpo e bem organizado, evitando slices desnecessários que fragmentam o gerenciamento do estado. + +### Recomendação: +- Use `Slice` apenas para estados grandes ou aninhados onde o acesso a componentes individuais é necessário. +- Evite o excesso de slicing do estado, o que pode levar à confusão e a um gerenciamento de estado fragmentado. + +## 5. Use Constantes para Valores Estáticos + +O recurso `@Constant` permite que você defina constantes de apenas leitura que podem ser compartilhadas em toda a sua aplicação. É útil para valores que permanecem inalterados ao longo do ciclo de vida de sua aplicação, como configurações ou dados predefinidos. As constantes garantem que esses valores não sejam modificados involuntariamente. + +### Recomendação: +- Use `@Constant` para valores que permanecem inalterados, como configurações da aplicação, variáveis de ambiente ou referências estáticas. + +## 6. Modularize seu AppState + +Para aplicações maiores, considere dividir seu AppState em módulos menores e mais gerenciáveis. Cada módulo pode ter seu próprio estado e dependências, que são então compostos no AppState geral. Isso pode tornar seu AppState mais fácil de entender, testar e manter. + +### Recomendação: +- Organize suas extensões de `Application` em arquivos Swift separados ou até mesmo em módulos Swift separados, agrupados por recurso ou domínio. Isso modulariza naturalmente as definições. +- Ao definir estados ou dependências usando métodos de fábrica como `state(initial:feature:id:)`, utilize o parâmetro `feature` para fornecer um namespace, por exemplo, `state(initial: 0, feature: "UserProfile", id: "score")`. Isso ajuda a organizar e prevenir colisões de ID se forem usados IDs manuais. +- Evite criar múltiplas instâncias de `Application`. Limite-se a estender e usar o singleton compartilhado (`Application.shared`). + +## 7. Aproveite a Criação Just-In-Time + +Os valores do AppState são criados just-in-time, o que significa que são instanciados apenas quando acessados. Isso otimiza o uso da memória e garante que os valores do AppState só sejam criados quando necessário. + +### Recomendação: +- Permita que os valores do AppState sejam criados just-in-time em vez de pré-carregar desnecessariamente todos os estados e dependências. + +## Conclusão + +Cada aplicação é única, então estas melhores práticas podem não se adequar a todas as situações. Sempre considere os requisitos específicos de sua aplicação ao decidir como usar o AppState, e esforce-se para manter seu gerenciamento de estado limpo, eficiente e bem testado. + +--- +Esta tradução foi gerada automaticamente e pode conter erros. Se você é um falante nativo, agradecemos suas contribuições com correções por meio de um Pull Request. diff --git a/documentation/pt/contributing.md b/documentation/pt/contributing.md new file mode 100644 index 0000000..0b5aa8d --- /dev/null +++ b/documentation/pt/contributing.md @@ -0,0 +1,63 @@ +# Contribuindo para o AppState + +Obrigado por considerar contribuir para o **AppState**! Suas contribuições ajudam a tornar este projeto melhor para todos. + +## Como Contribuir + +### 1. Relatando Bugs + +Se você encontrar algum bug, por favor, abra uma issue no GitHub. Ao relatar um bug, por favor, inclua: + +- Um título claro e descritivo. +- Uma descrição detalhada do bug, incluindo os passos para reproduzi-lo. +- O comportamento esperado e o que realmente aconteceu. +- A versão do **AppState** que você está usando. +- Quaisquer capturas de tela ou logs relevantes. + +### 2. Sugerindo Funcionalidades + +Novas ideias são bem-vindas! Se você tem uma funcionalidade que gostaria de ver adicionada ao **AppState**, por favor, abra uma issue e descreva: + +- O problema que a funcionalidade resolveria. +- Como você acha que a funcionalidade deveria funcionar. +- Qualquer contexto ou exemplos adicionais que ajudem a ilustrar sua ideia. + +### 3. Enviando Pull Requests + +Se você gostaria de contribuir com código para o **AppState**, siga estes passos: + +1. **Faça um Fork do Repositório**: Crie um fork pessoal do repositório **AppState** no GitHub. +2. **Clone o Seu Fork**: Clone o seu fork para a sua máquina local: + ```bash + git clone https://github.com/your-username/AppState.git + ``` +3. **Crie um Novo Ramo**: Crie um novo ramo para a sua funcionalidade ou correção de bug: + ```bash + git checkout -b meu-ramo-de-funcionalidade + ``` +4. **Faça as Alterações**: Implemente as suas alterações no novo ramo. +5. **Teste as Suas Alterações**: Garanta que as suas alterações passam em todos os testes. Adicione novos testes, se necessário. +6. **Faça o Commit das Suas Alterações**: Faça o commit das suas alterações com uma mensagem de commit descritiva: + ```bash + git commit -m "Adicionar a minha nova funcionalidade" + ``` +7. **Envie para o GitHub**: Envie o seu ramo para o seu fork no GitHub: + ```bash + git push origin meu-ramo-de-funcionalidade + ``` +8. **Crie um Pull Request**: Vá para o repositório **AppState** no GitHub e crie um pull request a partir do seu ramo. + +### 4. Estilo de Código + +Por favor, siga as diretrizes de estilo de codificação usadas no projeto **AppState**. Um estilo de código consistente ajuda a tornar a base de código mais fácil de manter e revisar. + +### 5. Licença + +Ao contribuir para o **AppState**, você concorda que as suas contribuições serão licenciadas sob a mesma licença que o projeto: [LICENÇA](https://github.com/0xLeif/AppState/blob/main/LICENSE). + +## Obrigado! + +As suas contribuições são muito valorizadas e apreciadas. Obrigado por ajudar a melhorar o **AppState**! + +--- +Esta tradução foi gerada automaticamente e pode conter erros. Se você é um falante nativo, agradecemos suas contribuições com correções por meio de um Pull Request. diff --git a/documentation/pt/faq.md b/documentation/pt/faq.md new file mode 100644 index 0000000..cf9fe79 --- /dev/null +++ b/documentation/pt/faq.md @@ -0,0 +1,43 @@ +# Perguntas Frequentes + +Este breve FAQ aborda questões comuns que os desenvolvedores podem ter ao usar o **AppState**. + +## Como eu redefino um valor de estado? + +Para estados persistentes como `StoredState`, `FileState` e `SyncState`, você pode redefini-los para seus valores iniciais usando as funções estáticas `reset` no tipo `Application`. + +Por exemplo, para redefinir um `StoredState`: +```swift +extension Application { + var hasCompletedOnboarding: StoredState { storedState(initial: false, id: "onboarding_complete") } +} + +// Em algum lugar do seu código +Application.reset(storedState: \.hasCompletedOnboarding) +``` +Isso redefinirá o valor no `UserDefaults` de volta para `false`. Funções `reset` semelhantes existem para `FileState`, `SyncState` e `SecureState`. + +Para um `State` não persistente, você pode redefini-lo da mesma forma que os estados persistentes: +```swift +extension Application { + var counter: State { state(initial: 0) } +} + +// Em algum lugar do seu código +Application.reset(\.counter) +``` + +## Posso usar o AppState com tarefas assíncronas? + +Sim. Os valores de `State` e de dependência são thread-safe e funcionam perfeitamente com o Swift Concurrency. Você pode acessá-los e modificá-los dentro de funções `async` sem bloqueio adicional. + +## Onde devo definir os estados e as dependências? + +Mantenha todos os seus estados e dependências em extensões de `Application`. Isso garante uma única fonte de verdade e facilita a descoberta de todos os valores disponíveis. + +## O AppState é compatível com o Combine? + +Você pode usar o AppState junto com o Combine, fazendo a ponte entre as alterações de `State` e os publishers. Observe um valor de `State` e envie atualizações através de um `PassthroughSubject` ou outro publisher do Combine, se necessário. + +--- +Esta tradução foi gerada automaticamente e pode conter erros. Se você é um falante nativo, agradecemos suas contribuições com correções por meio de um Pull Request. diff --git a/documentation/pt/installation.md b/documentation/pt/installation.md new file mode 100644 index 0000000..4872dac --- /dev/null +++ b/documentation/pt/installation.md @@ -0,0 +1,87 @@ +# Guia de Instalação + +Este guia irá orientá-lo através do processo de instalação do **AppState** no seu projeto Swift usando o Swift Package Manager. + +## Swift Package Manager + +O **AppState** pode ser facilmente integrado ao seu projeto usando o Swift Package Manager. Siga os passos abaixo para adicionar o **AppState** como uma dependência. + +### Passo 1: Atualize o seu Arquivo `Package.swift` + +Adicione o **AppState** à seção `dependencies` do seu arquivo `Package.swift`: + +```swift +dependencies: [ + .package(url: "https://github.com/0xLeif/AppState.git", from: "2.2.0") +] +``` + +### Passo 2: Adicione o AppState ao seu Alvo + +Inclua o AppState nas dependências do seu alvo: + +```swift +.target( + name: "YourTarget", + dependencies: ["AppState"] +) +``` + +### Passo 3: Compile o seu Projeto + +Depois de adicionar o AppState ao seu arquivo `Package.swift`, compile o seu projeto para buscar a dependência e integrá-la ao seu código-base. + +``` +swift build +``` + +### Passo 4: Importe o AppState no seu Código + +Agora, você pode começar a usar o AppState no seu projeto importando-o no topo dos seus arquivos Swift: + +```swift +import AppState +``` + +## Xcode + +Se você preferir adicionar o **AppState** diretamente através do Xcode, siga estes passos: + +### Passo 1: Abra o seu Projeto Xcode + +Abra o seu projeto ou workspace do Xcode. + +### Passo 2: Adicione uma Dependência de Pacote Swift + +1. Navegue até o navegador de projetos e selecione o arquivo do seu projeto. +2. No editor de projetos, selecione o seu alvo e, em seguida, vá para a guia "Swift Packages". +3. Clique no botão "+" para adicionar uma dependência de pacote. + +### Passo 3: Insira a URL do Repositório + +Na caixa de diálogo "Choose Package Repository", insira a seguinte URL: `https://github.com/0xLeif/AppState.git` + +Em seguida, clique em "Próximo". + +### Passo 4: Especifique a Versão + +Escolha a versão que deseja usar. Recomenda-se selecionar a opção "Up to Next Major Version" e especificar `2.0.0` como o limite inferior. Em seguida, clique em "Próximo". + +### Passo 5: Adicione o Pacote + +O Xcode buscará o pacote e apresentará opções para adicionar o **AppState** ao seu alvo. Certifique-se de selecionar o alvo correto e clique em "Finalizar". + +### Passo 6: Importe o `AppState` no seu Código + +Agora você pode importar o **AppState** no topo dos seus arquivos Swift: + +```swift +import AppState +``` + +## Próximos Passos + +Com o AppState instalado, você pode avançar para a [Visão Geral do Uso](usage-overview.md) para ver como implementar os principais recursos no seu projeto. + +--- +Esta tradução foi gerada automaticamente e pode conter erros. Se você é um falante nativo, agradecemos suas contribuições com correções por meio de um Pull Request. diff --git a/documentation/pt/migration-considerations.md b/documentation/pt/migration-considerations.md new file mode 100644 index 0000000..24f34da --- /dev/null +++ b/documentation/pt/migration-considerations.md @@ -0,0 +1,81 @@ +# Considerações sobre Migração + +Ao atualizar seu modelo de dados, especialmente para dados persistidos ou sincronizados, você precisa lidar com a compatibilidade retroativa para evitar possíveis problemas ao carregar dados mais antigos. Aqui estão alguns pontos importantes a serem lembrados: + +## 1. Adicionando Campos Não Opcionais +Se você adicionar novos campos não opcionais ao seu modelo, a decodificação de dados antigos (que não conterão esses campos) pode falhar. Para evitar isso: +- Considere dar valores padrão aos novos campos. +- Torne os novos campos opcionais para garantir a compatibilidade com versões mais antigas do seu aplicativo. + +### Exemplo: +```swift +struct Settings: Codable { + var text: String + var isDarkMode: Bool + var newField: String? // Novo campo é opcional +} +``` + +## 2. Mudanças no Formato dos Dados +Se você modificar a estrutura de um modelo (por exemplo, alterando um tipo de `Int` para `String`), o processo de decodificação pode falhar ao ler dados mais antigos. Planeje uma migração suave: +- Criando uma lógica de migração para converter formatos de dados antigos para a nova estrutura. +- Usando o inicializador personalizado de `Decodable` para lidar com dados antigos e mapeá-los para o seu novo modelo. + +### Exemplo: +```swift +struct Settings: Codable { + var text: String + var isDarkMode: Bool + var version: Int + + // Lógica de decodificação personalizada para versões mais antigas + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.text = try container.decode(String.self, forKey: .text) + self.isDarkMode = try container.decode(Bool.self, forKey: .isDarkMode) + self.version = (try? container.decode(Int.self, forKey: .version)) ?? 1 // Padrão para dados mais antigos + } +} +``` + +## 3. Lidando com Campos Excluídos ou Obsoletos +Se você remover um campo do modelo, certifique-se de que as versões antigas do aplicativo ainda possam decodificar os novos dados sem travar. Você pode: +- Ignorar campos extras ao decodificar. +- Usar decodificadores personalizados para lidar com dados antigos e gerenciar campos obsoletos adequadamente. + +## 4. Versionando Seus Modelos + +O versionamento de seus modelos permite que você lide com as mudanças em sua estrutura de dados ao longo do tempo. Ao manter um número de versão como parte de seu modelo, você pode implementar facilmente uma lógica de migração para converter formatos de dados antigos em novos. Essa abordagem garante que seu aplicativo possa lidar com estruturas de dados antigas enquanto transita suavemente para novas versões. + +- **Por que o Versionamento é Importante**: Quando os usuários atualizam seu aplicativo, eles ainda podem ter dados mais antigos persistidos em seus dispositivos. O versionamento ajuda seu aplicativo a reconhecer o formato dos dados e a aplicar a lógica de migração correta. +- **Como Usar**: Adicione um campo `version` ao seu modelo e verifique-o durante o processo de decodificação para determinar se a migração é necessária. + +### Exemplo: +```swift +struct Settings: Codable { + var version: Int + var text: String + var isDarkMode: Bool + + // Lidar com a lógica de decodificação específica da versão + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.version = try container.decode(Int.self, forKey: .version) + self.text = try container.decode(String.self, forKey: .text) + self.isDarkMode = try container.decode(Bool.self, forKey: .isDarkMode) + + // Se estiver migrando de uma versão mais antiga, aplique as transformações necessárias aqui + if version < 2 { + // Migrar dados mais antigos para o novo formato + } + } +} +``` + +- **Melhor Prática**: Comece com um campo `version` desde o início. Cada vez que você atualizar a estrutura do seu modelo, incremente a versão e lide com a lógica de migração necessária. + +## 5. Testando a Migração +Sempre teste sua migração completamente, simulando o carregamento de dados antigos com novas versões do seu modelo para garantir que seu aplicativo se comporte como esperado. + +--- +Esta tradução foi gerada automaticamente e pode conter erros. Se você é um falante nativo, agradecemos suas contribuições com correções por meio de um Pull Request. diff --git a/documentation/pt/starting-to-use-syncstate.md b/documentation/pt/starting-to-use-syncstate.md new file mode 100644 index 0000000..abab026 --- /dev/null +++ b/documentation/pt/starting-to-use-syncstate.md @@ -0,0 +1,25 @@ +Para utilizar o SyncState, você primeiro precisará configurar os recursos e direitos do iCloud em seu projeto do Xcode. Aqui está uma introdução para guiá-lo através do processo: + +### Configurando os recursos do iCloud: + +1. Abra seu projeto do Xcode e ajuste os identificadores de pacote para os destinos macOS e iOS para corresponderem aos seus. +2. Em seguida, você precisa adicionar o recurso iCloud ao seu projeto. Para fazer isso, selecione seu projeto no Navegador de projetos e, em seguida, selecione seu destino. Na barra de guias na parte superior da área do editor, clique em "Signing & Capabilities". +3. No painel Recursos, ative o iCloud clicando no botão na linha do iCloud. Você deve ver o botão mudar para a posição Ligado. +4. Depois de habilitar o iCloud, você precisa habilitar o armazenamento de valor-chave. Você pode fazer isso marcando a caixa de seleção "Armazenamento de valor-chave". + +### Atualizando os direitos: + +1. Agora você precisará atualizar seu arquivo de direitos. Abra o arquivo de direitos para o seu destino. +2. Certifique-se de que o valor do Repositório de Valor-Chave do iCloud corresponda ao seu ID de repositório de valor-chave exclusivo. Seu ID exclusivo deve seguir o formato `$(TeamIdentifierPrefix)`. O valor padrão deve ser algo como, `$(TeamIdentifierPrefix)$(CFBundleIdentifier)`. Isso é bom para aplicativos de plataforma única, mas se seu aplicativo estiver em vários sistemas operacionais da Apple, é importante que as partes do ID do repositório de valor-chave sejam as mesmas para ambos os destinos. + +### Configurando os dispositivos: + +Além de configurar o projeto em si, você também precisa preparar os dispositivos que executarão o projeto. + +- Certifique-se de que o iCloud Drive esteja habilitado nos dispositivos iOS e macOS. +- Faça login em ambos os dispositivos usando a mesma conta do iCloud. + +Se você tiver alguma dúvida ou encontrar algum problema, sinta-se à vontade para entrar em contato ou enviar um problema. + +--- +Esta tradução foi gerada automaticamente e pode conter erros. Se você é um falante nativo, agradecemos suas contribuições com correções por meio de um Pull Request. diff --git a/documentation/pt/syncstate-implementation.md b/documentation/pt/syncstate-implementation.md new file mode 100644 index 0000000..788642f --- /dev/null +++ b/documentation/pt/syncstate-implementation.md @@ -0,0 +1,84 @@ +# Implementação do SyncState no AppState + +Este guia aborda como configurar o SyncState em sua aplicação, incluindo a configuração das capacidades do iCloud e a compreensão das possíveis limitações. + +## 1. Configurando as Capacidades do iCloud + +Para usar o SyncState em sua aplicação, você primeiro precisa habilitar o iCloud em seu projeto e configurar o armazenamento de chave-valor. + +### Passos para Habilitar o iCloud e o Armazenamento de Chave-Valor: + +1. Abra o seu projeto do Xcode e navegue até as configurações do seu projeto. +2. Na guia "Signing & Capabilities", selecione o seu alvo (iOS ou macOS). +3. Clique no botão "+ Capability" e escolha "iCloud" na lista. +4. Habilite a opção "Key-Value storage" nas configurações do iCloud. Isso permite que sua aplicação armazene e sincronize pequenas quantidades de dados usando o iCloud. + +### Configuração do Arquivo de Entitlements: + +1. No seu projeto do Xcode, encontre ou crie o **arquivo de entitlements** para a sua aplicação. +2. Certifique-se de que o Armazenamento de Chave-Valor do iCloud está configurado corretamente no arquivo de entitlements com o contêiner do iCloud correto. + +Exemplo no arquivo de entitlements: + +```xml +com.apple.developer.ubiquity-kvstore-identifier +$(TeamIdentifierPrefix)com.yourdomain.app +``` + +Certifique-se de que o valor da string corresponde ao contêiner do iCloud associado ao seu projeto. + +## 2. Usando o SyncState na sua Aplicação + +Uma vez que o iCloud esteja habilitado, você pode usar o `SyncState` na sua aplicação para sincronizar dados entre dispositivos. + +### Exemplo de Uso do SyncState: + +```swift +import AppState +import SwiftUI + +extension Application { + var syncValue: SyncState { + syncState(id: "syncValue") + } +} + +struct ContentView: View { + @SyncState(\.syncValue) private var syncValue: Int? + + var body: some View { + VStack { + if let syncValue = syncValue { + Text("SyncValue: \(syncValue)") + } else { + Text("No SyncValue") + } + + Button("Update SyncValue") { + syncValue = Int.random(in: 0..<100) + } + } + } +} +``` + +Neste exemplo, o estado de sincronização será salvo no iCloud e sincronizado em todos os dispositivos logados na mesma conta do iCloud. + +## 3. Limitações e Melhores Práticas + +O SyncState usa o `NSUbiquitousKeyValueStore`, que tem algumas limitações: + +- **Limite de Armazenamento**: O SyncState é projetado para pequenas quantidades de dados. O limite total de armazenamento é de 1 MB, e cada par de chave-valor é limitado a cerca de 1 MB. +- **Sincronização**: As alterações feitas no SyncState não são sincronizadas instantaneamente entre os dispositivos. Pode haver um pequeno atraso na sincronização, e a sincronização do iCloud pode, ocasionalmente, ser afetada pelas condições da rede. + +### Melhores Práticas: + +- **Use o SyncState para Dados Pequenos**: Certifique-se de que apenas dados pequenos, como preferências do usuário ou configurações, sejam sincronizados usando o SyncState. +- **Lide com as Falhas do SyncState com Elegância**: Use valores padrão ou mecanismos de tratamento de erros para levar em conta possíveis atrasos ou falhas na sincronização. + +## 4. Conclusão + +Ao configurar corretamente o iCloud e entender as limitações do SyncState, você pode aproveitar seu poder para sincronizar dados entre dispositivos. Certifique-se de usar o SyncState apenas para pequenas e críticas peças de dados para evitar possíveis problemas com os limites de armazenamento do iCloud. + +--- +Esta tradução foi gerada automaticamente e pode conter erros. Se você é um falante nativo, agradecemos suas contribuições com correções por meio de um Pull Request. diff --git a/documentation/pt/usage-constant.md b/documentation/pt/usage-constant.md new file mode 100644 index 0000000..5aec893 --- /dev/null +++ b/documentation/pt/usage-constant.md @@ -0,0 +1,87 @@ +# Uso de Constantes + +`Constant` na biblioteca **AppState** fornece acesso somente leitura a valores dentro do estado da sua aplicação. Funciona de forma semelhante a `Slice`, mas garante que os valores acessados sejam imutáveis. Isso torna `Constant` ideal para acessar valores que, de outra forma, poderiam ser mutáveis, mas que devem permanecer somente leitura em certos contextos. + +## Principais Características + +- **Acesso Somente Leitura**: As constantes fornecem acesso ao estado mutável, mas os valores não podem ser modificados. +- **Escopo para a Aplicação**: Assim como `Slice`, `Constant` é definido dentro da extensão `Application` e tem como escopo o acesso a partes específicas do estado. +- **Seguro para Threads**: `Constant` garante o acesso seguro ao estado em ambientes concorrentes. + +## Exemplo de Uso + +### Definindo uma Constante na Aplicação + +Veja como definir uma `Constant` na extensão `Application` para acessar um valor somente leitura: + +```swift +import AppState +import SwiftUI + +struct ExampleValue { + var username: String? + var isLoading: Bool + let value: String + var mutableValue: String +} + +extension Application { + var exampleValue: State { + state( + initial: ExampleValue( + username: "Leif", + isLoading: false, + value: "value", + mutableValue: "" + ) + ) + } +} +``` + +### Acessando a Constante em uma Visualização SwiftUI + +Em uma visualização SwiftUI, você pode usar o property wrapper `@Constant` para acessar o estado constante de forma somente leitura: + +```swift +import AppState +import SwiftUI + +struct ExampleView: View { + @Constant(\.exampleValue, \.value) var constantValue: String + + var body: some View { + Text("Valor Constante: \(constantValue)") + } +} +``` + +### Acesso Somente Leitura a um Estado Mutável + +Mesmo que o valor seja mutável em outro lugar, quando acessado através de `@Constant`, o valor se torna imutável: + +```swift +import AppState +import SwiftUI + +struct ExampleView: View { + @Constant(\.exampleValue, \.mutableValue) var constantMutableValue: String + + var body: some View { + Text("Valor Mutável Somente Leitura: \(constantMutableValue)") + } +} +``` + +## Melhores Práticas + +- **Use para Acesso Somente Leitura**: Use `Constant` para acessar partes do estado que não devem ser modificadas em certos contextos, mesmo que sejam mutáveis em outro lugar. +- **Seguro para Threads**: Assim como outros componentes do AppState, `Constant` garante o acesso seguro ao estado por threads. +- **Use `OptionalConstant` para Valores Opcionais**: Se a parte do estado que você está acessando puder ser `nil`, use `OptionalConstant` para lidar com segurança com a ausência de um valor. + +## Conclusão + +`Constant` e `OptionalConstant` fornecem uma maneira eficiente de acessar partes específicas do estado da sua aplicação de forma somente leitura. Eles garantem que valores que, de outra forma, poderiam ser mutáveis, sejam tratados como imutáveis quando acessados dentro de uma visualização, garantindo segurança e clareza no seu código. + +--- +Esta tradução foi gerada automaticamente e pode conter erros. Se você é um falante nativo, agradecemos suas contribuições com correções por meio de um Pull Request. diff --git a/documentation/pt/usage-filestate.md b/documentation/pt/usage-filestate.md new file mode 100644 index 0000000..81c7cde --- /dev/null +++ b/documentation/pt/usage-filestate.md @@ -0,0 +1,96 @@ +# Uso do FileState + +`FileState` é um componente da biblioteca **AppState** que permite armazenar e recuperar dados persistentes usando o sistema de arquivos. É útil para armazenar dados grandes ou objetos complexos que precisam ser salvos entre os lançamentos do aplicativo e restaurados quando necessário. + +## Principais Características + +- **Armazenamento Persistente**: Os dados armazenados usando `FileState` persistem entre os lançamentos do aplicativo. +- **Manuseio de Dados Grandes**: Ao contrário de `StoredState`, `FileState` é ideal para lidar com dados maiores ou mais complexos. +- **Seguro para Threads**: Assim como outros componentes do AppState, `FileState` garante o acesso seguro aos dados em ambientes concorrentes. + +## Exemplo de Uso + +### Armazenando e Recuperando Dados com FileState + +Veja como definir um `FileState` na extensão `Application` para armazenar e recuperar um objeto grande: + +```swift +import AppState +import SwiftUI + +struct UserProfile: Codable { + var name: String + var age: Int +} + +extension Application { + @MainActor + var userProfile: FileState { + fileState(initial: UserProfile(name: "Guest", age: 25), filename: "userProfile") + } +} + +struct FileStateExampleView: View { + @FileState(\.userProfile) var userProfile: UserProfile + + var body: some View { + VStack { + Text("Nome: \(userProfile.name), Idade: \(userProfile.age)") + Button("Atualizar Perfil") { + userProfile = UserProfile(name: "UpdatedName", age: 30) + } + } + } +} +``` + +### Lidando com Dados Grandes com FileState + +Quando você precisa lidar com conjuntos de dados ou objetos maiores, `FileState` garante que os dados sejam armazenados de forma eficiente no sistema de arquivos do aplicativo. Isso é útil para cenários como cache ou armazenamento offline. + +```swift +import AppState +import SwiftUI + +extension Application { + @MainActor + var largeDataset: FileState<[String]> { + fileState(initial: [], filename: "largeDataset") + } +} + +struct LargeDataView: View { + @FileState(\.largeDataset) var largeDataset: [String] + + var body: some View { + List(largeDataset, id: \.self) { item in + Text(item) + } + } +} +``` + +### Considerações sobre Migração + +Ao atualizar seu modelo de dados, é importante levar em conta os possíveis desafios de migração, especialmente ao trabalhar com dados persistentes usando **StoredState**, **FileState** ou **SyncState**. Sem o tratamento adequado da migração, alterações como adicionar novos campos ou modificar formatos de dados podem causar problemas ao carregar dados mais antigos. + +Aqui estão alguns pontos-chave a serem lembrados: +- **Adicionando Novos Campos Não Opcionais**: Certifique-se de que os novos campos sejam opcionais ou tenham valores padrão para manter a compatibilidade com versões anteriores. +- **Lidando com Alterações no Formato de Dados**: Se a estrutura do seu modelo mudar, implemente uma lógica de decodificação personalizada para suportar formatos antigos. +- **Versionando Seus Modelos**: Use um campo `version` em seus modelos para ajudar nas migrações e aplicar a lógica com base na versão dos dados. + +Para saber mais sobre como gerenciar migrações e evitar possíveis problemas, consulte o [Guia de Considerações sobre Migração](migration-considerations.md). + + +## Melhores Práticas + +- **Use para Dados Grandes ou Complexos**: Se você estiver armazenando dados grandes ou objetos complexos, `FileState` é ideal em vez de `StoredState`. +- **Acesso Seguro para Threads**: Assim como outros componentes do **AppState**, `FileState` garante que os dados sejam acessados com segurança, mesmo quando várias tarefas interagem com os dados armazenados. +- **Combine com Codable**: Ao trabalhar com tipos de dados personalizados, certifique-se de que eles estejam em conformidade com `Codable` para simplificar a codificação e decodificação de e para o sistema de arquivos. + +## Conclusão + +`FileState` é uma ferramenta poderosa para lidar com dados persistentes em seu aplicativo, permitindo que você armazene e recupere objetos maiores ou mais complexos de maneira segura para threads e persistente. Ele funciona perfeitamente com o protocolo `Codable` do Swift, garantindo que seus dados possam ser facilmente serializados e desserializados para armazenamento a longo prazo. + +--- +Esta tradução foi gerada automaticamente e pode conter erros. Se você é um falante nativo, agradecemos suas contribuições com correções por meio de um Pull Request. diff --git a/documentation/pt/usage-observeddependency.md b/documentation/pt/usage-observeddependency.md new file mode 100644 index 0000000..f1b1972 --- /dev/null +++ b/documentation/pt/usage-observeddependency.md @@ -0,0 +1,135 @@ +# Uso de ObservedDependency + +`ObservedDependency` é um componente da biblioteca **AppState** que permite que você use dependências que se conformam com `ObservableObject`. Isso é útil quando você quer que a dependência notifique suas visualizações SwiftUI sobre mudanças, tornando suas visualizações reativas e dinâmicas. + +## Principais Características + +- **Dependências Observáveis**: Use dependências que se conformam com `ObservableObject`, permitindo que a dependência atualize automaticamente suas visualizações quando seu estado muda. +- **Atualizações de IU Reativas**: As visualizações SwiftUI são atualizadas automaticamente quando as alterações são publicadas pela dependência observada. +- **Seguro para Threads**: Como outros componentes do AppState, `ObservedDependency` garante acesso seguro à dependência observada em threads. + +## Exemplo de Uso + +### Definindo uma Dependência Observável + +Veja como definir um serviço observável como uma dependência na extensão `Application`: + +```swift +import AppState +import SwiftUI + +@MainActor +class ObservableService: ObservableObject { + @Published var count: Int = 0 +} + +extension Application { + @MainActor + var observableService: Dependency { + dependency(ObservableService()) + } +} +``` + +### Usando a Dependência Observada em uma Visualização SwiftUI + +Em sua visualização SwiftUI, você pode acessar a dependência observável usando o property wrapper `@ObservedDependency`. O objeto observado atualiza automaticamente a visualização sempre que seu estado muda. + +```swift +import AppState +import SwiftUI + +struct ObservedDependencyExampleView: View { + @ObservedDependency(\.observableService) var service: ObservableService + + var body: some View { + VStack { + Text("Contagem: \(service.count)") + Button("Incrementar Contagem") { + service.count += 1 + } + } + } +} +``` + +### Caso de Teste + +O seguinte caso de teste demonstra a interação com `ObservedDependency`: + +```swift +import XCTest +@testable import AppState + +@MainActor +fileprivate class ObservableService: ObservableObject { + @Published var count: Int + + init() { + count = 0 + } +} + +fileprivate extension Application { + @MainActor + var observableService: Dependency { + dependency(ObservableService()) + } +} + +@MainActor +fileprivate struct ExampleDependencyWrapper { + @ObservedDependency(\.observableService) var service + + func test() { + service.count += 1 + } +} + +final class ObservedDependencyTests: XCTestCase { + @MainActor + func testDependency() async { + let example = ExampleDependencyWrapper() + + XCTAssertEqual(example.service.count, 0) + + example.test() + + XCTAssertEqual(example.service.count, 1) + } +} +``` + +### Atualizações de IU Reativas + +Como a dependência se conforma com `ObservableObject`, qualquer alteração em seu estado acionará uma atualização da IU na visualização SwiftUI. Você pode vincular o estado diretamente a elementos da IU como um `Picker`: + +```swift +import AppState +import SwiftUI + +struct ReactiveView: View { + @ObservedDependency(\.observableService) var service: ObservableService + + var body: some View { + Picker("Selecionar Contagem", selection: $service.count) { + ForEach(0..<10) { count in + Text("\(count)").tag(count) + } + } + } +} +``` + +## Melhores Práticas + +- **Use para Serviços Observáveis**: `ObservedDependency` é ideal quando sua dependência precisa notificar as visualizações sobre mudanças, especialmente para serviços que fornecem atualizações de dados ou de estado. +- **Aproveite as Propriedades Publicadas**: Certifique-se de que sua dependência use propriedades `@Published` para acionar atualizações em suas visualizações SwiftUI. +- **Seguro para Threads**: Como outros componentes do AppState, `ObservedDependency` garante acesso e modificações seguros para threads ao serviço observável. + +## Conclusão + +`ObservedDependency` é uma ferramenta poderosa para gerenciar dependências observáveis dentro de seu aplicativo. Ao aproveitar o protocolo `ObservableObject` do Swift, ele garante que suas visualizações SwiftUI permaneçam reativas e atualizadas com as mudanças no serviço ou recurso. + +--- +Esta tradução foi gerada automaticamente e pode conter erros. Se você é um falante nativo, agradecemos suas contribuições com correções por meio de um Pull Request. diff --git a/documentation/pt/usage-overview.md b/documentation/pt/usage-overview.md new file mode 100644 index 0000000..ec1efa4 --- /dev/null +++ b/documentation/pt/usage-overview.md @@ -0,0 +1,215 @@ +# Visão Geral do Uso + +Esta visão geral fornece uma introdução rápida ao uso dos principais componentes da biblioteca **AppState** dentro de uma `View` do SwiftUI. Cada seção inclui exemplos simples que se encaixam no escopo de uma estrutura de visualização do SwiftUI. + +## Definindo Valores na Extensão da Aplicação + +Para definir o estado ou as dependências de toda a aplicação, você deve estender o objeto `Application`. Isso permite que você centralize todo o estado da sua aplicação em um só lugar. Aqui está um exemplo de como estender `Application` para criar vários estados e dependências: + +```swift +import AppState + +extension Application { + var user: State { + state(initial: User(name: "Guest", isLoggedIn: false)) + } + + var userPreferences: StoredState { + storedState(initial: "Default Preferences", id: "userPreferences") + } + + var darkModeEnabled: SyncState { + syncState(initial: false, id: "darkModeEnabled") + } + + var userToken: SecureState { + secureState(id: "userToken") + } + + @MainActor + var largeDataset: FileState<[String]> { + fileState(initial: [], filename: "largeDataset") + } +} +``` + +## State + +`State` permite que você defina um estado de toda a aplicação que pode ser acessado e modificado em qualquer lugar da sua aplicação. + +### Exemplo + +```swift +import AppState +import SwiftUI + +struct ContentView: View { + @AppState(\.user) var user: User + + var body: some View { + VStack { + Text("Olá, \(user.name)!") + Button("Fazer login") { + user.isLoggedIn.toggle() + } + } + } +} +``` + +## StoredState + +`StoredState` persiste o estado usando `UserDefaults` para garantir que os valores sejam salvos entre os lançamentos da aplicação. + +### Exemplo + +```swift +import AppState +import SwiftUI + +struct PreferencesView: View { + @StoredState(\.userPreferences) var userPreferences: String + + var body: some View { + VStack { + Text("Preferências: \(userPreferences)") + Button("Atualizar Preferências") { + userPreferences = "Updated Preferences" + } + } + } +} +``` + +## SyncState + +`SyncState` sincroniza o estado da aplicação em múltiplos dispositivos usando o iCloud. + +### Exemplo + +```swift +import AppState +import SwiftUI + +struct SyncSettingsView: View { + @SyncState(\.darkModeEnabled) var isDarkModeEnabled: Bool + + var body: some View { + VStack { + Toggle("Modo Escuro", isOn: $isDarkModeEnabled) + } + } +} +``` + +## FileState + +`FileState` é usado para armazenar dados maiores ou mais complexos de forma persistente usando o sistema de arquivos, tornando-o ideal para cache ou para salvar dados que não se encaixam nas limitações do `UserDefaults`. + +### Exemplo + +```swift +import AppState +import SwiftUI + +struct LargeDataView: View { + @FileState(\.largeDataset) var largeDataset: [String] + + var body: some View { + List(largeDataset, id: \.self) { item in + Text(item) + } + } +} +``` + +## SecureState + +`SecureState` armazena dados sensíveis de forma segura no Keychain. + +### Exemplo + +```swift +import AppState +import SwiftUI + +struct SecureView: View { + @SecureState(\.userToken) var userToken: String? + + var body: some View { + VStack { + if let token = userToken { + Text("Token do usuário: \(token)") + } else { + Text("Nenhum token encontrado.") + } + Button("Definir Token") { + userToken = "secure_token_value" + } + } + } +} +``` + +## Constant + +`Constant` fornece acesso imutável e somente leitura a valores dentro do estado da sua aplicação, garantindo a segurança ao acessar valores que não devem ser modificados. + +### Exemplo + +```swift +import AppState +import SwiftUI + +struct ExampleView: View { + @Constant(\.user, \.name) var name: String + + var body: some View { + Text("Nome de usuário: \(name)") + } +} +``` + +## Fatiando o Estado + +`Slice` e `OptionalSlice` permitem que você acesse partes específicas do estado da sua aplicação. + +### Exemplo + +```swift +import AppState +import SwiftUI + +struct SlicingView: View { + @Slice(\.user, \.name) var name: String + + var body: some View { + VStack { + Text("Nome de usuário: \(name)") + Button("Atualizar Nome de Usuário") { + name = "NewUsername" + } + } + } +} +``` + +## Melhores Práticas + +- **Use `AppState` em Visualizações SwiftUI**: Os property wrappers como `@AppState`, `@StoredState`, `@FileState`, `@SecureState` e outros são projetados para serem usados no escopo das visualizações SwiftUI. +- **Defina o Estado na Extensão da Aplicação**: Centralize o gerenciamento de estado estendendo `Application` para definir o estado e as dependências da sua aplicação. +- **Atualizações Reativas**: O SwiftUI atualiza automaticamente as visualizações quando o estado muda, então você não precisa atualizar manualmente a interface do usuário. +- **[Guia de Melhores Práticas](best-practices.md)**: Para uma análise detalhada das melhores práticas ao usar o AppState. + +## Próximos Passos + +Depois de se familiarizar com o uso básico, você pode explorar tópicos mais avançados: + +- Explore o uso de **FileState** para persistir grandes quantidades de dados em arquivos no [Guia de Uso do FileState](usage-filestate.md). +- Aprenda sobre **Constantes** e como usá-las para valores imutáveis no estado da sua aplicação no [Guia de Uso de Constantes](usage-constant.md). +- Investigue como a **Dependência** é usada no AppState para lidar com serviços compartilhados e veja exemplos no [Guia de Uso de Dependência de Estado](usage-state-dependency.md). +- Aprofunde-se em técnicas avançadas de **SwiftUI**, como o uso de `ObservedDependency` para gerenciar dependências observáveis em visualizações, no [Guia de Uso de ObservedDependency](usage-observeddependency.md). +- Para técnicas de uso mais avançadas, como criação Just-In-Time e pré-carregamento de dependências, consulte o [Guia de Uso Avançado](advanced-usage.md). + +--- +Esta tradução foi gerada automaticamente e pode conter erros. Se você é um falante nativo, agradecemos suas contribuições com correções por meio de um Pull Request. diff --git a/documentation/pt/usage-securestate.md b/documentation/pt/usage-securestate.md new file mode 100644 index 0000000..3b71ee7 --- /dev/null +++ b/documentation/pt/usage-securestate.md @@ -0,0 +1,68 @@ +# Uso do SecureState + +`SecureState` é um componente da biblioteca **AppState** que permite armazenar dados confidenciais de forma segura no Keychain. É mais adequado para armazenar pequenas porções de dados como tokens ou senhas que precisam ser criptografados com segurança. + +## Principais Características + +- **Armazenamento Seguro**: Os dados armazenados usando `SecureState` são criptografados e salvos com segurança no Keychain. +- **Persistência**: Os dados permanecem persistentes entre os lançamentos do aplicativo, permitindo a recuperação segura de valores confidenciais. + +## Limitações do Keychain + +Embora o `SecureState` seja muito seguro, ele possui certas limitações: + +- **Tamanho de Armazenamento Limitado**: O Keychain é projetado para pequenas porções de dados. Não é adequado para armazenar arquivos grandes ou conjuntos de dados. +- **Desempenho**: O acesso ao Keychain é mais lento do que o acesso ao `UserDefaults`, portanto, use-o apenas quando necessário para armazenar dados confidenciais com segurança. + +## Exemplo de Uso + +### Armazenando um Token Seguro + +```swift +import AppState +import SwiftUI + +extension Application { + var userToken: SecureState { + secureState(id: "userToken") + } +} + +struct SecureView: View { + @SecureState(\.userToken) var userToken: String? + + var body: some View { + VStack { + if let token = userToken { + Text("Token do usuário: \(token)") + } else { + Text("Nenhum token encontrado.") + } + Button("Definir Token") { + userToken = "secure_token_value" + } + } + } +} +``` + +### Lidando com a Ausência de Dados Seguros + +Ao acessar o Keychain pela primeira vez, ou se não houver valor armazenado, `SecureState` retornará `nil`. Certifique-se de lidar com este cenário adequadamente: + +```swift +if let token = userToken { + print("Token: \(token)") +} else { + print("Nenhum token disponível.") +} +``` + +## Melhores Práticas + +- **Use para Dados Pequenos**: O Keychain deve ser usado para armazenar pequenas porções de informações confidenciais como tokens, senhas e chaves. +- **Evite Grandes Conjuntos de Dados**: Se você precisar armazenar grandes conjuntos de dados com segurança, considere usar criptografia baseada em arquivos ou outros métodos, pois o Keychain não é projetado para armazenamento de grandes dados. +- **Lide com nulo**: Sempre lide com os casos em que o Keychain retorna `nil` quando nenhum valor está presente. + +--- +Esta tradução foi gerada automaticamente e pode conter erros. Se você é um falante nativo, agradecemos suas contribuições com correções por meio de um Pull Request. diff --git a/documentation/pt/usage-slice.md b/documentation/pt/usage-slice.md new file mode 100644 index 0000000..85beaf4 --- /dev/null +++ b/documentation/pt/usage-slice.md @@ -0,0 +1,94 @@ +# Uso de Slice e OptionalSlice + +`Slice` e `OptionalSlice` são componentes da biblioteca **AppState** que permitem acessar partes específicas do estado da sua aplicação. Eles são úteis quando você precisa manipular ou observar uma parte de uma estrutura de estado mais complexa. + +## Visão Geral + +- **Slice**: Permite acessar e modificar uma parte específica de um objeto `State` existente. +- **OptionalSlice**: Funciona de forma semelhante a `Slice`, mas é projetado para lidar com valores opcionais, como quando parte do seu estado pode ou não ser `nil`. + +### Principais Características + +- **Acesso Seletivo ao Estado**: Acesse apenas a parte do estado de que você precisa. +- **Segurança de Threads**: Assim como outros tipos de gerenciamento de estado no **AppState**, `Slice` e `OptionalSlice` são seguros para threads. +- **Reatividade**: As visualizações do SwiftUI são atualizadas quando a fatia do estado muda, garantindo que sua interface do usuário permaneça reativa. + +## Exemplo de Uso + +### Usando Slice + +Neste exemplo, usamos `Slice` para acessar e atualizar uma parte específica do estado — neste caso, o `username` de um objeto `User` mais complexo armazenado no estado da aplicação. + +```swift +import AppState +import SwiftUI + +struct User { + var username: String + var email: String +} + +extension Application { + var user: State { + state(initial: User(username: "Guest", email: "guest@example.com")) + } +} + +struct SlicingView: View { + @Slice(\.user, \.username) var username: String + + var body: some View { + VStack { + Text("Nome de usuário: \(username)") + Button("Atualizar Nome de Usuário") { + username = "NewUsername" + } + } + } +} +``` + +### Usando OptionalSlice + +`OptionalSlice` é útil quando parte do seu estado pode ser `nil`. Neste exemplo, o próprio objeto `User` pode ser `nil`, então usamos `OptionalSlice` para lidar com este caso com segurança. + +```swift +import AppState +import SwiftUI + +extension Application { + var user: State { + state(initial: nil) + } +} + +struct OptionalSlicingView: View { + @OptionalSlice(\.user, \.username) var username: String? + + var body: some View { + VStack { + if let username = username { + Text("Nome de usuário: \(username)") + } else { + Text("Nenhum nome de usuário disponível") + } + Button("Definir Nome de Usuário") { + username = "UpdatedUsername" + } + } + } +} +``` + +## Melhores Práticas + +- **Use `Slice` para estado não opcional**: Se o seu estado for garantido como não opcional, use `Slice` para acessá-lo e atualizá-lo. +- **Use `OptionalSlice` para estado opcional**: Se o seu estado ou parte do estado for opcional, use `OptionalSlice` para lidar com casos em que o valor pode ser `nil`. +- **Segurança de Threads**: Assim como `State`, `Slice` e `OptionalSlice` são seguros para threads e projetados para funcionar com o modelo de concorrência do Swift. + +## Conclusão + +`Slice` e `OptionalSlice` fornecem maneiras poderosas de acessar e modificar partes específicas do seu estado de maneira segura para threads. Ao aproveitar esses componentes, você pode simplificar o gerenciamento de estado em aplicações mais complexas, garantindo que sua interface do usuário permaneça reativa e atualizada. + +--- +Esta tradução foi gerada automaticamente e pode conter erros. Se você é um falante nativo, agradecemos suas contribuições com correções por meio de um Pull Request. diff --git a/documentation/pt/usage-state-dependency.md b/documentation/pt/usage-state-dependency.md new file mode 100644 index 0000000..1bd4e8e --- /dev/null +++ b/documentation/pt/usage-state-dependency.md @@ -0,0 +1,136 @@ +# Uso de Estado e Dependência + +**AppState** fornece ferramentas poderosas para gerenciar o estado de toda a aplicação e injetar dependências em visualizações SwiftUI. Ao centralizar seu estado e dependências, você pode garantir que sua aplicação permaneça consistente e de fácil manutenção. + +## Visão Geral + +- **Estado**: Representa um valor que pode ser compartilhado em toda a aplicação. Os valores de estado podem ser modificados e observados em suas visualizações SwiftUI. +- **Dependência**: Representa um recurso ou serviço compartilhado que pode ser injetado e acessado em visualizações SwiftUI. + +### Principais Características + +- **Estado Centralizado**: Defina e gerencie o estado de toda a aplicação em um só lugar. +- **Injeção de Dependência**: Injete e acesse serviços e recursos compartilhados em diferentes componentes da sua aplicação. + +## Exemplo de Uso + +### Definindo o Estado da Aplicação + +Para definir o estado de toda a aplicação, estenda o objeto `Application` e declare as propriedades de estado. + +```swift +import AppState + +struct User { + var name: String + var isLoggedIn: Bool +} + +extension Application { + var user: State { + state(initial: User(name: "Guest", isLoggedIn: false)) + } +} +``` + +### Acessando e Modificando o Estado em uma Visualização + +Você pode acessar e modificar os valores de estado diretamente em uma visualização SwiftUI usando o property wrapper `@AppState`. + +```swift +import AppState +import SwiftUI + +struct ContentView: View { + @AppState(\.user) var user: User + + var body: some View { + VStack { + Text("Olá, \(user.name)!") + Button("Fazer login") { + user.name = "John Doe" + user.isLoggedIn = true + } + } + } +} +``` + +### Definindo Dependências + +Você pode definir recursos compartilhados, como um serviço de rede, como dependências no objeto `Application`. Essas dependências podem ser injetadas em visualizações SwiftUI. + +```swift +import AppState + +protocol NetworkServiceType { + func fetchData() -> String +} + +class NetworkService: NetworkServiceType { + func fetchData() -> String { + return "Data from network" + } +} + +extension Application { + var networkService: Dependency { + dependency(NetworkService()) + } +} +``` + +### Acessando Dependências em uma Visualização + +Acesse as dependências em uma visualização SwiftUI usando o property wrapper `@AppDependency`. Isso permite injetar serviços como um serviço de rede em sua visualização. + +```swift +import AppState +import SwiftUI + +struct NetworkView: View { + @AppDependency(\.networkService) var networkService: NetworkServiceType + + var body: some View { + VStack { + Text("Dados: \(networkService.fetchData())") + } + } +} +``` + +### Combinando Estado e Dependências em uma Visualização + +Estado e dependências podem trabalhar juntos para construir uma lógica de aplicação mais complexa. Por exemplo, você pode buscar dados de um serviço e atualizar o estado: + +```swift +import AppState +import SwiftUI + +struct CombinedView: View { + @AppState(\.user) var user: User + @AppDependency(\.networkService) var networkService: NetworkServiceType + + var body: some View { + VStack { + Text("Usuário: \(user.name)") + Button("Buscar Dados") { + user.name = networkService.fetchData() + user.isLoggedIn = true + } + } + } +} +``` + +### Melhores Práticas + +- **Centralize o Estado**: Mantenha o estado de toda a sua aplicação em um só lugar para evitar duplicação e garantir a consistência. +- **Use Dependências para Serviços Compartilhados**: Injete dependências como serviços de rede, bancos de dados ou outros recursos compartilhados para evitar um acoplamento forte entre os componentes. + +## Conclusão + +Com o **AppState**, você pode gerenciar o estado de toda a aplicação e injetar dependências compartilhadas diretamente em suas visualizações SwiftUI. Este padrão ajuda a manter sua aplicação modular e de fácil manutenção. Explore outras funcionalidades da biblioteca **AppState**, como [SecureState](usage-securestate.md) e [SyncState](usage-syncstate.md), para aprimorar ainda mais o gerenciamento de estado da sua aplicação. + +--- +Esta tradução foi gerada automaticamente e pode conter erros. Se você é um falante nativo, agradecemos suas contribuições com correções por meio de um Pull Request. diff --git a/documentation/pt/usage-storedstate.md b/documentation/pt/usage-storedstate.md new file mode 100644 index 0000000..de8096d --- /dev/null +++ b/documentation/pt/usage-storedstate.md @@ -0,0 +1,75 @@ +# Uso do StoredState + +`StoredState` é um componente da biblioteca **AppState** que permite armazenar e persistir pequenas quantidades de dados usando `UserDefaults`. É ideal para armazenar dados leves e não sensíveis que devem persistir entre os lançamentos do aplicativo. + +## Visão Geral + +- **StoredState** é construído sobre `UserDefaults`, o que significa que é rápido e eficiente para armazenar pequenas quantidades de dados (como preferências do usuário ou configurações do aplicativo). +- Os dados salvos em **StoredState** persistem entre as sessões do aplicativo, permitindo que você restaure o estado da aplicação no lançamento. + +### Principais Características + +- **Armazenamento Persistente**: Os dados salvos em `StoredState` permanecem disponíveis entre os lançamentos do aplicativo. +- **Manuseio de Dados Pequenos**: Melhor usado para dados leves como preferências, alternâncias ou pequenas configurações. +- **Seguro para Threads**: `StoredState` garante que o acesso aos dados permaneça seguro em ambientes concorrentes. + +## Exemplo de Uso + +### Definindo um StoredState + +Você pode definir um **StoredState** estendendo o objeto `Application` e declarando a propriedade de estado: + +```swift +import AppState + +extension Application { + var userPreferences: StoredState { + storedState(initial: "Default Preferences", id: "userPreferences") + } +} +``` + +### Acessando e Modificando o StoredState em uma Visualização + +Você pode acessar e modificar os valores de **StoredState** dentro das visualizações SwiftUI usando o property wrapper `@StoredState`: + +```swift +import AppState +import SwiftUI + +struct PreferencesView: View { + @StoredState(\.userPreferences) var userPreferences: String + + var body: some View { + VStack { + Text("Preferências: \(userPreferences)") + Button("Atualizar Preferências") { + userPreferences = "Updated Preferences" + } + } + } +} +``` + +## Lidando com a Migração de Dados + +À medida que seu aplicativo evolui, você pode atualizar os modelos que são persistidos via **StoredState**. Ao atualizar seu modelo de dados, garanta a compatibilidade com versões anteriores. Por exemplo, você pode adicionar novos campos ou versionar seu modelo para lidar com a migração. + +Para mais informações, consulte o [Guia de Considerações sobre Migração](migration-considerations.md). + +### Considerações sobre Migração + +- **Adicionando Novos Campos Não Opcionais**: Certifique-se de que os novos campos sejam opcionais ou tenham valores padrão para manter a compatibilidade com versões anteriores. +- **Versionando Modelos**: Se o seu modelo de dados mudar ao longo do tempo, inclua um campo `version` para gerenciar diferentes versões dos seus dados persistidos. + +## Melhores Práticas + +- **Use para Dados Pequenos**: Armazene dados leves e não sensíveis que precisam persistir entre os lançamentos do aplicativo, como as preferências do usuário. +- **Considere Alternativas para Dados Maiores**: Se você precisar armazenar grandes quantidades de dados, considere usar **FileState** em vez disso. + +## Conclusão + +**StoredState** é uma maneira simples e eficiente de persistir pequenas porções de dados usando `UserDefaults`. É ideal para salvar preferências e outras pequenas configurações entre os lançamentos do aplicativo, ao mesmo tempo que fornece acesso seguro e fácil integração com o SwiftUI. Para necessidades de persistência mais complexas, explore outras funcionalidades do **AppState**, como [FileState](usage-filestate.md) ou [SyncState](usage-syncstate.md). + +--- +Esta tradução foi gerada automaticamente e pode conter erros. Se você é um falante nativo, agradecemos suas contribuições com correções por meio de um Pull Request. diff --git a/documentation/pt/usage-syncstate.md b/documentation/pt/usage-syncstate.md new file mode 100644 index 0000000..f5f8976 --- /dev/null +++ b/documentation/pt/usage-syncstate.md @@ -0,0 +1,159 @@ +# Uso do SyncState + +`SyncState` é um componente da biblioteca **AppState** que permite sincronizar o estado da aplicação em vários dispositivos usando o iCloud. Isso é especialmente útil para manter as preferências do usuário, configurações ou outros dados importantes consistentes em todos os dispositivos. + +## Visão Geral + +`SyncState` aproveita o `NSUbiquitousKeyValueStore` do iCloud para manter pequenas quantidades de dados sincronizadas em todos os dispositivos. Isso o torna ideal para sincronizar o estado leve da aplicação, como preferências ou configurações do usuário. + +### Principais Características + +- **Sincronização com o iCloud**: Sincroniza automaticamente o estado em todos os dispositivos conectados à mesma conta do iCloud. +- **Armazenamento Persistente**: Os dados são armazenados de forma persistente no iCloud, o que significa que eles persistirão mesmo que o aplicativo seja encerrado ou reiniciado. +- **Sincronização Quase em Tempo Real**: As alterações no estado são propagadas para outros dispositivos quase instantaneamente. + +> **Nota**: `SyncState` é suportado no watchOS 9.0 e posterior. + +## Exemplo de Uso + +### Modelo de Dados + +Suponha que temos uma estrutura chamada `Settings` que se conforma com `Codable`: + +```swift +struct Settings: Codable { + var text: String + var isShowingSheet: Bool + var isDarkMode: Bool +} +``` + +### Definindo um SyncState + +Você pode definir um `SyncState` estendendo o objeto `Application` e declarando as propriedades de estado que devem ser sincronizadas: + +```swift +extension Application { + var settings: SyncState { + syncState( + initial: Settings( + text: "Hello, World!", + isShowingSheet: false, + isDarkMode: false + ), + id: "settings" + ) + } +} +``` + +### Lidando com Alterações Externas + +Para garantir que o aplicativo responda a alterações externas do iCloud, substitua a função `didChangeExternally` criando uma subclasse personalizada de `Application`: + +```swift +class CustomApplication: Application { + override func didChangeExternally(notification: Notification) { + super.didChangeExternally(notification: notification) + + DispatchQueue.main.async { + self.objectWillChange.send() + } + } +} +``` + +### Criando Visualizações para Modificar e Sincronizar o Estado + +No exemplo a seguir, temos duas visualizações: `ContentView` e `ContentViewInnerView`. Essas visualizações compartilham e sincronizam o estado de `Settings` entre elas. `ContentView` permite que o usuário modifique o `text` e alterne `isDarkMode`, enquanto `ContentViewInnerView` exibe o mesmo texto e o atualiza quando tocado. + +```swift +struct ContentView: View { + @SyncState(\.settings) private var settings: Settings + + var body: some View { + VStack { + TextField("", text: $settings.text) + + Button(settings.isDarkMode ? "Light" : "Dark") { + settings.isDarkMode.toggle() + } + + Button("Show") { settings.isShowingSheet = true } + } + .preferredColorScheme(settings.isDarkMode ? .dark : .light) + .sheet(isPresented: $settings.isShowingSheet, content: ContentViewInnerView.init) + } +} + +struct ContentViewInnerView: View { + @Slice(\.settings, \.text) private var text: String + + var body: some View { + Text("\(text)") + .onTapGesture { + text = Date().formatted() + } + } +} +``` + +### Configurando o Aplicativo + +Finalmente, configure o aplicativo na estrutura `@main`. Na inicialização, promova o aplicativo personalizado, habilite o registro e carregue a dependência do armazenamento do iCloud para sincronização: + +```swift +@main +struct SyncStateExampleApp: App { + init() { + Application + .promote(to: CustomApplication.self) + .logging(isEnabled: true) + .load(dependency: \.icloudStore) + } + + var body: some Scene { + WindowGroup { + ContentView() + } + } +} +``` + +### Habilitando o Armazenamento de Chave-Valor do iCloud + +Para habilitar a sincronização do iCloud, certifique-se de seguir este guia para habilitar a capacidade de Armazenamento de Chave-Valor do iCloud: [Começando a usar o SyncState](starting-to-use-syncstate.md). + +### SyncState: Notas sobre o Armazenamento do iCloud + +Embora o `SyncState` permita uma sincronização fácil, é importante lembrar as limitações do `NSUbiquitousKeyValueStore`: + +- **Limite de Armazenamento**: Você pode armazenar até 1 MB de dados no iCloud usando o `NSUbiquitousKeyValueStore`, com um limite de tamanho de valor por chave de 1 MB. + +### Considerações sobre Migração + +Ao atualizar seu modelo de dados, é importante levar em conta os possíveis desafios de migração, especialmente ao trabalhar com dados persistentes usando **StoredState**, **FileState** ou **SyncState**. Sem o tratamento adequado da migração, alterações como adicionar novos campos ou modificar formatos de dados podem causar problemas ao carregar dados mais antigos. + +Aqui estão alguns pontos-chave a serem lembrados: +- **Adicionando Novos Campos Não Opcionais**: Certifique-se de que os novos campos sejam opcionais ou tenham valores padrão para manter a compatibilidade com versões anteriores. +- **Lidando com Alterações no Formato de Dados**: Se a estrutura do seu modelo mudar, implemente uma lógica de decodificação personalizada para suportar formatos antigos. +- **Versionando Seus Modelos**: Use um campo `version` em seus modelos para ajudar nas migrações e aplicar a lógica com base na versão dos dados. + +Para saber mais sobre como gerenciar migrações e evitar possíveis problemas, consulte o [Guia de Considerações sobre Migração](migration-considerations.md). + +## Guia de Implementação do SyncState + +Para obter instruções detalhadas sobre como configurar o iCloud e o SyncState em seu projeto, consulte o [Guia de Implementação do SyncState](syncstate-implementation.md). + +## Melhores Práticas + +- **Use para Dados Pequenos e Críticos**: `SyncState` é ideal para sincronizar pequenas e importantes peças de estado, como preferências do usuário, configurações ou sinalizadores de recursos. +- **Monitore o Armazenamento do iCloud**: Certifique-se de que seu uso do `SyncState` permaneça dentro dos limites de armazenamento do iCloud para evitar problemas de sincronização de dados. +- **Lide com Atualizações Externas**: Se seu aplicativo precisar responder a alterações de estado iniciadas em outro dispositivo, substitua a função `didChangeExternally` para atualizar o estado do aplicativo em tempo real. + +## Conclusão + +`SyncState` fornece uma maneira poderosa de sincronizar pequenas quantidades de estado da aplicação em todos os dispositivos via iCloud. É ideal para garantir que as preferências do usuário e outros dados importantes permaneçam consistentes em todos os dispositivos conectados à mesma conta do iCloud. Para casos de uso mais avançados, explore outras funcionalidades do **AppState**, como [SecureState](usage-securestate.md) e [FileState](usage-filestate.md). + +--- +Esta tradução foi gerada automaticamente e pode conter erros. Se você é um falante nativo, agradecemos suas contribuições com correções por meio de um Pull Request. diff --git a/documentation/ru/advanced-usage.md b/documentation/ru/advanced-usage.md new file mode 100644 index 0000000..4a8cb39 --- /dev/null +++ b/documentation/ru/advanced-usage.md @@ -0,0 +1,181 @@ +# Расширенное использование AppState + +Это руководство охватывает расширенные темы использования **AppState**, включая создание "точно в срок", предварительную загрузку зависимостей, эффективное управление состоянием и зависимостями, а также сравнение **AppState** с **окружением SwiftUI**. + +## 1. Создание "точно в срок" + +Значения AppState, такие как `State`, `Dependency`, `StoredState` и `SyncState`, создаются "точно в срок". Это означает, что они создаются только при первом доступе, что повышает эффективность и производительность вашего приложения. + +### Пример + +```swift +extension Application { + var defaultState: State { + state(initial: 0) // Значение не создается, пока к нему не обратятся + } +} +``` + +В этом примере `defaultState` не создается до тех пор, пока к нему не обратятся в первый раз, что оптимизирует использование ресурсов. + +## 2. Предварительная загрузка зависимостей + +В некоторых случаях вам может потребоваться предварительно загрузить определенные зависимости, чтобы убедиться, что они доступны при запуске вашего приложения. AppState предоставляет функцию `load`, которая предварительно загружает зависимости. + +### Пример + +```swift +extension Application { + var databaseClient: Dependency { + dependency(DatabaseClient()) + } +} + +// Предварительная загрузка при инициализации приложения +Application.load(dependency: \.databaseClient) +``` + +В этом примере `databaseClient` предварительно загружается во время инициализации приложения, что гарантирует его доступность при необходимости в ваших представлениях. + +## 3. Управление состоянием и зависимостями + +### 3.1 Общее состояние и зависимости в приложении + +Вы можете определить общее состояние или зависимости в одной части вашего приложения и получить к ним доступ в другой части, используя уникальные идентификаторы. + +### Пример + +```swift +private extension Application { + var stateValue: State { + state(initial: 0, id: "stateValue") + } + + var dependencyValue: Dependency { + dependency(SomeType(), id: "dependencyValue") + } +} +``` + +Это позволяет вам получить доступ к тому же `State` или `Dependency` в другом месте, используя тот же идентификатор. + +```swift +private extension Application { + var theSameStateValue: State { + state(initial: 0, id: "stateValue") + } + + var theSameDependencyValue: Dependency { + dependency(SomeType(), id: "dependencyValue") + } +} +``` + +Хотя этот подход является допустимым для совместного использования состояния и зависимостей в приложении путем повторного использования одного и того же строкового `id`, он, как правило, не рекомендуется. Он основан на ручном управлении этими строковыми идентификаторами, что может привести к: +- Случайным коллизиям идентификаторов, если один и тот же идентификатор используется для разных предполагаемых состояний/зависимостей. +- Трудности в отслеживании того, где определено состояние/зависимость, по сравнению с тем, где к нему осуществляется доступ. +- Снижению ясности и поддерживаемости кода. +`initial` значение, предоставленное в последующих определениях с тем же идентификатором, будет проигнорировано, если состояние/зависимость уже было инициализировано при первом доступе. Такое поведение является скорее побочным эффектом работы кэширования на основе идентификаторов в AppState, а не рекомендуемым основным шаблоном для определения общих данных. Предпочтительнее определять состояния и зависимости как уникальные вычисляемые свойства в расширениях `Application` (которые автоматически генерируют уникальные внутренние идентификаторы, если явный `id` не предоставлен фабричному методу). + +### 3.2 Ограниченный доступ к состоянию и зависимостям + +Чтобы ограничить доступ, используйте уникальный идентификатор, такой как UUID, чтобы гарантировать, что только нужные части приложения могут получить доступ к определенным состояниям или зависимостям. + +### Пример + +```swift +private extension Application { + var restrictedState: State { + state(initial: nil, id: UUID().uuidString) + } + + var restrictedDependency: Dependency { + dependency(SomeType(), id: UUID().uuidString) + } +} +``` + +### 3.3 Уникальные идентификаторы для состояний и зависимостей + +Когда идентификатор не предоставляется, AppState генерирует идентификатор по умолчанию на основе местоположения в исходном коде. Это гарантирует, что каждый `State` или `Dependency` является уникальным и защищен от непреднамеренного доступа. + +### Пример + +```swift +extension Application { + var defaultState: State { + state(initial: 0) // AppState генерирует уникальный идентификатор + } + + var defaultDependency: Dependency { + dependency(SomeType()) // AppState генерирует уникальный идентификатор + } +} +``` + +### 3.4 Доступ к состоянию и зависимостям на уровне файла + +Для еще более ограниченного доступа в пределах одного и того же файла Swift используйте уровень доступа `fileprivate`, чтобы защитить состояния и зависимости от внешнего доступа. + +### Пример + +```swift +fileprivate extension Application { + var fileprivateState: State { + state(initial: 0) + } + + var fileprivateDependency: Dependency { + dependency(SomeType()) + } +} +``` + +### 3.5 Понимание механизма хранения AppState + +AppState использует единый кэш для хранения `State`, `Dependency`, `StoredState` и `SyncState`. Это обеспечивает эффективное управление этими типами данных в вашем приложении. + +По умолчанию AppState присваивает значение имени "App", что гарантирует, что все значения, связанные с модулем, привязаны к этому имени. Это усложняет доступ к этим состояниям и зависимостям из других модулей. + +## 4. AppState по сравнению с окружением SwiftUI + +AppState и окружение SwiftUI оба предлагают способы управления общим состоянием и зависимостями в вашем приложении, но они различаются по области применения, функциональности и вариантам использования. + +### 4.1 Окружение SwiftUI + +Окружение SwiftUI - это встроенный механизм, который позволяет передавать общие данные вниз по иерархии представлений. Он идеально подходит для передачи данных, к которым нужен доступ многим представлениям, но у него есть ограничения, когда речь заходит о более сложном управлении состоянием. + +**Преимущества:** +- Простота в использовании и хорошая интеграция с SwiftUI. +- Идеально подходит для легковесных данных, которые необходимо совместно использовать в нескольких представлениях в иерархии. + +**Ограничения:** +- Данные доступны только в пределах определенной иерархии представлений. Доступ к тем же данным в разных иерархиях представлений невозможен без дополнительной работы. +- Меньший контроль над поточно-безопасностью и персистентностью по сравнению с AppState. +- Отсутствие встроенных механизмов персистентности или синхронизации. + +### 4.2 AppState + +AppState предоставляет более мощную и гибкую систему для управления состоянием во всем приложении с возможностями поточно-безопасности, персистентности и внедрения зависимостей. + +**Преимущества:** +- Централизованное управление состоянием, доступное во всем приложении, а не только в определенных иерархиях представлений. +- Встроенные механизмы персистентности (`StoredState`, `FileState` и `SyncState`). +- Гарантии типобезопасности и поточно-безопасности, обеспечивающие правильный доступ и изменение состояния. +- Может обрабатывать более сложное управление состоянием и зависимостями. + +**Ограничения:** +- Требует больше настроек и конфигурации по сравнению с окружением SwiftUI. +- Несколько менее интегрирован с SwiftUI по сравнению с Environment, хотя все еще хорошо работает в приложениях SwiftUI. + +### 4.3 Когда что использовать + +- Используйте **окружение SwiftUI**, когда у вас есть простые данные, которые необходимо совместно использовать в иерархии представлений, например, настройки пользователя или предпочтения темы. +- Используйте **AppState**, когда вам необходимо централизованное управление состоянием, персистентность или более сложное состояние, к которому необходимо получить доступ во всем приложении. + +## Заключение + +Используя эти расширенные методы, такие как создание "точно в срок", предварительная загрузка, управление состоянием и зависимостями, а также понимание различий между AppState и окружением SwiftUI, вы можете создавать эффективные и ресурсосберегающие приложения с помощью **AppState**. + +--- +Этот перевод был сгенерирован автоматически и может содержать ошибки. Если вы носитель языка, мы будем признательны за ваши исправления через Pull Request. diff --git a/documentation/ru/best-practices.md b/documentation/ru/best-practices.md new file mode 100644 index 0000000..39896c4 --- /dev/null +++ b/documentation/ru/best-practices.md @@ -0,0 +1,65 @@ +# Лучшие практики использования AppState + +Это руководство предоставляет лучшие практики, которые помогут вам эффективно и результативно использовать AppState в ваших приложениях Swift. + +## 1. Используйте AppState экономно + +AppState универсален и подходит как для управления общим, так и для локализованного состояния. Он идеально подходит для данных, которые необходимо совместно использовать в нескольких компонентах, сохранять между представлениями или сеансами пользователя, или управлять на уровне компонента. Однако чрезмерное использование может привести к ненужной сложности. + +### Рекомендация: +- Используйте AppState для данных, которые действительно должны быть доступны в масштабе всего приложения, совместно использоваться удаленными компонентами или требовать специфических функций персистентности/синхронизации AppState. +- Для состояния, которое является локальным для одного представления SwiftUI или близкой иерархии представлений, предпочитайте встроенные инструменты SwiftUI, такие как `@State`, `@StateObject`, `@ObservedObject` или `@EnvironmentObject`. + +## 2. Поддерживайте чистоту AppState + +По мере расширения вашего приложения ваш AppState может усложняться. Регулярно просматривайте и рефакторите ваш AppState, чтобы удалять неиспользуемые состояния и зависимости. Поддержание чистоты вашего AppState упрощает его понимание, обслуживание и тестирование. + +### Рекомендация: +- Периодически проверяйте ваш AppState на наличие неиспользуемых или избыточных состояний и зависимостей. +- Рефакторите большие структуры AppState, чтобы они оставались чистыми и управляемыми. + +## 3. Тестируйте ваш AppState + +Как и другие аспекты вашего приложения, убедитесь, что ваш AppState тщательно протестирован. Используйте макеты зависимостей, чтобы изолировать ваш AppState от внешних зависимостей во время тестирования, и убедитесь, что каждая часть вашего приложения ведет себя так, как ожидалось. + +### Рекомендация: +- Используйте XCTest или аналогичные фреймворки для тестирования поведения и взаимодействий AppState. +- Используйте макеты или заглушки для зависимостей, чтобы обеспечить изоляцию и надежность тестов AppState. + +## 4. Используйте функцию Slice с умом + +Функция `Slice` позволяет вам получать доступ к определенным частям состояния AppState, что полезно для обработки больших и сложных структур состояния. Однако используйте эту функцию с умом, чтобы поддерживать чистый и хорошо организованный AppState, избегая ненужных срезов, которые фрагментируют управление состоянием. + +### Рекомендация: +- Используйте `Slice` только для больших или вложенных состояний, где необходим доступ к отдельным компонентам. +- Избегайте чрезмерного нарезания состояния, что может привести к путанице и фрагментированному управлению состоянием. + +## 5. Используйте константы для статических значений + +Функция `@Constant` позволяет определять константы только для чтения, которые могут быть совместно использованы в вашем приложении. Она полезна для значений, которые остаются неизменными на протяжении всего жизненного цикла вашего приложения, таких как настройки конфигурации или предопределенные данные. Константы гарантируют, что эти значения не будут изменены непреднамеренно. + +### Рекомендация: +- Используйте `@Constant` для значений, которые остаются неизменными, таких как конфигурации приложения, переменные среды или статические ссылки. + +## 6. Модуляризируйте ваш AppState + +Для больших приложений рассмотрите возможность разделения вашего AppState на более мелкие, более управляемые модули. Каждый модуль может иметь свое собственное состояние и зависимости, которые затем объединяются в общий AppState. Это может сделать ваш AppState более понятным, тестируемым и обслуживаемым. + +### Рекомендация: +- Организуйте ваши расширения `Application` в отдельные файлы Swift или даже в отдельные модули Swift, сгруппированные по функциям или доменам. Это естественным образом модуляризирует определения. +- При определении состояний или зависимостей с помощью фабричных методов, таких как `state(initial:feature:id:)`, используйте параметр `feature` для предоставления пространства имен, например, `state(initial: 0, feature: "UserProfile", id: "score")`. Это помогает в организации и предотвращении коллизий идентификаторов при использовании ручных идентификаторов. +- Избегайте создания нескольких экземпляров `Application`. Придерживайтесь расширения и использования общего синглтона (`Application.shared`). + +## 7. Используйте создание "точно в срок" + +Значения AppState создаются "точно в срок", что означает, что они создаются только при доступе к ним. Это оптимизирует использование памяти и гарантирует, что значения AppState создаются только при необходимости. + +### Рекомендация: +- Позволяйте значениям AppState создаваться "точно в срок", а не предварительно загружать все состояния и зависимости без необходимости. + +## Заключение + +Каждое приложение уникально, поэтому эти лучшие практики могут не подойти для каждой ситуации. Всегда учитывайте конкретные требования вашего приложения при принятии решения о том, как использовать AppState, и стремитесь поддерживать управление состоянием чистым, эффективным и хорошо протестированным. + +--- +Этот перевод был сгенерирован автоматически и может содержать ошибки. Если вы носитель языка, мы будем признательны за ваши исправления через Pull Request. diff --git a/documentation/ru/contributing.md b/documentation/ru/contributing.md new file mode 100644 index 0000000..880b394 --- /dev/null +++ b/documentation/ru/contributing.md @@ -0,0 +1,63 @@ +# Вклад в AppState + +Спасибо за то, что рассматриваете возможность внести свой вклад в **AppState**! Ваши вклады помогают сделать этот проект лучше для всех. + +## Как внести вклад + +### 1. Сообщение об ошибках + +Если вы столкнулись с какими-либо ошибками, пожалуйста, откройте issue на GitHub. При сообщении об ошибке, пожалуйста, включите: + +- Четкий и описательный заголовок. +- Подробное описание ошибки, включая шаги для ее воспроизведения. +- Ожидаемое поведение и то, что произошло на самом деле. +- Версия **AppState**, которую вы используете. +- Любые соответствующие скриншоты или журналы. + +### 2. Предложение функций + +Новые идеи приветствуются! Если у вас есть функция, которую вы хотели бы видеть добавленной в **AppState**, пожалуйста, откройте issue и опишите: + +- Проблему, которую решит эта функция. +- Как, по вашему мнению, должна работать эта функция. +- Любой дополнительный контекст или примеры, которые помогут проиллюстрировать вашу идею. + +### 3. Отправка Pull-запросов + +Если вы хотите внести свой вклад в код **AppState**, выполните следующие действия: + +1. **Сделайте форк репозитория**: Создайте личный форк репозитория **AppState** на GitHub. +2. **Клонируйте свой форк**: Клонируйте свой форк на свой локальный компьютер: + ```bash + git clone https://github.com/your-username/AppState.git + ``` +3. **Создайте новую ветку**: Создайте новую ветку для вашей функции или исправления ошибки: + ```bash + git checkout -b my-feature-branch + ``` +4. **Внесите изменения**: Реализуйте свои изменения в новой ветке. +5. **Протестируйте свои изменения**: Убедитесь, что ваши изменения проходят все тесты. При необходимости добавьте новые тесты. +6. **Закоммитьте свои изменения**: Закоммитьте свои изменения с описательным сообщением коммита: + ```bash + git commit -m "Add my new feature" + ``` +7. **Отправьте на GitHub**: Отправьте свою ветку в свой форк на GitHub: + ```bash + git push origin my-feature-branch + ``` +8. **Создайте Pull-запрос**: Перейдите в репозиторий **AppState** на GitHub и создайте pull-запрос из вашей ветки. + +### 4. Стиль кода + +Пожалуйста, следуйте рекомендациям по стилю кодирования, используемым в проекте **AppState**. Последовательный стиль кода помогает сделать кодовую базу более удобной для сопровождения и просмотра. + +### 5. Лицензия + +Внося вклад в **AppState**, вы соглашаетесь с тем, что ваши вклады будут лицензироваться по той же лицензии, что и проект: [ЛИЦЕНЗИЯ](https://github.com/0xLeif/AppState/blob/main/LICENSE). + +## Спасибо! + +Ваши вклады очень ценны и высоко ценятся. Спасибо за помощь в улучшении **AppState**! + +--- +Этот перевод был сгенерирован автоматически и может содержать ошибки. Если вы носитель языка, мы будем признательны за ваши исправления через Pull Request. diff --git a/documentation/ru/faq.md b/documentation/ru/faq.md new file mode 100644 index 0000000..0323984 --- /dev/null +++ b/documentation/ru/faq.md @@ -0,0 +1,43 @@ +# Часто задаваемые вопросы + +Этот краткий FAQ отвечает на распространенные вопросы, которые могут возникнуть у разработчиков при использовании **AppState**. + +## Как сбросить значение состояния? + +Для постоянных состояний, таких как `StoredState`, `FileState` и `SyncState`, вы можете сбросить их до начальных значений, используя статические функции `reset` для типа `Application`. + +Например, чтобы сбросить `StoredState`: +```swift +extension Application { + var hasCompletedOnboarding: StoredState { storedState(initial: false, id: "onboarding_complete") } +} + +// Где-то в вашем коде +Application.reset(storedState: \.hasCompletedOnboarding) +``` +Это сбросит значение в `UserDefaults` обратно на `false`. Аналогичные функции `reset` существуют для `FileState`, `SyncState` и `SecureState`. + +Для непостоянного `State` вы можете сбросить его так же, как и постоянные состояния: +```swift +extension Application { + var counter: State { state(initial: 0) } +} + +// Где-то в вашем коде +Application.reset(\.counter) +``` + +## Могу ли я использовать AppState с асинхронными задачами? + +Да. Значения `State` и зависимостей являются поточно-безопасными и без проблем работают с Swift Concurrency. Вы можете получать к ним доступ и изменять их внутри функций `async` без дополнительной блокировки. + +## Где мне следует определять состояния и зависимости? + +Храните все свои состояния и зависимости в расширениях `Application`. Это обеспечивает единый источник истины и упрощает обнаружение всех доступных значений. + +## Совместим ли AppState с Combine? + +Вы можете использовать AppState вместе с Combine, связывая изменения `State` с издателями. Наблюдайте за значением `State` и при необходимости отправляйте обновления через `PassthroughSubject` или другой издатель Combine. + +--- +Этот перевод был сгенерирован автоматически и может содержать ошибки. Если вы носитель языка, мы будем признательны за ваши исправления через Pull Request. diff --git a/documentation/ru/installation.md b/documentation/ru/installation.md new file mode 100644 index 0000000..c104261 --- /dev/null +++ b/documentation/ru/installation.md @@ -0,0 +1,87 @@ +# Руководство по установке + +Это руководство проведет вас через процесс установки **AppState** в ваш проект Swift с помощью Swift Package Manager. + +## Swift Package Manager + +**AppState** можно легко интегрировать в ваш проект с помощью Swift Package Manager. Следуйте приведенным ниже шагам, чтобы добавить **AppState** в качестве зависимости. + +### Шаг 1: Обновите ваш файл `Package.swift` + +Добавьте **AppState** в раздел `dependencies` вашего файла `Package.swift`: + +```swift +dependencies: [ + .package(url: "https://github.com/0xLeif/AppState.git", from: "2.2.0") +] +``` + +### Шаг 2: Добавьте AppState в вашу цель + +Включите AppState в зависимости вашей цели: + +```swift +.target( + name: "YourTarget", + dependencies: ["AppState"] +) +``` + +### Шаг 3: Соберите ваш проект + +После того, как вы добавили AppState в ваш файл `Package.swift`, соберите ваш проект, чтобы получить зависимость и интегрировать ее в вашу кодовую базу. + +``` +swift build +``` + +### Шаг 4: Импортируйте AppState в ваш код + +Теперь вы можете начать использовать AppState в вашем проекте, импортировав его в верхней части ваших файлов Swift: + +```swift +import AppState +``` + +## Xcode + +Если вы предпочитаете добавлять **AppState** напрямую через Xcode, выполните следующие действия: + +### Шаг 1: Откройте ваш проект Xcode + +Откройте ваш проект или рабочее пространство Xcode. + +### Шаг 2: Добавьте зависимость Swift Package + +1. Перейдите в навигатор проекта и выберите файл вашего проекта. +2. В редакторе проекта выберите вашу цель, а затем перейдите на вкладку «Swift Packages». +3. Нажмите кнопку «+», чтобы добавить зависимость пакета. + +### Шаг 3: Введите URL-адрес репозитория + +В диалоговом окне «Выбрать репозиторий пакетов» введите следующий URL-адрес: `https://github.com/0xLeif/AppState.git` + +Затем нажмите «Далее». + +### Шаг 4: Укажите версию + +Выберите версию, которую вы хотите использовать. Рекомендуется выбрать опцию «До следующей основной версии» и указать `2.0.0` в качестве нижней границы. Затем нажмите «Далее». + +### Шаг 5: Добавьте пакет + +Xcode получит пакет и предоставит вам варианты добавления **AppState** в вашу цель. Убедитесь, что вы выбрали правильную цель, и нажмите «Готово». + +### Шаг 6: Импортируйте `AppState` в ваш код + +Теперь вы можете импортировать **AppState** в верхней части ваших файлов Swift: + +```swift +import AppState +``` + +## Следующие шаги + +После установки AppState вы можете перейти к [Обзору использования](usage-overview.md), чтобы увидеть, как реализовать ключевые функции в вашем проекте. + +--- +Этот перевод был сгенерирован автоматически и может содержать ошибки. Если вы носитель языка, мы будем признательны за ваши исправления через Pull Request. diff --git a/documentation/ru/migration-considerations.md b/documentation/ru/migration-considerations.md new file mode 100644 index 0000000..7bc1539 --- /dev/null +++ b/documentation/ru/migration-considerations.md @@ -0,0 +1,81 @@ +# Вопросы миграции + +При обновлении вашей модели данных, особенно для сохраненных или синхронизированных данных, вам необходимо обеспечить обратную совместимость, чтобы избежать потенциальных проблем при загрузке старых данных. Вот несколько важных моментов, которые следует учитывать: + +## 1. Добавление необязательных полей +Если вы добавляете в свою модель новые необязательные поля, декодирование старых данных (которые не будут содержать эти поля) может завершиться неудачей. Чтобы избежать этого: +- Рассмотрите возможность присвоения новым полям значений по умолчанию. +- Сделайте новые поля необязательными, чтобы обеспечить совместимость со старыми версиями вашего приложения. + +### Пример: +```swift +struct Settings: Codable { + var text: String + var isDarkMode: Bool + var newField: String? // Новое поле является необязательным +} +``` + +## 2. Изменения формата данных +Если вы изменяете структуру модели (например, меняете тип с `Int` на `String`), процесс декодирования может завершиться неудачей при чтении старых данных. Спланируйте плавную миграцию: +- Создав логику миграции для преобразования старых форматов данных в новую структуру. +- Используя настраиваемый инициализатор `Decodable` для обработки старых данных и их сопоставления с вашей новой моделью. + +### Пример: +```swift +struct Settings: Codable { + var text: String + var isDarkMode: Bool + var version: Int + + // Пользовательская логика декодирования для старых версий + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.text = try container.decode(String.self, forKey: .text) + self.isDarkMode = try container.decode(Bool.self, forKey: .isDarkMode) + self.version = (try? container.decode(Int.self, forKey: .version)) ?? 1 // Значение по умолчанию для старых данных + } +} +``` + +## 3. Обработка удаленных или устаревших полей +Если вы удаляете поле из модели, убедитесь, что старые версии приложения все еще могут декодировать новые данные без сбоев. Вы можете: +- Игнорировать лишние поля при декодировании. +- Использовать настраиваемые декодеры для обработки старых данных и правильного управления устаревшими полями. + +## 4. Версионирование ваших моделей + +Версионирование ваших моделей позволяет вам управлять изменениями в вашей структуре данных с течением времени. Сохраняя номер версии как часть вашей модели, вы можете легко реализовать логику миграции для преобразования старых форматов данных в новые. Такой подход гарантирует, что ваше приложение сможет обрабатывать старые структуры данных, плавно переходя на новые версии. + +- **Почему версионирование важно**: когда пользователи обновляют свое приложение, у них все еще могут быть сохраненные на устройствах старые данные. Версионирование помогает вашему приложению распознавать формат данных и применять правильную логику миграции. +- **Как использовать**: добавьте поле `version` в свою модель и проверяйте его во время процесса декодирования, чтобы определить, требуется ли миграция. + +### Пример: +```swift +struct Settings: Codable { + var version: Int + var text: String + var isDarkMode: Bool + + // Обработка логики декодирования для конкретной версии + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.version = try container.decode(Int.self, forKey: .version) + self.text = try container.decode(String.self, forKey: .text) + self.isDarkMode = try container.decode(Bool.self, forKey: .isDarkMode) + + // При миграции со старой версии примените необходимые преобразования здесь + if version < 2 { + // Миграция старых данных в новый формат + } + } +} +``` + +- **Лучшая практика**: начинайте с поля `version` с самого начала. Каждый раз, когда вы обновляете структуру своей модели, увеличивайте версию и обрабатывайте необходимую логику миграции. + +## 5. Тестирование миграции +Всегда тщательно тестируйте свою миграцию, имитируя загрузку старых данных с новыми версиями вашей модели, чтобы убедиться, что ваше приложение ведет себя так, как ожидалось. + +--- +Этот перевод был сгенерирован автоматически и может содержать ошибки. Если вы носитель языка, мы будем признательны за ваши исправления через Pull Request. diff --git a/documentation/ru/starting-to-use-syncstate.md b/documentation/ru/starting-to-use-syncstate.md new file mode 100644 index 0000000..63c0360 --- /dev/null +++ b/documentation/ru/starting-to-use-syncstate.md @@ -0,0 +1,27 @@ +# Начало работы с SyncState + +Чтобы использовать SyncState, вам сначала необходимо настроить возможности и права iCloud в вашем проекте Xcode. Вот введение, которое проведет вас через этот процесс: + +### Настройка возможностей iCloud: + +1. Откройте свой проект Xcode и измените идентификаторы пакетов для целей macOS и iOS, чтобы они соответствовали вашим собственным. +2. Затем вам нужно добавить возможность iCloud в свой проект. Для этого выберите свой проект в навигаторе проектов, затем выберите свою цель. На панели вкладок в верхней части области редактора нажмите «Signing & Capabilities». +3. На панели «Возможности» включите iCloud, щелкнув переключатель в строке iCloud. Вы должны увидеть, как переключатель переместится в положение «Вкл.». +4. После включения iCloud вам необходимо включить хранилище «ключ-значение». Вы можете сделать это, установив флажок «Хранилище ключ-значение». + +### Обновление прав: + +1. Теперь вам нужно будет обновить файл прав. Откройте файл прав для вашей цели. +2. Убедитесь, что значение хранилища ключ-значение iCloud совпадает с вашим уникальным идентификатором хранилища ключ-значение. Ваш уникальный идентификатор должен соответствовать формату `$(TeamIdentifierPrefix)`. Значение по умолчанию должно быть примерно таким: `$(TeamIdentifierPrefix)$(CFBundleIdentifier)`. Это подходит для приложений для одной платформы, но если ваше приложение работает на нескольких ОС Apple, важно, чтобы части идентификатора хранилища ключ-значение были одинаковыми для обеих целей. + +### Настройка устройств: + +Помимо настройки самого проекта, вам также необходимо подготовить устройства, на которых будет работать проект. + +- Убедитесь, что iCloud Drive включен как на устройствах iOS, так и на macOS. +- Войдите на оба устройства, используя одну и ту же учетную запись iCloud. + +Если у вас есть какие-либо вопросы или вы столкнулись с какими-либо проблемами, не стесняйтесь обращаться к нам или отправлять отчет о проблеме. + +--- +Этот перевод был сгенерирован автоматически и может содержать ошибки. Если вы носитель языка, мы будем признательны за ваши исправления через Pull Request. diff --git a/documentation/ru/syncstate-implementation.md b/documentation/ru/syncstate-implementation.md new file mode 100644 index 0000000..9ed399d --- /dev/null +++ b/documentation/ru/syncstate-implementation.md @@ -0,0 +1,84 @@ +# Реализация SyncState в AppState + +Это руководство описывает, как настроить и сконфигурировать SyncState в вашем приложении, включая настройку возможностей iCloud и понимание потенциальных ограничений. + +## 1. Настройка возможностей iCloud + +Чтобы использовать SyncState в вашем приложении, вам сначала нужно включить iCloud в вашем проекте и настроить хранилище ключ-значение. + +### Шаги для включения iCloud и хранилища ключ-значение: + +1. Откройте ваш проект Xcode и перейдите в настройки вашего проекта. +2. На вкладке «Signing & Capabilities» выберите вашу цель (iOS или macOS). +3. Нажмите кнопку «+ Capability» и выберите «iCloud» из списка. +4. Включите опцию «Key-Value storage» в настройках iCloud. Это позволит вашему приложению хранить и синхронизировать небольшие объемы данных с помощью iCloud. + +### Конфигурация файла прав: + +1. В вашем проекте Xcode найдите или создайте **файл прав** для вашего приложения. +2. Убедитесь, что хранилище ключ-значение iCloud правильно настроено в файле прав с правильным контейнером iCloud. + +Пример в файле прав: + +```xml +com.apple.developer.ubiquity-kvstore-identifier +$(TeamIdentifierPrefix)com.yourdomain.app +``` + +Убедитесь, что значение строки соответствует контейнеру iCloud, связанному с вашим проектом. + +## 2. Использование SyncState в вашем приложении + +После включения iCloud вы можете использовать `SyncState` в вашем приложении для синхронизации данных между устройствами. + +### Пример использования SyncState: + +```swift +import AppState +import SwiftUI + +extension Application { + var syncValue: SyncState { + syncState(id: "syncValue") + } +} + +struct ContentView: View { + @SyncState(\.syncValue) private var syncValue: Int? + + var body: some View { + VStack { + if let syncValue = syncValue { + Text("SyncValue: \(syncValue)") + } else { + Text("No SyncValue") + } + + Button("Update SyncValue") { + syncValue = Int.random(in: 0..<100) + } + } + } +} +``` + +В этом примере состояние синхронизации будет сохранено в iCloud и синхронизировано на всех устройствах, вошедших в ту же учетную запись iCloud. + +## 3. Ограничения и лучшие практики + +SyncState использует `NSUbiquitousKeyValueStore`, у которого есть некоторые ограничения: + +- **Ограничение хранилища**: SyncState предназначен для небольших объемов данных. Общий лимит хранилища составляет 1 МБ, а каждая пара ключ-значение ограничена примерно 1 МБ. +- **Синхронизация**: изменения, внесенные в SyncState, не синхронизируются мгновенно между устройствами. Может быть небольшая задержка в синхронизации, и синхронизация iCloud иногда может зависеть от условий сети. + +### Лучшие практики: + +- **Используйте SyncState для небольших данных**: убедитесь, что с помощью SyncState синхронизируются только небольшие данные, такие как пользовательские предпочтения или настройки. +- **Изящно обрабатывайте сбои SyncState**: используйте значения по умолчанию или механизмы обработки ошибок для учета потенциальных задержек или сбоев синхронизации. + +## 4. Заключение + +Правильно настроив iCloud и понимая ограничения SyncState, вы можете использовать его возможности для синхронизации данных между устройствами. Убедитесь, что вы используете SyncState только для небольших, критически важных фрагментов данных, чтобы избежать потенциальных проблем с ограничениями хранилища iCloud. + +--- +Этот перевод был сгенерирован автоматически и может содержать ошибки. Если вы носитель языка, мы будем признательны за ваши исправления через Pull Request. diff --git a/documentation/ru/usage-constant.md b/documentation/ru/usage-constant.md new file mode 100644 index 0000000..28b8c23 --- /dev/null +++ b/documentation/ru/usage-constant.md @@ -0,0 +1,87 @@ +# Использование констант + +`Constant` в библиотеке **AppState** предоставляет доступ только для чтения к значениям в состоянии вашего приложения. Он работает аналогично `Slice`, но гарантирует, что доступные значения являются неизменяемыми. Это делает `Constant` идеальным для доступа к значениям, которые в противном случае могли бы быть изменяемыми, но должны оставаться только для чтения в определенных контекстах. + +## Ключевые особенности + +- **Доступ только для чтения**: константы предоставляют доступ к изменяемому состоянию, но значения не могут быть изменены. +- **Ограничено приложением**: как и `Slice`, `Constant` определяется в расширении `Application` и ограничен доступом к определенным частям состояния. +- **Потокобезопасность**: `Constant` обеспечивает безопасный доступ к состоянию в многопоточных средах. + +## Пример использования + +### Определение константы в приложении + +Вот как вы определяете `Constant` в расширении `Application` для доступа к значению только для чтения: + +```swift +import AppState +import SwiftUI + +struct ExampleValue { + var username: String? + var isLoading: Bool + let value: String + var mutableValue: String +} + +extension Application { + var exampleValue: State { + state( + initial: ExampleValue( + username: "Leif", + isLoading: false, + value: "value", + mutableValue: "" + ) + ) + } +} +``` + +### Доступ к константе в представлении SwiftUI + +В представлении SwiftUI вы можете использовать обертку свойства `@Constant` для доступа к постоянному состоянию только для чтения: + +```swift +import AppState +import SwiftUI + +struct ExampleView: View { + @Constant(\.exampleValue, \.value) var constantValue: String + + var body: some View { + Text("Постоянное значение: \(constantValue)") + } +} +``` + +### Доступ только для чтения к изменяемому состоянию + +Даже если значение изменяемо в другом месте, при доступе через `@Constant` значение становится неизменяемым: + +```swift +import AppState +import SwiftUI + +struct ExampleView: View { + @Constant(\.exampleValue, \.mutableValue) var constantMutableValue: String + + var body: some View { + Text("Изменяемое значение только для чтения: \(constantMutableValue)") + } +} +``` + +## Лучшие практики + +- **Используйте для доступа только для чтения**: используйте `Constant` для доступа к частям состояния, которые не должны изменяться в определенных контекстах, даже если они изменяемы в другом месте. +- **Потокобезопасность**: как и другие компоненты AppState, `Constant` обеспечивает потокобезопасный доступ к состоянию. +- **Используйте `OptionalConstant` для необязательных значений**: если часть состояния, к которой вы обращаетесь, может быть `nil`, используйте `OptionalConstant` для безопасной обработки отсутствия значения. + +## Заключение + +`Constant` и `OptionalConstant` предоставляют эффективный способ доступа к определенным частям состояния вашего приложения только для чтения. Они гарантируют, что значения, которые в противном случае могли бы быть изменяемыми, рассматриваются как неизменяемые при доступе к ним в представлении, обеспечивая безопасность и ясность в вашем коде. + +--- +Этот перевод был сгенерирован автоматически и может содержать ошибки. Если вы носитель языка, мы будем признательны за ваши исправления через Pull Request. diff --git a/documentation/ru/usage-filestate.md b/documentation/ru/usage-filestate.md new file mode 100644 index 0000000..a51505a --- /dev/null +++ b/documentation/ru/usage-filestate.md @@ -0,0 +1,96 @@ +# Использование FileState + +`FileState` — это компонент библиотеки **AppState**, который позволяет хранить и извлекать постоянные данные с помощью файловой системы. Он полезен для хранения больших данных или сложных объектов, которые необходимо сохранять между запусками приложения и восстанавливать при необходимости. + +## Ключевые особенности + +- **Постоянное хранилище**: данные, хранящиеся с помощью `FileState`, сохраняются между запусками приложения. +- **Обработка больших данных**: в отличие от `StoredState`, `FileState` идеально подходит для обработки больших или более сложных данных. +- **Потокобезопасность**: как и другие компоненты AppState, `FileState` обеспечивает безопасный доступ к данным в многопоточных средах. + +## Пример использования + +### Хранение и извлечение данных с помощью FileState + +Вот как определить `FileState` в расширении `Application` для хранения и извлечения большого объекта: + +```swift +import AppState +import SwiftUI + +struct UserProfile: Codable { + var name: String + var age: Int +} + +extension Application { + @MainActor + var userProfile: FileState { + fileState(initial: UserProfile(name: "Guest", age: 25), filename: "userProfile") + } +} + +struct FileStateExampleView: View { + @FileState(\.userProfile) var userProfile: UserProfile + + var body: some View { + VStack { + Text("Имя: \(userProfile.name), Возраст: \(userProfile.age)") + Button("Обновить профиль") { + userProfile = UserProfile(name: "UpdatedName", age: 30) + } + } + } +} +``` + +### Обработка больших данных с помощью FileState + +Когда вам нужно обрабатывать большие наборы данных или объекты, `FileState` обеспечивает эффективное хранение данных в файловой системе приложения. Это полезно для таких сценариев, как кэширование или автономное хранилище. + +```swift +import AppState +import SwiftUI + +extension Application { + @MainActor + var largeDataset: FileState<[String]> { + fileState(initial: [], filename: "largeDataset") + } +} + +struct LargeDataView: View { + @FileState(\.largeDataset) var largeDataset: [String] + + var body: some View { + List(largeDataset, id: \.self) { item in + Text(item) + } + } +} +``` + +### Вопросы миграции + +При обновлении вашей модели данных важно учитывать потенциальные проблемы миграции, особенно при работе с постоянными данными с использованием **StoredState**, **FileState** или **SyncState**. Без надлежащей обработки миграции такие изменения, как добавление новых полей или изменение форматов данных, могут вызвать проблемы при загрузке старых данных. + +Вот несколько ключевых моментов, которые следует учитывать: +- **Добавление новых необязательных полей**: убедитесь, что новые поля являются необязательными или имеют значения по умолчанию для поддержания обратной совместимости. +- **Обработка изменений формата данных**: если структура вашей модели изменяется, реализуйте настраиваемую логику декодирования для поддержки старых форматов. +- **Версионирование ваших моделей**: используйте поле `version` в ваших моделях, чтобы помочь с миграцией и применить логику на основе версии данных. + +Чтобы узнать больше о том, как управлять миграцией и избегать потенциальных проблем, обратитесь к [Руководству по вопросам миграции](migration-considerations.md). + + +## Лучшие практики + +- **Используйте для больших или сложных данных**: если вы храните большие данные или сложные объекты, `FileState` предпочтительнее, чем `StoredState`. +- **Потокобезопасный доступ**: как и другие компоненты **AppState**, `FileState` обеспечивает безопасный доступ к данным, даже когда несколько задач взаимодействуют с хранимыми данными. +- **Сочетайте с Codable**: при работе с пользовательскими типами данных убедитесь, что они соответствуют `Codable`, чтобы упростить кодирование и декодирование в файловую систему и из нее. + +## Заключение + +`FileState` — это мощный инструмент для работы с постоянными данными в вашем приложении, позволяющий хранить и извлекать большие или более сложные объекты потокобезопасным и постоянным образом. Он без проблем работает с протоколом `Codable` Swift, гарантируя, что ваши данные могут быть легко сериализованы и десериализованы для долгосрочного хранения. + +--- +Этот перевод был сгенерирован автоматически и может содержать ошибки. Если вы носитель языка, мы будем признательны за ваши исправления через Pull Request. diff --git a/documentation/ru/usage-observeddependency.md b/documentation/ru/usage-observeddependency.md new file mode 100644 index 0000000..9a5f313 --- /dev/null +++ b/documentation/ru/usage-observeddependency.md @@ -0,0 +1,135 @@ +# Использование ObservedDependency + +`ObservedDependency` — это компонент библиотеки **AppState**, который позволяет использовать зависимости, соответствующие протоколу `ObservableObject`. Это полезно, когда вы хотите, чтобы зависимость уведомляла ваши представления SwiftUI об изменениях, делая их реактивными и динамичными. + +## Ключевые особенности + +- **Наблюдаемые зависимости**: используйте зависимости, соответствующие протоколу `ObservableObject`, что позволяет зависимости автоматически обновлять ваши представления при изменении ее состояния. +- **Реактивные обновления пользовательского интерфейса**: представления SwiftUI автоматически обновляются при публикации изменений наблюдаемой зависимостью. +- **Потокобезопасность**: как и другие компоненты AppState, `ObservedDependency` обеспечивает потокобезопасный доступ к наблюдаемой зависимости. + +## Пример использования + +### Определение наблюдаемой зависимости + +Вот как определить наблюдаемую службу как зависимость в расширении `Application`: + +```swift +import AppState +import SwiftUI + +@MainActor +class ObservableService: ObservableObject { + @Published var count: Int = 0 +} + +extension Application { + @MainActor + var observableService: Dependency { + dependency(ObservableService()) + } +} +``` + +### Использование наблюдаемой зависимости в представлении SwiftUI + +В вашем представлении SwiftUI вы можете получить доступ к наблюдаемой зависимости с помощью обертки свойства `@ObservedDependency`. Наблюдаемый объект автоматически обновляет представление при каждом изменении его состояния. + +```swift +import AppState +import SwiftUI + +struct ObservedDependencyExampleView: View { + @ObservedDependency(\.observableService) var service: ObservableService + + var body: some View { + VStack { + Text("Счетчик: \(service.count)") + Button("Увеличить счетчик") { + service.count += 1 + } + } + } +} +``` + +### Тестовый случай + +Следующий тестовый случай демонстрирует взаимодействие с `ObservedDependency`: + +```swift +import XCTest +@testable import AppState + +@MainActor +fileprivate class ObservableService: ObservableObject { + @Published var count: Int + + init() { + count = 0 + } +} + +fileprivate extension Application { + @MainActor + var observableService: Dependency { + dependency(ObservableService()) + } +} + +@MainActor +fileprivate struct ExampleDependencyWrapper { + @ObservedDependency(\.observableService) var service + + func test() { + service.count += 1 + } +} + +final class ObservedDependencyTests: XCTestCase { + @MainActor + func testDependency() async { + let example = ExampleDependencyWrapper() + + XCTAssertEqual(example.service.count, 0) + + example.test() + + XCTAssertEqual(example.service.count, 1) + } +} +``` + +### Реактивные обновления пользовательского интерфейса + +Поскольку зависимость соответствует протоколу `ObservableObject`, любое изменение ее состояния вызовет обновление пользовательского интерфейса в представлении SwiftUI. Вы можете напрямую привязать состояние к элементам пользовательского интерфейса, таким как `Picker`: + +```swift +import AppState +import SwiftUI + +struct ReactiveView: View { + @ObservedDependency(\.observableService) var service: ObservableService + + var body: some View { + Picker("Выберите счетчик", selection: $service.count) { + ForEach(0..<10) { count in + Text("\(count)").tag(count) + } + } + } +} +``` + +## Лучшие практики + +- **Используйте для наблюдаемых служб**: `ObservedDependency` идеально подходит, когда вашей зависимости необходимо уведомлять представления об изменениях, особенно для служб, которые предоставляют обновления данных или состояния. +- **Используйте опубликованные свойства**: убедитесь, что ваша зависимость использует свойства `@Published` для запуска обновлений в ваших представлениях SwiftUI. +- **Потокобезопасность**: как и другие компоненты AppState, `ObservedDependency` обеспечивает потокобезопасный доступ и изменения наблюдаемой службы. + +## Заключение + +`ObservedDependency` — это мощный инструмент для управления наблюдаемыми зависимостями в вашем приложении. Используя протокол `ObservableObject` Swift, он гарантирует, что ваши представления SwiftUI остаются реактивными и актуальными с изменениями в службе или ресурсе. + +--- +Этот перевод был сгенерирован автоматически и может содержать ошибки. Если вы носитель языка, мы будем признательны за ваши исправления через Pull Request. diff --git a/documentation/ru/usage-overview.md b/documentation/ru/usage-overview.md new file mode 100644 index 0000000..be5422a --- /dev/null +++ b/documentation/ru/usage-overview.md @@ -0,0 +1,215 @@ +# Обзор использования + +Этот обзор представляет собой краткое введение в использование ключевых компонентов библиотеки **AppState** в SwiftUI `View`. Каждый раздел содержит простые примеры, которые вписываются в рамки структуры представления SwiftUI. + +## Определение значений в расширении приложения + +Для определения состояния или зависимостей в масштабах всего приложения необходимо расширить объект `Application`. Это позволяет централизовать все состояние вашего приложения в одном месте. Вот пример того, как расширить `Application` для создания различных состояний и зависимостей: + +```swift +import AppState + +extension Application { + var user: State { + state(initial: User(name: "Guest", isLoggedIn: false)) + } + + var userPreferences: StoredState { + storedState(initial: "Default Preferences", id: "userPreferences") + } + + var darkModeEnabled: SyncState { + syncState(initial: false, id: "darkModeEnabled") + } + + var userToken: SecureState { + secureState(id: "userToken") + } + + @MainActor + var largeDataset: FileState<[String]> { + fileState(initial: [], filename: "largeDataset") + } +} +``` + +## State + +`State` позволяет определить состояние в масштабах всего приложения, к которому можно получить доступ и изменить его в любом месте вашего приложения. + +### Пример + +```swift +import AppState +import SwiftUI + +struct ContentView: View { + @AppState(\.user) var user: User + + var body: some View { + VStack { + Text("Привет, \(user.name)!") + Button("Войти") { + user.isLoggedIn.toggle() + } + } + } +} +``` + +## StoredState + +`StoredState` сохраняет состояние с помощью `UserDefaults`, чтобы гарантировать, что значения сохраняются между запусками приложения. + +### Пример + +```swift +import AppState +import SwiftUI + +struct PreferencesView: View { + @StoredState(\.userPreferences) var userPreferences: String + + var body: some View { + VStack { + Text("Настройки: \(userPreferences)") + Button("Обновить настройки") { + userPreferences = "Updated Preferences" + } + } + } +} +``` + +## SyncState + +`SyncState` синхронизирует состояние приложения на нескольких устройствах с помощью iCloud. + +### Пример + +```swift +import AppState +import SwiftUI + +struct SyncSettingsView: View { + @SyncState(\.darkModeEnabled) var isDarkModeEnabled: Bool + + var body: some View { + VStack { + Toggle("Темный режим", isOn: $isDarkModeEnabled) + } + } +} +``` + +## FileState + +`FileState` используется для постоянного хранения больших или более сложных данных с помощью файловой системы, что делает его идеальным для кэширования или сохранения данных, которые не вписываются в ограничения `UserDefaults`. + +### Пример + +```swift +import AppState +import SwiftUI + +struct LargeDataView: View { + @FileState(\.largeDataset) var largeDataset: [String] + + var body: some View { + List(largeDataset, id: \.self) { item in + Text(item) + } + } +} +``` + +## SecureState + +`SecureState` надежно хранит конфиденциальные данные в связке ключей. + +### Пример + +```swift +import AppState +import SwiftUI + +struct SecureView: View { + @SecureState(\.userToken) var userToken: String? + + var body: some View { + VStack { + if let token = userToken { + Text("Токен пользователя: \(token)") + } else { + Text("Токен не найден.") + } + Button("Установить токен") { + userToken = "secure_token_value" + } + } + } +} +``` + +## Constant + +`Constant` предоставляет неизменяемый доступ только для чтения к значениям в состоянии вашего приложения, обеспечивая безопасность при доступе к значениям, которые не должны изменяться. + +### Пример + +```swift +import AppState +import SwiftUI + +struct ExampleView: View { + @Constant(\.user, \.name) var name: String + + var body: some View { + Text("Имя пользователя: \(name)") + } +} +``` + +## Slicing State + +`Slice` и `OptionalSlice` позволяют получить доступ к определенным частям состояния вашего приложения. + +### Пример + +```swift +import AppState +import SwiftUI + +struct SlicingView: View { + @Slice(\.user, \.name) var name: String + + var body: some View { + VStack { + Text("Имя пользователя: \(name)") + Button("Обновить имя пользователя") { + name = "NewUsername" + } + } + } +} +``` + +## Лучшие практики + +- **Используйте `AppState` в представлениях SwiftUI**: обертки свойств, такие как `@AppState`, `@StoredState`, `@FileState`, `@SecureState` и другие, предназначены для использования в области представлений SwiftUI. +- **Определяйте состояние в расширении приложения**: централизуйте управление состоянием, расширяя `Application` для определения состояния и зависимостей вашего приложения. +- **Реактивные обновления**: SwiftUI автоматически обновляет представления при изменении состояния, поэтому вам не нужно вручную обновлять пользовательский интерфейс. +- **[Руководство по лучшим практикам](best-practices.md)**: для подробного описания лучших практик при использовании AppState. + +## Следующие шаги + +После ознакомления с основами использования вы можете изучить более сложные темы: + +- Изучите использование **FileState** для сохранения больших объемов данных в файлы в [Руководстве по использованию FileState](usage-filestate.md). +- Узнайте о **константах** и о том, как их использовать для неизменяемых значений в состоянии вашего приложения, в [Руководстве по использованию констант](usage-constant.md). +- Узнайте, как **Dependency** используется в AppState для обработки общих служб, и посмотрите примеры в [Руководстве по использованию зависимостей состояния](usage-state-dependency.md). +- Углубитесь в более сложные методы **SwiftUI**, такие как использование `ObservedDependency` для управления наблюдаемыми зависимостями в представлениях, в [Руководстве по использованию ObservedDependency](usage-observeddependency.md). +- Для более сложных методов использования, таких как создание «точно в срок» и предварительная загрузка зависимостей, см. [Руководство по расширенному использованию](advanced-usage.md). + +--- +Этот перевод был сгенерирован автоматически и может содержать ошибки. Если вы носитель языка, мы будем признательны за ваши исправления через Pull Request. diff --git a/documentation/ru/usage-securestate.md b/documentation/ru/usage-securestate.md new file mode 100644 index 0000000..6dd46aa --- /dev/null +++ b/documentation/ru/usage-securestate.md @@ -0,0 +1,68 @@ +# Использование SecureState + +`SecureState` — это компонент библиотеки **AppState**, который позволяет безопасно хранить конфиденциальные данные в связке ключей. Он лучше всего подходит для хранения небольших фрагментов данных, таких как токены или пароли, которые необходимо надежно зашифровать. + +## Ключевые особенности + +- **Безопасное хранилище**: данные, хранящиеся с помощью `SecureState`, шифруются и безопасно сохраняются в связке ключей. +- **Постоянство**: данные остаются постоянными между запусками приложения, что позволяет безопасно извлекать конфиденциальные значения. + +## Ограничения связки ключей + +Хотя `SecureState` очень безопасен, у него есть определенные ограничения: + +- **Ограниченный размер хранилища**: связка ключей предназначена для небольших фрагментов данных. Она не подходит для хранения больших файлов или наборов данных. +- **Производительность**: доступ к связке ключей медленнее, чем доступ к `UserDefaults`, поэтому используйте его только при необходимости безопасного хранения конфиденциальных данных. + +## Пример использования + +### Хранение безопасного токена + +```swift +import AppState +import SwiftUI + +extension Application { + var userToken: SecureState { + secureState(id: "userToken") + } +} + +struct SecureView: View { + @SecureState(\.userToken) var userToken: String? + + var body: some View { + VStack { + if let token = userToken { + Text("Токен пользователя: \(token)") + } else { + Text("Токен не найден.") + } + Button("Установить токен") { + userToken = "secure_token_value" + } + } + } +} +``` + +### Обработка отсутствия безопасных данных + +При первом доступе к связке ключей или если значение не сохранено, `SecureState` вернет `nil`. Убедитесь, что вы правильно обрабатываете этот сценарий: + +```swift +if let token = userToken { + print("Токен: \(token)") +} else { + print("Токен недоступен.") +} +``` + +## Лучшие практики + +- **Используйте для небольших данных**: связку ключей следует использовать для хранения небольших фрагментов конфиденциальной информации, такой как токены, пароли и ключи. +- **Избегайте больших наборов данных**: если вам необходимо безопасно хранить большие наборы данных, рассмотрите возможность использования шифрования на основе файлов или других методов, поскольку связка ключей не предназначена для хранения больших данных. +- **Обрабатывайте nil**: всегда обрабатывайте случаи, когда связка ключей возвращает `nil` при отсутствии значения. + +--- +Этот перевод был сгенерирован автоматически и может содержать ошибки. Если вы носитель языка, мы будем признательны за ваши исправления через Pull Request. diff --git a/documentation/ru/usage-slice.md b/documentation/ru/usage-slice.md new file mode 100644 index 0000000..9feb25a --- /dev/null +++ b/documentation/ru/usage-slice.md @@ -0,0 +1,94 @@ +# Использование Slice и OptionalSlice + +`Slice` и `OptionalSlice` — это компоненты библиотеки **AppState**, которые позволяют вам получать доступ к определенным частям состояния вашего приложения. Они полезны, когда вам нужно манипулировать или наблюдать за частью более сложной структуры состояния. + +## Обзор + +- **Slice**: позволяет получать доступ и изменять определенную часть существующего объекта `State`. +- **OptionalSlice**: работает аналогично `Slice`, но предназначен для обработки необязательных значений, например, когда часть вашего состояния может быть `nil` или нет. + +### Ключевые особенности + +- **Выборочный доступ к состоянию**: получайте доступ только к той части состояния, которая вам нужна. +- **Потокобезопасность**: как и другие типы управления состоянием в **AppState**, `Slice` и `OptionalSlice` являются потокобезопасными. +- **Реактивность**: представления SwiftUI обновляются при изменении среза состояния, обеспечивая реактивность вашего пользовательского интерфейса. + +## Пример использования + +### Использование Slice + +В этом примере мы используем `Slice` для доступа и обновления определенной части состояния — в данном случае, `username` из более сложного объекта `User`, хранящегося в состоянии приложения. + +```swift +import AppState +import SwiftUI + +struct User { + var username: String + var email: String +} + +extension Application { + var user: State { + state(initial: User(username: "Guest", email: "guest@example.com")) + } +} + +struct SlicingView: View { + @Slice(\.user, \.username) var username: String + + var body: some View { + VStack { + Text("Имя пользователя: \(username)") + Button("Обновить имя пользователя") { + username = "NewUsername" + } + } + } +} +``` + +### Использование OptionalSlice + +`OptionalSlice` полезен, когда часть вашего состояния может быть `nil`. В этом примере сам объект `User` может быть `nil`, поэтому мы используем `OptionalSlice` для безопасной обработки этого случая. + +```swift +import AppState +import SwiftUI + +extension Application { + var user: State { + state(initial: nil) + } +} + +struct OptionalSlicingView: View { + @OptionalSlice(\.user, \.username) var username: String? + + var body: some View { + VStack { + if let username = username { + Text("Имя пользователя: \(username)") + } else { + Text("Имя пользователя недоступно") + } + Button("Установить имя пользователя") { + username = "UpdatedUsername" + } + } + } +} +``` + +## Лучшие практики + +- **Используйте `Slice` для необязательного состояния**: если ваше состояние гарантированно не является необязательным, используйте `Slice` для доступа к нему и его обновления. +- **Используйте `OptionalSlice` для необязательного состояния**: если ваше состояние или часть состояния является необязательной, используйте `OptionalSlice` для обработки случаев, когда значение может быть `nil`. +- **Потокобезопасность**: как и `State`, `Slice` и `OptionalSlice` являются потокобезопасными и предназначены для работы с моделью параллелизма Swift. + +## Заключение + +`Slice` и `OptionalSlice` предоставляют мощные способы доступа и изменения определенных частей вашего состояния потокобезопасным образом. Используя эти компоненты, вы можете упростить управление состоянием в более сложных приложениях, обеспечивая реактивность и актуальность вашего пользовательского интерфейса. + +--- +Этот перевод был сгенерирован автоматически и может содержать ошибки. Если вы носитель языка, мы будем признательны за ваши исправления через Pull Request. diff --git a/documentation/ru/usage-state-dependency.md b/documentation/ru/usage-state-dependency.md new file mode 100644 index 0000000..73b97b8 --- /dev/null +++ b/documentation/ru/usage-state-dependency.md @@ -0,0 +1,136 @@ +# Использование состояния и зависимостей + +**AppState** предоставляет мощные инструменты для управления состоянием в масштабах всего приложения и внедрения зависимостей в представления SwiftUI. Централизуя свое состояние и зависимости, вы можете обеспечить согласованность и удобство сопровождения вашего приложения. + +## Обзор + +- **Состояние**: представляет значение, которое можно совместно использовать в приложении. Значения состояния можно изменять и наблюдать в представлениях SwiftUI. +- **Зависимость**: представляет собой общий ресурс или службу, которую можно внедрять и получать доступ в представлениях SwiftUI. + +### Ключевые особенности + +- **Централизованное состояние**: определяйте и управляйте состоянием в масштабах всего приложения в одном месте. +- **Внедрение зависимостей**: внедряйте и получайте доступ к общим службам и ресурсам в различных компонентах вашего приложения. + +## Пример использования + +### Определение состояния приложения + +Чтобы определить состояние в масштабах всего приложения, расширьте объект `Application` и объявите свойства состояния. + +```swift +import AppState + +struct User { + var name: String + var isLoggedIn: Bool +} + +extension Application { + var user: State { + state(initial: User(name: "Guest", isLoggedIn: false)) + } +} +``` + +### Доступ и изменение состояния в представлении + +Вы можете получать доступ и изменять значения состояния непосредственно в представлении SwiftUI с помощью обертки свойства `@AppState`. + +```swift +import AppState +import SwiftUI + +struct ContentView: View { + @AppState(\.user) var user: User + + var body: some View { + VStack { + Text("Привет, \(user.name)!") + Button("Войти") { + user.name = "John Doe" + user.isLoggedIn = true + } + } + } +} +``` + +### Определение зависимостей + +Вы можете определить общие ресурсы, такие как сетевая служба, как зависимости в объекте `Application`. Эти зависимости можно внедрять в представления SwiftUI. + +```swift +import AppState + +protocol NetworkServiceType { + func fetchData() -> String +} + +class NetworkService: NetworkServiceType { + func fetchData() -> String { + return "Data from network" + } +} + +extension Application { + var networkService: Dependency { + dependency(NetworkService()) + } +} +``` + +### Доступ к зависимостям в представлении + +Получайте доступ к зависимостям в представлении SwiftUI с помощью обертки свойства `@AppDependency`. Это позволяет внедрять службы, такие как сетевая служба, в ваше представление. + +```swift +import AppState +import SwiftUI + +struct NetworkView: View { + @AppDependency(\.networkService) var networkService: NetworkServiceType + + var body: some View { + VStack { + Text("Данные: \(networkService.fetchData())") + } + } +} +``` + +### Объединение состояния и зависимостей в представлении + +Состояние и зависимости могут работать вместе для создания более сложной логики приложения. Например, вы можете получать данные из службы и обновлять состояние: + +```swift +import AppState +import SwiftUI + +struct CombinedView: View { + @AppState(\.user) var user: User + @AppDependency(\.networkService) var networkService: NetworkServiceType + + var body: some View { + VStack { + Text("Пользователь: \(user.name)") + Button("Получить данные") { + user.name = networkService.fetchData() + user.isLoggedIn = true + } + } + } +} +``` + +### Лучшие практики + +- **Централизуйте состояние**: храните состояние вашего приложения в одном месте, чтобы избежать дублирования и обеспечить согласованность. +- **Используйте зависимости для общих служб**: внедряйте зависимости, такие как сетевые службы, базы данных или другие общие ресурсы, чтобы избежать тесной связи между компонентами. + +## Заключение + +С помощью **AppState** вы можете управлять состоянием в масштабах всего приложения и внедрять общие зависимости непосредственно в ваши представления SwiftUI. Этот шаблон помогает сохранить модульность и удобство сопровождения вашего приложения. Изучите другие функции библиотеки **AppState**, такие как [SecureState](usage-securestate.md) и [SyncState](usage-syncstate.md), чтобы еще больше улучшить управление состоянием вашего приложения. + +--- +Этот перевод был сгенерирован автоматически и может содержать ошибки. Если вы носитель языка, мы будем признательны за ваши исправления через Pull Request. diff --git a/documentation/ru/usage-storedstate.md b/documentation/ru/usage-storedstate.md new file mode 100644 index 0000000..fe00222 --- /dev/null +++ b/documentation/ru/usage-storedstate.md @@ -0,0 +1,75 @@ +# Использование StoredState + +`StoredState` — это компонент библиотеки **AppState**, который позволяет хранить и сохранять небольшие объемы данных с помощью `UserDefaults`. Он идеально подходит для хранения легковесных, неконфиденциальных данных, которые должны сохраняться между запусками приложения. + +## Обзор + +- **StoredState** построен на основе `UserDefaults`, что означает, что он быстр и эффективен для хранения небольших объемов данных (таких как пользовательские настройки или настройки приложения). +- Данные, сохраненные в **StoredState**, сохраняются между сеансами приложения, что позволяет восстанавливать состояние приложения при запуске. + +### Ключевые особенности + +- **Постоянное хранилище**: данные, сохраненные в `StoredState`, остаются доступными между запусками приложения. +- **Обработка небольших данных**: лучше всего использовать для легковесных данных, таких как настройки, переключатели или небольшие конфигурации. +- **Потокобезопасность**: `StoredState` обеспечивает безопасный доступ к данным в многопоточных средах. + +## Пример использования + +### Определение StoredState + +Вы можете определить **StoredState**, расширив объект `Application` и объявив свойство состояния: + +```swift +import AppState + +extension Application { + var userPreferences: StoredState { + storedState(initial: "Default Preferences", id: "userPreferences") + } +} +``` + +### Доступ и изменение StoredState в представлении + +Вы можете получать доступ и изменять значения **StoredState** в представлениях SwiftUI с помощью обертки свойства `@StoredState`: + +```swift +import AppState +import SwiftUI + +struct PreferencesView: View { + @StoredState(\.userPreferences) var userPreferences: String + + var body: some View { + VStack { + Text("Настройки: \(userPreferences)") + Button("Обновить настройки") { + userPreferences = "Updated Preferences" + } + } + } +} +``` + +## Обработка миграции данных + +По мере развития вашего приложения вы можете обновлять модели, которые сохраняются с помощью **StoredState**. При обновлении вашей модели данных обеспечьте обратную совместимость. Например, вы можете добавить новые поля или версионировать свою модель для обработки миграции. + +Для получения дополнительной информации обратитесь к [Руководству по вопросам миграции](migration-considerations.md). + +### Вопросы миграции + +- **Добавление новых необязательных полей**: убедитесь, что новые поля являются необязательными или имеют значения по умолчанию для поддержания обратной совместимости. +- **Версионирование моделей**: если ваша модель данных со временем изменяется, включите поле `version` для управления различными версиями ваших сохраненных данных. + +## Лучшие практики + +- **Используйте для небольших данных**: храните легковесные, неконфиденциальные данные, которые должны сохраняться между запусками приложения, например, пользовательские настройки. +- **Рассмотрите альтернативы для больших данных**: если вам нужно хранить большие объемы данных, рассмотрите возможность использования **FileState**. + +## Заключение + +**StoredState** — это простой и эффективный способ сохранения небольших фрагментов данных с помощью `UserDefaults`. Он идеально подходит для сохранения настроек и других небольших параметров между запусками приложения, обеспечивая при этом безопасный доступ и простую интеграцию с SwiftUI. Для более сложных потребностей в сохранении изучите другие функции **AppState**, такие как [FileState](usage-filestate.md) или [SyncState](usage-syncstate.md). + +--- +Этот перевод был сгенерирован автоматически и может содержать ошибки. Если вы носитель языка, мы будем признательны за ваши исправления через Pull Request. diff --git a/documentation/ru/usage-syncstate.md b/documentation/ru/usage-syncstate.md new file mode 100644 index 0000000..d80e89e --- /dev/null +++ b/documentation/ru/usage-syncstate.md @@ -0,0 +1,159 @@ +# Использование SyncState + +`SyncState` — это компонент библиотеки **AppState**, который позволяет синхронизировать состояние приложения на нескольких устройствах с помощью iCloud. Это особенно полезно для поддержания согласованности пользовательских настроек, параметров и других важных данных на всех устройствах. + +## Обзор + +`SyncState` использует `NSUbiquitousKeyValueStore` iCloud для синхронизации небольших объемов данных на всех устройствах. Это делает его идеальным для синхронизации легковесного состояния приложения, такого как настройки или пользовательские параметры. + +### Ключевые особенности + +- **Синхронизация с iCloud**: автоматическая синхронизация состояния на всех устройствах, вошедших в одну и ту же учетную запись iCloud. +- **Постоянное хранилище**: данные постоянно хранятся в iCloud, что означает, что они сохранятся даже при завершении или перезапуске приложения. +- **Синхронизация почти в реальном времени**: изменения состояния распространяются на другие устройства почти мгновенно. + +> **Примечание**: `SyncState` поддерживается на watchOS 9.0 и более поздних версиях. + +## Пример использования + +### Модель данных + +Предположим, у нас есть структура с именем `Settings`, которая соответствует `Codable`: + +```swift +struct Settings: Codable { + var text: String + var isShowingSheet: Bool + var isDarkMode: Bool +} +``` + +### Определение SyncState + +Вы можете определить `SyncState`, расширив объект `Application` и объявив свойства состояния, которые должны быть синхронизированы: + +```swift +extension Application { + var settings: SyncState { + syncState( + initial: Settings( + text: "Hello, World!", + isShowingSheet: false, + isDarkMode: false + ), + id: "settings" + ) + } +} +``` + +### Обработка внешних изменений + +Чтобы убедиться, что приложение реагирует на внешние изменения из iCloud, переопределите функцию `didChangeExternally`, создав настраиваемый подкласс `Application`: + +```swift +class CustomApplication: Application { + override func didChangeExternally(notification: Notification) { + super.didChangeExternally(notification: notification) + + DispatchQueue.main.async { + self.objectWillChange.send() + } + } +} +``` + +### Создание представлений для изменения и синхронизации состояния + +В следующем примере у нас есть два представления: `ContentView` и `ContentViewInnerView`. Эти представления совместно используют и синхронизируют состояние `Settings`. `ContentView` позволяет пользователю изменять `text` и переключать `isDarkMode`, а `ContentViewInnerView` отображает тот же текст и обновляет его при нажатии. + +```swift +struct ContentView: View { + @SyncState(\.settings) private var settings: Settings + + var body: some View { + VStack { + TextField("", text: $settings.text) + + Button(settings.isDarkMode ? "Light" : "Dark") { + settings.isDarkMode.toggle() + } + + Button("Show") { settings.isShowingSheet = true } + } + .preferredColorScheme(settings.isDarkMode ? .dark : .light) + .sheet(isPresented: $settings.isShowingSheet, content: ContentViewInnerView.init) + } +} + +struct ContentViewInnerView: View { + @Slice(\.settings, \.text) private var text: String + + var body: some View { + Text("\(text)") + .onTapGesture { + text = Date().formatted() + } + } +} +``` + +### Настройка приложения + +Наконец, настройте приложение в структуре `@main`. При инициализации повысьте уровень настраиваемого приложения, включите ведение журнала и загрузите зависимость хранилища iCloud для синхронизации: + +```swift +@main +struct SyncStateExampleApp: App { + init() { + Application + .promote(to: CustomApplication.self) + .logging(isEnabled: true) + .load(dependency: \.icloudStore) + } + + var body: some Scene { + WindowGroup { + ContentView() + } + } +} +``` + +### Включение хранилища ключ-значение iCloud + +Чтобы включить синхронизацию iCloud, убедитесь, что вы следуете этому руководству, чтобы включить возможность хранилища ключ-значение iCloud: [Начало работы с SyncState](starting-to-use-syncstate.md). + +### SyncState: примечания по хранилищу iCloud + +Хотя `SyncState` обеспечивает простую синхронизацию, важно помнить об ограничениях `NSUbiquitousKeyValueStore`: + +- **Ограничение хранилища**: вы можете хранить до 1 МБ данных в iCloud с помощью `NSUbiquitousKeyValueStore`, с ограничением размера значения для каждого ключа в 1 МБ. + +### Вопросы миграции + +При обновлении вашей модели данных важно учитывать потенциальные проблемы миграции, особенно при работе с постоянными данными с использованием **StoredState**, **FileState** или **SyncState**. Без надлежащей обработки миграции такие изменения, как добавление новых полей или изменение форматов данных, могут вызвать проблемы при загрузке старых данных. + +Вот несколько ключевых моментов, которые следует учитывать: +- **Добавление новых необязательных полей**: убедитесь, что новые поля являются необязательными или имеют значения по умолчанию для поддержания обратной совместимости. +- **Обработка изменений формата данных**: если структура вашей модели изменяется, реализуйте настраиваемую логику декодирования для поддержки старых форматов. +- **Версионирование ваших моделей**: используйте поле `version` в ваших моделях, чтобы помочь с миграцией и применить логику на основе версии данных. + +Чтобы узнать больше о том, как управлять миграцией и избегать потенциальных проблем, обратитесь к [Руководству по вопросам миграции](migration-considerations.md). + +## Руководство по реализации SyncState + +Для получения подробных инструкций о том, как настроить iCloud и SyncState в вашем проекте, см. [Руководство по реализации SyncState](syncstate-implementation.md). + +## Лучшие практики + +- **Используйте для небольших, критически важных данных**: `SyncState` идеально подходит для синхронизации небольших, важных фрагментов состояния, таких как пользовательские настройки, параметры или флаги функций. +- **Контролируйте хранилище iCloud**: убедитесь, что ваше использование `SyncState` остается в пределах ограничений хранилища iCloud, чтобы предотвратить проблемы с синхронизацией данных. +- **Обрабатывайте внешние обновления**: если вашему приложению необходимо реагировать на изменения состояния, инициированные на другом устройстве, переопределите функцию `didChangeExternally`, чтобы обновлять состояние приложения в режиме реального времени. + +## Заключение + +`SyncState` предоставляет мощный способ синхронизации небольших объемов состояния приложения на всех устройствах через iCloud. Он идеально подходит для обеспечения согласованности пользовательских настроек и других ключевых данных на всех устройствах, вошедших в одну и ту же учетную запись iCloud. Для более сложных случаев использования изучите другие функции **AppState**, такие как [SecureState](usage-securestate.md) и [FileState](usage-filestate.md). + +--- +Этот перевод был сгенерирован автоматически и может содержать ошибки. Если вы носитель языка, мы будем признательны за ваши исправления через Pull Request. diff --git a/documentation/zh-CN/advanced-usage.md b/documentation/zh-CN/advanced-usage.md new file mode 100644 index 0000000..6d62a30 --- /dev/null +++ b/documentation/zh-CN/advanced-usage.md @@ -0,0 +1,181 @@ +# AppState 的高级用法 + +本指南涵盖了使用 **AppState** 的高级主题,包括即时创建、预加载依赖项、有效管理状态和依赖项,以及将 **AppState** 与 **SwiftUI 的 Environment** 进行比较。 + +## 1. 即时创建 + +AppState 的值,例如 `State`、`Dependency`、`StoredState` 和 `SyncState`,是即时创建的。这意味着它们仅在首次访问时才被实例化,从而提高了应用程序的效率和性能。 + +### 示例 + +```swift +extension Application { + var defaultState: State { + state(initial: 0) // 该值直到被访问时才被创建 + } +} +``` + +在此示例中,`defaultState` 直到首次访问时才被创建,从而优化了资源使用。 + +## 2. 预加载依赖项 + +在某些情况下,您可能希望预加载某些依赖项,以确保它们在应用程序启动时可用。AppState 提供了一个 `load` 函数来预加载依赖项。 + +### 示例 + +```swift +extension Application { + var databaseClient: Dependency { + dependency(DatabaseClient()) + } +} + +// 在应用程序初始化时预加载 +Application.load(dependency: \.databaseClient) +``` + +在此示例中,`databaseClient` 在应用程序初始化期间被预加载,确保在视图中需要时可用。 + +## 3. 状态和依赖项管理 + +### 3.1 在整个应用程序中共享状态和依赖项 + +您可以在应用程序的一部分中定义共享状态或依赖项,并使用唯一 ID 在另一部分中访问它们。 + +### 示例 + +```swift +private extension Application { + var stateValue: State { + state(initial: 0, id: "stateValue") + } + + var dependencyValue: Dependency { + dependency(SomeType(), id: "dependencyValue") + } +} +``` + +这使您可以通过使用相同的 ID 在其他地方访问相同的 `State` 或 `Dependency`。 + +```swift +private extension Application { + var theSameStateValue: State { + state(initial: 0, id: "stateValue") + } + + var theSameDependencyValue: Dependency { + dependency(SomeType(), id: "dependencyValue") + } +} +``` + +虽然这种通过重用相同的字符串 `id` 在整个应用程序中共享状态和依赖项的方法是有效的,但通常不鼓励这样做。它依赖于手动管理这些字符串 ID,这可能导致: +- 如果相同的 ID 用于不同的预期状态/依赖项,则会发生意外的 ID 冲突。 +- 难以跟踪状态/依赖项的定义位置与访问位置。 +- 降低了代码的清晰度和可维护性。 +如果状态/依赖项已通过其首次访问进行了初始化,则在后续使用相同 ID 的定义中提供的 `initial` 值将被忽略。此行为更多是 AppState 中基于 ID 的缓存工作方式的副作用,而不是定义共享数据的推荐主要模式。首选在 `Application` 扩展中将状态和依赖项定义为唯一的计算属性(如果在工厂方法中未提供显式 `id`,则会自动生成唯一的内部 ID)。 + +### 3.2 受限的状态和依赖项访问 + +要限制访问,请使用像 UUID 这样的唯一 ID,以确保只有应用程序的正确部分才能访问特定的状态或依赖项。 + +### 示例 + +```swift +private extension Application { + var restrictedState: State { + state(initial: nil, id: UUID().uuidString) + } + + var restrictedDependency: Dependency { + dependency(SomeType(), id: UUID().uuidString) + } +} +``` + +### 3.3 状态和依赖项的唯一 ID + +当未提供 ID 时,AppState 会根据源代码中的位置生成默认 ID。这确保了每个 `State` 或 `Dependency` 都是唯一的,并受到保护,防止意外访问。 + +### 示例 + +```swift +extension Application { + var defaultState: State { + state(initial: 0) // AppState 生成一个唯一的 ID + } + + var defaultDependency: Dependency { + dependency(SomeType()) // AppState 生成一个唯一的 ID + } +} +``` + +### 3.4 文件私有状态和依赖项访问 + +为了在同一个 Swift 文件中实现更严格的访问限制,请使用 `fileprivate` 访问级别来保护状态和依赖项不被外部访问。 + +### 示例 + +```swift +fileprivate extension Application { + var fileprivateState: State { + state(initial: 0) + } + + var fileprivateDependency: Dependency { + dependency(SomeType()) + } +} +``` + +### 3.5 理解 AppState 的存储机制 + +AppState 使用统一的缓存来存储 `State`、`Dependency`、`StoredState` 和 `SyncState`。这确保了这些数据类型在您的应用程序中得到有效管理。 + +默认情况下,AppState 将名称值指定为“App”,这确保了与模块关联的所有值都与该名称绑定。这使得从其他模块访问这些状态和依赖项变得更加困难。 + +## 4. AppState 与 SwiftUI 的 Environment + +AppState 和 SwiftUI 的 Environment 都提供了在应用程序中管理共享状态和依赖项的方法,但它们在范围、功能和用例上有所不同。 + +### 4.1 SwiftUI 的 Environment + +SwiftUI 的 Environment 是一种内置机制,允许您通过视图层次结构向下传递共享数据。它非常适合传递许多视图需要访问的数据,但在更复杂的状态管理方面存在局限性。 + +**优点:** +- 使用简单,与 SwiftUI 集成良好。 +- 非常适合需要在层次结构中的多个视图之间共享的轻量级数据。 + +**局限性:** +- 数据仅在特定的视图层次结构中可用。在没有额外工作的情况下,无法跨不同的视图层次结构访问相同的数据。 +- 与 AppState 相比,对线程安全和持久性的控制较少。 +- 缺乏内置的持久性或同步机制。 + +### 4.2 AppState + +AppState 为在整个应用程序中管理状态提供了一个更强大、更灵活的系统,具有线程安全、持久性和依赖项注入功能。 + +**优点:** +- 集中式状态管理,可在整个应用程序中访问,而不仅仅是在特定的视图层次结构中。 +- 内置的持久性机制(`StoredState`、`FileState` 和 `SyncState`)。 +- 类型安全和线程安全保证,确保状态被正确访问和修改。 +- 可以处理更复杂的状态和依赖项管理。 + +**局限性:** +- 与 SwiftUI 的 Environment 相比,需要更多的设置和配置。 +- 与 Environment 相比,与 SwiftUI 的集成程度稍差,但在 SwiftUI 应用程序中仍然运行良好。 + +### 4.3 何时使用 + +- 当您有需要在视图层次结构中共享的简单数据(例如用户设置或主题首选项)时,请使用 **SwiftUI 的 Environment**。 +- 当您需要集中式状态管理、持久性或需要在整个应用程序中访问的更复杂的状态时,请使用 **AppState**。 + +## 结论 + +通过使用这些高级技术,例如即时创建、预加载、状态和依赖项管理,以及理解 AppState 和 SwiftUI 的 Environment 之间的差异,您可以使用 **AppState** 构建高效且资源节约的应用程序。 + +--- +该译文由机器自动生成,可能存在错误。如果您是母语使用者,我们期待您通过 Pull Request 提出修改建议。 diff --git a/documentation/zh-CN/best-practices.md b/documentation/zh-CN/best-practices.md new file mode 100644 index 0000000..cd29d32 --- /dev/null +++ b/documentation/zh-CN/best-practices.md @@ -0,0 +1,65 @@ +# 使用 AppState 的最佳实践 + +本指南提供了帮助您在 Swift 应用程序中高效使用 AppState 的最佳实践。 + +## 1. 谨慎使用 AppState + +AppState 功能多样,适用于共享和本地化状态管理。它非常适合需要在多个组件之间共享、跨视图或用户会话持久化或在组件级别管理的数据。然而,过度使用可能导致不必要的复杂性。 + +### 建议: +- 将 AppState 用于真正需要在整个应用程序范围内共享、在远距离组件之间共享或需要 AppState 特定持久化/同步功能的数据。 +- 对于单个 SwiftUI 视图或紧密视图层次结构中的本地状态,首选 SwiftUI 的内置工具,如 `@State`、`@StateObject`、`@ObservedObject` 或 `@EnvironmentObject`。 + +## 2. 保持 AppState 的整洁 + +随着应用程序的扩展,您的 AppState 可能会变得越来越复杂。定期审查和重构您的 AppState,以删除未使用的状态和依赖项。保持 AppState 的整洁可以使其更易于理解、维护和测试。 + +### 建议: +- 定期审计您的 AppState,查找未使用或冗余的状态和依赖项。 +- 重构大型 AppState 结构,以保持其整洁和可管理性。 + +## 3. 测试您的 AppState + +与应用程序的其他方面一样,确保您的 AppState 经过了彻底的测试。在测试期间,使用模拟依赖项将您的 AppState 与外部依赖项隔离开来,并确认应用程序的每个部分都按预期运行。 + +### 建议: +- 使用 XCTest 或类似框架来测试 AppState 的行为和交互。 +- 模拟或存根依赖项,以确保 AppState 测试是隔离且可靠的。 + +## 4. 明智地使用 Slice 功能 + +`Slice` 功能允许您访问 AppState 状态的特定部分,这对于处理大型复杂的状态结构非常有用。但是,要明智地使用此功能,以保持 AppState 的整洁和组织良好,避免不必要的切片,从而导致状态处理的碎片化。 + +### 建议: +- 仅在需要访问单个组件的大型或嵌套状态时使用 `Slice`。 +- 避免过度切片状态,这可能导致混乱和碎片化的状态管理。 + +## 5. 使用常量来表示静态值 + +`@Constant` 功能允许您定义可在整个应用程序中共享的只读常量。它对于在应用程序生命周期内保持不变的值(如配置设置或预定义数据)非常有用。常量可确保这些值不会被意外修改。 + +### 建议: +- 对于保持不变的值,例如应用程序配置、环境变量或静态引用,请使用 `@Constant`。 + +## 6. 模块化您的 AppState + +对于大型应用程序,可以考虑将您的 AppState 分解为更小、更易于管理的模块。每个模块可以有自己的状态和依赖项,然后将它们组合成整个 AppState。这可以使您的 AppState 更易于理解、测试和维护。 + +### 建议: +- 将您的 `Application` 扩展组织到单独的 Swift 文件甚至单独的 Swift 模块中,按功能或领域分组。这自然地模块化了定义。 +- 在使用 `state(initial:feature:id:)` 等工厂方法定义状态或依赖项时,利用 `feature` 参数提供命名空间,例如 `state(initial: 0, feature: "UserProfile", id: "score")`。这有助于组织和防止在使用手动 ID 时的 ID 冲突。 +- 避免创建 `Application` 的多个实例。坚持扩展和使用共享的单例(`Application.shared`)。 + +## 7. 利用即时创建 + +AppState 值是即时创建的,这意味着它们仅在被访问时才被实例化。这优化了内存使用,并确保 AppState 值仅在必要时才被创建。 + +### 建议: +- 允许 AppState 值即时创建,而不是不必要地预加载所有状态和依赖项。 + +## 结论 + +每个应用程序都是独一无二的,因此这些最佳实践可能不适用于所有情况。在决定如何使用 AppState 时,请始终考虑您的应用程序的具体要求,并努力保持您的状态管理整洁、高效和经过良好测试。 + +--- +该译文由机器自动生成,可能存在错误。如果您是母语使用者,我们期待您通过 Pull Request 提出修改建议。 diff --git a/documentation/zh-CN/contributing.md b/documentation/zh-CN/contributing.md new file mode 100644 index 0000000..a368c83 --- /dev/null +++ b/documentation/zh-CN/contributing.md @@ -0,0 +1,63 @@ +# 为 AppState 做贡献 + +感谢您考虑为 **AppState** 做出贡献!您的贡献有助于让这个项目对每个人都更好。 + +## 如何贡献 + +### 1. 报告错误 + +如果您遇到任何错误,请在 GitHub 上提出一个问题。在报告错误时,请包括: + +- 一个清晰且描述性的标题。 +- 错误的详细描述,包括重现错误的步骤。 +- 预期的行为以及实际发生的情况。 +- 您正在使用的 **AppState** 的版本。 +- 任何相关的截图或日志。 + +### 2. 建议功能 + +欢迎提出新想法!如果您希望看到某个功能被添加到 **AppState** 中,请提出一个问题并描述: + +- 该功能将解决的问题。 +- 您认为该功能应该如何工作。 +- 任何有助于说明您的想法的额外上下文或示例。 + +### 3. 提交拉取请求 + +如果您想为 **AppState** 贡献代码,请按照以下步骤操作: + +1. **Fork 仓库**:在 GitHub 上创建 **AppState** 仓库的个人分支。 +2. **克隆您的分支**:将您的分支克隆到本地计算机: + ```bash + git clone https://github.com/your-username/AppState.git + ``` +3. **创建一个新分支**:为您的功能或错误修复创建一个新分支: + ```bash + git checkout -b my-feature-branch + ``` +4. **进行更改**:在新分支中实现您的更改。 +5. **测试您的更改**:确保您的更改通过所有测试。如有必要,请添加新测试。 +6. **提交您的更改**:使用描述性的提交消息提交您的更改: + ```bash + git commit -m "Add my new feature" + ``` +7. **推送到 GitHub**:将您的分支推送到您的 GitHub 分支: + ```bash + git push origin my-feature-branch + ``` +8. **创建拉取请求**:转到 GitHub 上的 **AppState** 仓库,并从您的分支创建一个拉取请求。 + +### 4. 代码风格 + +请遵循 **AppState** 项目中使用的编码风格指南。一致的代码风格有助于使代码库更易于维护和审查。 + +### 5. 许可证 + +通过为 **AppState** 做出贡献,您同意您的贡献将根据与项目相同的许可证进行许可:[许可证](https://github.com/0xLeif/AppState/blob/main/LICENSE)。 + +## 谢谢! + +您的贡献非常有价值和赞赏。感谢您帮助改进 **AppState**! + +--- +该译文由机器自动生成,可能存在错误。如果您是母语使用者,我们期待您通过 Pull Request 提出修改建议。 diff --git a/documentation/zh-CN/faq.md b/documentation/zh-CN/faq.md new file mode 100644 index 0000000..e5e69ed --- /dev/null +++ b/documentation/zh-CN/faq.md @@ -0,0 +1,43 @@ +# 常见问题 + +这个简短的常见问题解答解决了开发人员在使用 **AppState** 时可能遇到的常见问题。 + +## 如何重置状态值? + +对于像 `StoredState`、`FileState` 和 `SyncState` 这样的持久化状态,您可以使用 `Application` 类型上的静态 `reset` 函数将它们重置为初始值。 + +例如,要重置一个 `StoredState`: +```swift +extension Application { + var hasCompletedOnboarding: StoredState { storedState(initial: false, id: "onboarding_complete") } +} + +// 在您的代码中的某个地方 +Application.reset(storedState: \.hasCompletedOnboarding) +``` +这将把 `UserDefaults` 中的值重置为 `false`。`FileState`、`SyncState` 和 `SecureState` 也存在类似的 `reset` 函数。 + +对于非持久化的 `State`,您可以像持久化状态一样重置它: +```swift +extension Application { + var counter: State { state(initial: 0) } +} + +// 在您的代码中的某个地方 +Application.reset(\.counter) +``` + +## 我可以在异步任务中使用 AppState 吗? + +可以。`State` 和依赖项值是线程安全的,并且可以与 Swift Concurrency 无缝协作。您可以在 `async` 函数中访问和修改它们,而无需额外的锁定。 + +## 我应该在哪里定义状态和依赖项? + +将您所有的状态和依赖项都放在 `Application` 扩展中。这确保了单一的真实来源,并使发现所有可用的值变得更加容易。 + +## AppState 与 Combine 兼容吗? + +您可以通过将 `State` 的更改桥接到发布者来将 AppState 与 Combine 一起使用。观察一个 `State` 值,并在需要时通过 `PassthroughSubject` 或其他 Combine 发布者发送更新。 + +--- +该译文由机器自动生成,可能存在错误。如果您是母语使用者,我们期待您通过 Pull Request 提出修改建议。 diff --git a/documentation/zh-CN/installation.md b/documentation/zh-CN/installation.md new file mode 100644 index 0000000..ac59595 --- /dev/null +++ b/documentation/zh-CN/installation.md @@ -0,0 +1,87 @@ +# 安装指南 + +本指南将引导您完成使用 Swift Package Manager 将 **AppState** 安装到您的 Swift 项目中的过程。 + +## Swift Package Manager + +**AppState** 可以使用 Swift Package Manager 轻松集成到您的项目中。请按照以下步骤添加 **AppState** 作为依赖项。 + +### 步骤 1:更新您的 `Package.swift` 文件 + +将 **AppState** 添加到您的 `Package.swift` 文件的 `dependencies` 部分: + +```swift +dependencies: [ + .package(url: "https://github.com/0xLeif/AppState.git", from: "2.2.0") +] +``` + +### 步骤 2:将 AppState 添加到您的目标 + +在您的目标依赖项中包含 AppState: + +```swift +.target( + name: "YourTarget", + dependencies: ["AppState"] +) +``` + +### 步骤 3:构建您的项目 + +将 AppState 添加到您的 `Package.swift` 文件后,构建您的项目以获取依赖项并将其集成到您的代码库中。 + +``` +swift build +``` + +### 步骤 4:在您的代码中导入 AppState + +现在,您可以通过在 Swift 文件的顶部导入 AppState 来开始在您的项目中使用它: + +```swift +import AppState +``` + +## Xcode + +如果您希望直接通过 Xcode 添加 **AppState**,请按照以下步骤操作: + +### 步骤 1:打开您的 Xcode 项目 + +打开您的 Xcode 项目或工作区。 + +### 步骤 2:添加 Swift 包依赖项 + +1. 导航到项目导航器并选择您的项目文件。 +2. 在项目编辑器中,选择您的目标,然后转到“Swift Packages”选项卡。 +3. 单击“+”按钮以添加包依赖项。 + +### 步骤 3:输入仓库 URL + +在“选择包仓库”对话框中,输入以下 URL:`https://github.com/0xLeif/AppState.git` + +然后单击“下一步”。 + +### 步骤 4:指定版本 + +选择您要使用的版本。建议选择“直到下一个主要版本”选项,并将 `2.0.0` 指定为下限。然后单击“下一步”。 + +### 步骤 5:添加包 + +Xcode 将获取该包并为您提供将 **AppState** 添加到您的目标的选项。请确保选择正确的目标,然后单击“完成”。 + +### 步骤 6:在您的代码中导入 `AppState` + +现在,您可以在 Swift 文件的顶部导入 **AppState**: + +```swift +import AppState +``` + +## 后续步骤 + +安装 AppState 后,您可以转到[用法概述](usage-overview.md)以了解如何在您的项目中实现关键功能。 + +--- +该译文由机器自动生成,可能存在错误。如果您是母语使用者,我们期待您通过 Pull Request 提出修改建议。 diff --git a/documentation/zh-CN/migration-considerations.md b/documentation/zh-CN/migration-considerations.md new file mode 100644 index 0000000..06e380f --- /dev/null +++ b/documentation/zh-CN/migration-considerations.md @@ -0,0 +1,81 @@ +# 迁移注意事项 + +在更新您的数据模型时,特别是对于持久化或同步的数据,您需要处理向后兼容性,以避免在加载旧数据时出现潜在问题。以下是一些需要牢记的重要事项: + +## 1. 添加非可选字段 +如果您向模型中添加新的非可选字段,解码旧数据(其中不包含这些字段)可能会失败。为避免这种情况: +- 考虑为新字段提供默认值。 +- 将新字段设为可选,以确保与旧版应用程序的兼容性。 + +### 示例: +```swift +struct Settings: Codable { + var text: String + var isDarkMode: Bool + var newField: String? // 新字段是可选的 +} +``` + +## 2. 数据格式更改 +如果您修改了模型的结构(例如,将类型从 `Int` 更改为 `String`),在读取旧数据时解码过程可能会失败。通过以下方式规划平滑迁移: +- 创建迁移逻辑以将旧数据格式转换为新结构。 +- 使用 `Decodable` 的自定义初始化程序来处理旧数据并将其映射到您的新模型。 + +### 示例: +```swift +struct Settings: Codable { + var text: String + var isDarkMode: Bool + var version: Int + + // 针对旧版本的自定义解码逻辑 + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.text = try container.decode(String.self, forKey: .text) + self.isDarkMode = try container.decode(Bool.self, forKey: .isDarkMode) + self.version = (try? container.decode(Int.self, forKey: .version)) ?? 1 // 旧数据的默认值 + } +} +``` + +## 3. 处理已删除或已弃用的字段 +如果您从模型中删除一个字段,请确保旧版本的应用程序仍然可以在不崩溃的情况下解码新数据。您可以: +- 在解码时忽略多余的字段。 +- 使用自定义解码器来处理旧数据并正确管理已弃用的字段。 + +## 4. 版本化您的模型 + +版本化您的模型允许您随时间处理数据结构中的更改。通过在模型中保留版本号,您可以轻松地实现迁移逻辑,将旧数据格式转换为新数据格式。这种方法可确保您的应用程序可以处理旧数据结构,同时平滑地过渡到新版本。 + +- **为什么版本化很重要**:当用户更新其应用程序时,他们的设备上可能仍保留有旧数据。版本化可帮助您的应用程序识别数据格式并应用正确的迁移逻辑。 +- **如何使用**:向您的模型添加一个 `version` 字段,并在解码过程中检查它,以确定是否需要迁移。 + +### 示例: +```swift +struct Settings: Codable { + var version: Int + var text: String + var isDarkMode: Bool + + // 处理特定于版本的解码逻辑 + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.version = try container.decode(Int.self, forKey: .version) + self.text = try container.decode(String.self, forKey: .text) + self.isDarkMode = try container.decode(Bool.self, forKey: .isDarkMode) + + // 如果从旧版本迁移,请在此处应用必要的转换 + if version < 2 { + // 将旧数据迁移到新格式 + } + } +} +``` + +- **最佳实践**:从一开始就使用 `version` 字段。每次更新模型结构时,增加版本并处理必要的迁移逻辑。 + +## 5. 测试迁移 +始终通过使用新版本的模型模拟加载旧数据来彻底测试您的迁移,以确保您的应用程序按预期运行。 + +--- +该译文由机器自动生成,可能存在错误。如果您是母语使用者,我们期待您通过 Pull Request 提出修改建议。 diff --git a/documentation/zh-CN/starting-to-use-syncstate.md b/documentation/zh-CN/starting-to-use-syncstate.md new file mode 100644 index 0000000..4dbaff5 --- /dev/null +++ b/documentation/zh-CN/starting-to-use-syncstate.md @@ -0,0 +1,27 @@ +# 开始使用 SyncState + +要使用 SyncState,您首先需要在您的 Xcode 项目中设置 iCloud 功能和权利。以下是指导您完成该过程的简介: + +### 设置 iCloud 功能: + +1. 打开您的 Xcode 项目并调整 macOS 和 iOS 目标的捆绑包标识符以匹配您自己的。 +2. 接下来,您需要将 iCloud 功能添加到您的项目中。为此,请在项目导航器中选择您的项目,然后选择您的目标。在编辑器区域顶部的选项卡栏中,单击“Signing & Capabilities”。 +3. 在“功能”窗格中,通过单击 iCloud 行中的开关打开 iCloud。您应该会看到开关移动到“打开”位置。 +4. 启用 iCloud 后,您需要启用键值存储。您可以通过选中“键值存储”复选框来执行此操作。 + +### 更新权利: + +1. 您现在需要更新您的权利文件。打开您目标的功能文件。 +2. 确保 iCloud 键值存储值与您的唯一键值存储 ID 匹配。您的唯一 ID 应遵循 `$(TeamIdentifierPrefix)` 的格式。默认值应类似于 `$(TeamIdentifierPrefix)$(CFBundleIdentifier)`。这对于单平台应用程序来说很好,但如果您的应用程序在多个 Apple 操作系统上,则键值存储 ID 部分对于两个目标都相同非常重要。 + +### 配置设备: + +除了配置项目本身之外,您还需要准备将运行该项目的设备。 + +- 确保在 iOS 和 macOS 设备上都启用了 iCloud 云盘。 +- 使用相同的 iCloud 帐户登录两台设备。 + +如果您有任何疑问或遇到任何问题,请随时与我们联系或提交问题。 + +--- +该译文由机器自动生成,可能存在错误。如果您是母语使用者,我们期待您通过 Pull Request 提出修改建议。 diff --git a/documentation/zh-CN/syncstate-implementation.md b/documentation/zh-CN/syncstate-implementation.md new file mode 100644 index 0000000..e2a78a2 --- /dev/null +++ b/documentation/zh-CN/syncstate-implementation.md @@ -0,0 +1,84 @@ +# AppState 中的 SyncState 实现 + +本指南介绍了如何在您的应用程序中设置和配置 SyncState,包括设置 iCloud 功能和了解潜在的限制。 + +## 1. 设置 iCloud 功能 + +要在您的应用程序中使用 SyncState,您首先需要在您的项目中启用 iCloud 并配置键值存储。 + +### 启用 iCloud 和键值存储的步骤: + +1. 打开您的 Xcode 项目并导航到您的项目设置。 +2. 在“Signing & Capabilities”选项卡下,选择您的目标(iOS 或 macOS)。 +3. 单击“+ Capability”按钮,然后从列表中选择“iCloud”。 +4. 在 iCloud 设置下启用“Key-Value storage”选项。这允许您的应用程序使用 iCloud 存储和同步少量数据。 + +### Entitlements 文件配置: + +1. 在您的 Xcode 项目中,找到或创建您应用程序的 **entitlements 文件**。 +2. 确保在 entitlements 文件中正确设置了 iCloud 键值存储,并使用了正确的 iCloud 容器。 + +entitlements 文件中的示例: + +```xml +com.apple.developer.ubiquity-kvstore-identifier +$(TeamIdentifierPrefix)com.yourdomain.app +``` + +确保字符串值与您的项目关联的 iCloud 容器匹配。 + +## 2. 在您的应用程序中使用 SyncState + +启用 iCloud 后,您可以在您的应用程序中使用 `SyncState` 来跨设备同步数据。 + +### SyncState 使用示例: + +```swift +import AppState +import SwiftUI + +extension Application { + var syncValue: SyncState { + syncState(id: "syncValue") + } +} + +struct ContentView: View { + @SyncState(\.syncValue) private var syncValue: Int? + + var body: some View { + VStack { + if let syncValue = syncValue { + Text("SyncValue: \(syncValue)") + } else { + Text("No SyncValue") + } + + Button("Update SyncValue") { + syncValue = Int.random(in: 0..<100) + } + } + } +} +``` + +在此示例中,同步状态将保存到 iCloud 并在登录到同一 iCloud 帐户的设备之间同步。 + +## 3. 限制和最佳实践 + +SyncState 使用 `NSUbiquitousKeyValueStore`,它有一些限制: + +- **存储限制**:SyncState 专为少量数据而设计。总存储限制为 1 MB,每个键值对限制在 1 MB 左右。 +- **同步**:对 SyncState 所做的更改不会立即在设备之间同步。同步可能会有轻微的延迟,并且 iCloud 同步有时可能会受到网络条件的影响。 + +### 最佳实践: + +- **将 SyncState 用于小数据**:确保仅使用 SyncState 同步用户偏好或设置等小数据。 +- **优雅地处理 SyncState 失败**:使用默认值或错误处理机制来解决潜在的同步延迟或失败。 + +## 4. 结论 + +通过正确配置 iCloud 并了解 SyncState 的限制,您可以利用其功能来跨设备同步数据。确保您仅将 SyncState 用于小的、关键的数据片段,以避免 iCloud 存储限制的潜在问题。 + +--- +该译文由机器自动生成,可能存在错误。如果您是母语使用者,我们期待您通过 Pull Request 提出修改建议。 diff --git a/documentation/zh-CN/usage-constant.md b/documentation/zh-CN/usage-constant.md new file mode 100644 index 0000000..a0bd6cf --- /dev/null +++ b/documentation/zh-CN/usage-constant.md @@ -0,0 +1,87 @@ +# 常量用法 + +**AppState** 库中的 `Constant` 提供了对应用程序状态中值的只读访问。它的工作方式类似于 `Slice`,但确保所访问的值是不可变的。这使得 `Constant` 非常适合访问在某些上下文中应保持只读但在其他地方可能是可变的值。 + +## 主要功能 + +- **只读访问**:常量提供对可变状态的访问,但值不能被修改。 +- **作用域限定于应用程序**:与 `Slice` 一样,`Constant` 在 `Application` 扩展中定义,并作用域限定于访问状态的特定部分。 +- **线程安全**:`Constant` 确保在并发环境中安全地访问状态。 + +## 用法示例 + +### 在应用程序中定义常量 + +以下是如何在 `Application` 扩展中定义 `Constant` 以访问只读值: + +```swift +import AppState +import SwiftUI + +struct ExampleValue { + var username: String? + var isLoading: Bool + let value: String + var mutableValue: String +} + +extension Application { + var exampleValue: State { + state( + initial: ExampleValue( + username: "Leif", + isLoading: false, + value: "value", + mutableValue: "" + ) + ) + } +} +``` + +### 在 SwiftUI 视图中访问常量 + +在 SwiftUI 视图中,您可以使用 `@Constant` 属性包装器以只读方式访问常量状态: + +```swift +import AppState +import SwiftUI + +struct ExampleView: View { + @Constant(\.exampleValue, \.value) var constantValue: String + + var body: some View { + Text("常量值: \(constantValue)") + } +} +``` + +### 对可变状态的只读访问 + +即使该值在其他地方是可变的,当通过 `@Constant` 访问时,该值也变为不可变的: + +```swift +import AppState +import SwiftUI + +struct ExampleView: View { + @Constant(\.exampleValue, \.mutableValue) var constantMutableValue: String + + var body: some View { + Text("只读可变值: \(constantMutableValue)") + } +} +``` + +## 最佳实践 + +- **用于只读访问**:使用 `Constant` 访问在某些上下文中不应修改的状态部分,即使它们在其他地方是可变的。 +- **线程安全**:与其他 AppState 组件一样,`Constant` 确保对状态的线程安全访问。 +- **对可选值使用 `OptionalConstant`**:如果您正在访问的状态部分可能为 `nil`,请使用 `OptionalConstant` 来安全地处理值的缺失。 + +## 结论 + +`Constant` 和 `OptionalConstant` 提供了一种以只读方式访问应用程序状态特定部分的有效方法。它们确保在视图中访问时,可能在其他地方是可变的值被视为不可变的,从而确保代码的安全性和清晰性。 + +--- +该译文由机器自动生成,可能存在错误。如果您是母语使用者,我们期待您通过 Pull Request 提出修改建议。 diff --git a/documentation/zh-CN/usage-filestate.md b/documentation/zh-CN/usage-filestate.md new file mode 100644 index 0000000..0dc14e0 --- /dev/null +++ b/documentation/zh-CN/usage-filestate.md @@ -0,0 +1,96 @@ +# FileState 用法 + +`FileState` 是 **AppState** 库的一个组件,允许您使用文件系统存储和检索持久性数据。它对于存储需要在应用程序启动之间保存并在需要时恢复的大型数据或复杂对象非常有用。 + +## 主要功能 + +- **持久性存储**:使用 `FileState` 存储的数据在应用程序启动之间保持持久。 +- **大型数据处理**:与 `StoredState` 不同,`FileState` 非常适合处理较大或更复杂的数据。 +- **线程安全**:与其他 AppState 组件一样,`FileState` 确保在并发环境中安全地访问数据。 + +## 用法示例 + +### 使用 FileState 存储和检索数据 + +以下是如何在 `Application` 扩展中定义 `FileState` 以存储和检索大型对象: + +```swift +import AppState +import SwiftUI + +struct UserProfile: Codable { + var name: String + var age: Int +} + +extension Application { + @MainActor + var userProfile: FileState { + fileState(initial: UserProfile(name: "Guest", age: 25), filename: "userProfile") + } +} + +struct FileStateExampleView: View { + @FileState(\.userProfile) var userProfile: UserProfile + + var body: some View { + VStack { + Text("姓名: \(userProfile.name), 年龄: \(userProfile.age)") + Button("更新个人资料") { + userProfile = UserProfile(name: "UpdatedName", age: 30) + } + } + } +} +``` + +### 使用 FileState 处理大型数据 + +当您需要处理较大数据集或对象时,`FileState` 可确保数据高效地存储在应用程序的文件系统中。这对于缓存或离线存储等场景非常有用。 + +```swift +import AppState +import SwiftUI + +extension Application { + @MainActor + var largeDataset: FileState<[String]> { + fileState(initial: [], filename: "largeDataset") + } +} + +struct LargeDataView: View { + @FileState(\.largeDataset) var largeDataset: [String] + + var body: some View { + List(largeDataset, id: \.self) { item in + Text(item) + } + } +} +``` + +### 迁移注意事项 + +在更新数据模型时,考虑潜在的迁移挑战非常重要,尤其是在使用 **StoredState**、**FileState** 或 **SyncState** 处理持久化数据时。如果没有适当的迁移处理,添加新字段或修改数据格式等更改可能会在加载旧数据时导致问题。 + +以下是一些需要牢记的关键点: +- **添加新的非可选字段**:确保新字段是可选的或具有默认值,以保持向后兼容性。 +- **处理数据格式更改**:如果模型的结构发生变化,请实现自定义解码逻辑以支持旧格式。 +- **版本化您的模型**:在您的模型中使用 `version` 字段以帮助进行迁移,并根据数据版本应用逻辑。 + +要了解有关如何管理迁移和避免潜在问题的更多信息,请参阅[迁移注意事项指南](migration-considerations.md)。 + + +## 最佳实践 + +- **用于大型或复杂数据**:如果要存储大型数据或复杂对象,`FileState` 优于 `StoredState`。 +- **线程安全访问**:与 **AppState** 的其他组件一样,`FileState` 确保即使在多个任务与存储的数据交互时也能安全地访问数据。 +- **与 Codable 结合使用**:在使用自定义数据类型时,请确保它们符合 `Codable`,以简化与文件系统的编码和解码。 + +## 结论 + +`FileState` 是在您的应用程序中处理持久性数据的强大工具,允许您以线程安全和持久的方式存储和检索较大或更复杂的对象。它与 Swift 的 `Codable` 协议无缝协作,确保您的数据可以轻松地序列化和反序列化以进行长期存储。 + +--- +该译文由机器自动生成,可能存在错误。如果您是母语使用者,我们期待您通过 Pull Request 提出修改建议。 diff --git a/documentation/zh-CN/usage-observeddependency.md b/documentation/zh-CN/usage-observeddependency.md new file mode 100644 index 0000000..528b6f3 --- /dev/null +++ b/documentation/zh-CN/usage-observeddependency.md @@ -0,0 +1,135 @@ +# ObservedDependency 用法 + +`ObservedDependency` 是 **AppState** 库的一个组件,允许您使用符合 `ObservableObject` 的依赖项。当您希望依赖项通知您的 SwiftUI 视图有关更改时,这非常有用,使您的视图具有反应性和动态性。 + +## 主要功能 + +- **可观察的依赖项**:使用符合 `ObservableObject` 的依赖项,允许依赖项在其状态更改时自动更新您的视图。 +- **反应式 UI 更新**:当观察到的依赖项发布更改时,SwiftUI 视图会自动更新。 +- **线程安全**:与其他 AppState 组件一样,`ObservedDependency` 确保对观察到的依赖项进行线程安全的访问。 + +## 用法示例 + +### 定义可观察的依赖项 + +以下是如何在 `Application` 扩展中将可观察的服务定义为依赖项: + +```swift +import AppState +import SwiftUI + +@MainActor +class ObservableService: ObservableObject { + @Published var count: Int = 0 +} + +extension Application { + @MainActor + var observableService: Dependency { + dependency(ObservableService()) + } +} +``` + +### 在 SwiftUI 视图中使用观察到的依赖项 + +在您的 SwiftUI 视图中,您可以使用 `@ObservedDependency` 属性包装器访问可观察的依赖项。观察到的对象在其状态更改时会自动更新视图。 + +```swift +import AppState +import SwiftUI + +struct ObservedDependencyExampleView: View { + @ObservedDependency(\.observableService) var service: ObservableService + + var body: some View { + VStack { + Text("计数: \(service.count)") + Button("增加计数") { + service.count += 1 + } + } + } +} +``` + +### 测试用例 + +以下测试用例演示了与 `ObservedDependency` 的交互: + +```swift +import XCTest +@testable import AppState + +@MainActor +fileprivate class ObservableService: ObservableObject { + @Published var count: Int + + init() { + count = 0 + } +} + +fileprivate extension Application { + @MainActor + var observableService: Dependency { + dependency(ObservableService()) + } +} + +@MainActor +fileprivate struct ExampleDependencyWrapper { + @ObservedDependency(\.observableService) var service + + func test() { + service.count += 1 + } +} + +final class ObservedDependencyTests: XCTestCase { + @MainActor + func testDependency() async { + let example = ExampleDependencyWrapper() + + XCTAssertEqual(example.service.count, 0) + + example.test() + + XCTAssertEqual(example.service.count, 1) + } +} +``` + +### 反应式 UI 更新 + +由于依赖项符合 `ObservableObject`,因此对其状态的任何更改都将触发 SwiftUI 视图中的 UI 更新。您可以将状态直接绑定到 UI 元素,例如 `Picker`: + +```swift +import AppState +import SwiftUI + +struct ReactiveView: View { + @ObservedDependency(\.observableService) var service: ObservableService + + var body: some View { + Picker("选择计数", selection: $service.count) { + ForEach(0..<10) { count in + Text("\(count)").tag(count) + } + } + } +} +``` + +## 最佳实践 + +- **用于可观察的服务**:当您的依赖项需要通知视图有关更改时,`ObservedDependency` 是理想的选择,特别是对于提供数据或状态更新的服务。 +- **利用已发布的属性**:确保您的依赖项使用 `@Published` 属性来触发 SwiftUI 视图中的更新。 +- **线程安全**:与其他 AppState 组件一样,`ObservedDependency` 确保对可观察服务的线程安全访问和修改。 + +## 结论 + +`ObservedDependency` 是在您的应用程序中管理可观察依赖项的强大工具。通过利用 Swift 的 `ObservableObject` 协议,它确保您的 SwiftUI 视图保持反应性并与服务或资源中的更改保持同步。 + +--- +该译文由机器自动生成,可能存在错误。如果您是母语使用者,我们期待您通过 Pull Request 提出修改建议。 diff --git a/documentation/zh-CN/usage-overview.md b/documentation/zh-CN/usage-overview.md new file mode 100644 index 0000000..c2a7204 --- /dev/null +++ b/documentation/zh-CN/usage-overview.md @@ -0,0 +1,215 @@ +# 用法概述 + +本概述简要介绍了如何在 SwiftUI `View` 中使用 **AppState** 库的关键组件。每个部分都包含适合 SwiftUI 视图结构范围的简单示例。 + +## 在 Application 扩展中定义值 + +要定义应用程序范围的状态或依赖项,您应该扩展 `Application` 对象。这使您可以将应用程序的所有状态集中在一个地方。以下是如何扩展 `Application` 以创建各种状态和依赖项的示例: + +```swift +import AppState + +extension Application { + var user: State { + state(initial: User(name: "Guest", isLoggedIn: false)) + } + + var userPreferences: StoredState { + storedState(initial: "Default Preferences", id: "userPreferences") + } + + var darkModeEnabled: SyncState { + syncState(initial: false, id: "darkModeEnabled") + } + + var userToken: SecureState { + secureState(id: "userToken") + } + + @MainActor + var largeDataset: FileState<[String]> { + fileState(initial: [], filename: "largeDataset") + } +} +``` + +## State + +`State` 允许您定义可在应用程序中任何位置访问和修改的应用程序范围状态。 + +### 示例 + +```swift +import AppState +import SwiftUI + +struct ContentView: View { + @AppState(\.user) var user: User + + var body: some View { + VStack { + Text("你好, \(user.name)!") + Button("登录") { + user.isLoggedIn.toggle() + } + } + } +} +``` + +## StoredState + +`StoredState` 使用 `UserDefaults` 持久化状态,以确保值在应用程序启动之间被保存。 + +### 示例 + +```swift +import AppState +import SwiftUI + +struct PreferencesView: View { + @StoredState(\.userPreferences) var userPreferences: String + + var body: some View { + VStack { + Text("偏好设置: \(userPreferences)") + Button("更新偏好设置") { + userPreferences = "Updated Preferences" + } + } + } +} +``` + +## SyncState + +`SyncState` 使用 iCloud 在多个设备之间同步应用程序状态。 + +### 示例 + +```swift +import AppState +import SwiftUI + +struct SyncSettingsView: View { + @SyncState(\.darkModeEnabled) var isDarkModeEnabled: Bool + + var body: some View { + VStack { + Toggle("深色模式", isOn: $isDarkModeEnabled) + } + } +} +``` + +## FileState + +`FileState` 用于使用文件系统持久地存储较大或更复杂的数据,使其非常适合缓存或保存不适合 `UserDefaults` 限制的数据。 + +### 示例 + +```swift +import AppState +import SwiftUI + +struct LargeDataView: View { + @FileState(\.largeDataset) var largeDataset: [String] + + var body: some View { + List(largeDataset, id: \.self) { item in + Text(item) + } + } +} +``` + +## SecureState + +`SecureState` 将敏感数据安全地存储在钥匙串中。 + +### 示例 + +```swift +import AppState +import SwiftUI + +struct SecureView: View { + @SecureState(\.userToken) var userToken: String? + + var body: some View { + VStack { + if let token = userToken { + Text("用户令牌: \(token)") + } else { + Text("未找到令牌。") + } + Button("设置令牌") { + userToken = "secure_token_value" + } + } + } +} +``` + +## Constant + +`Constant` 提供对应用程序状态中值的不可变、只读访问,确保在访问不应修改的值时的安全性。 + +### 示例 + +```swift +import AppState +import SwiftUI + +struct ExampleView: View { + @Constant(\.user, \.name) var name: String + + var body: some View { + Text("用户名: \(name)") + } +} +``` + +## Slicing State + +`Slice` 和 `OptionalSlice` 允许您访问应用程序状态的特定部分。 + +### 示例 + +```swift +import AppState +import SwiftUI + +struct SlicingView: View { + @Slice(\.user, \.name) var name: String + + var body: some View { + VStack { + Text("用户名: \(name)") + Button("更新用户名") { + name = "NewUsername" + } + } + } +} +``` + +## 最佳实践 + +- **在 SwiftUI 视图中使用 `AppState`**:`@AppState`、`@StoredState`、`@FileState`、`@SecureState` 等属性包装器设计用于 SwiftUI 视图的范围内。 +- **在 Application 扩展中定义状态**:通过扩展 `Application` 来定义应用程序的状态和依赖项,从而集中管理状态。 +- **反应式更新**:当状态更改时,SwiftUI 会自动更新视图,因此您无需手动刷新 UI。 +- **[最佳实践指南](best-practices.md)**:有关使用 AppState 时的最佳实践的详细分类。 + +## 后续步骤 + +熟悉基本用法后,您可以探索更高级的主题: + +- 在[FileState 用法指南](usage-filestate.md)中探索使用 **FileState** 将大量数据持久化到文件中。 +- 在[常量用法指南](usage-constant.md)中了解 **常量** 以及如何在应用程序状态中使用它们来表示不可变值。 +- 在[状态依赖用法指南](usage-state-dependency.md)中研究 **Dependency** 如何在 AppState 中用于处理共享服务,并查看示例。 +- 在[ObservedDependency 用法指南](usage-observeddependency.md)中更深入地研究 **高级 SwiftUI** 技术,例如使用 `ObservedDependency` 在视图中管理可观察的依赖项。 +- 有关更高级的用法技术,例如即时创建和预加载依赖项,请参阅[高级用法指南](advanced-usage.md)。 + +--- +该译文由机器自动生成,可能存在错误。如果您是母语使用者,我们期待您通过 Pull Request 提出修改建议。 diff --git a/documentation/zh-CN/usage-securestate.md b/documentation/zh-CN/usage-securestate.md new file mode 100644 index 0000000..bfc19a3 --- /dev/null +++ b/documentation/zh-CN/usage-securestate.md @@ -0,0 +1,68 @@ +# SecureState 用法 + +`SecureState` 是 **AppState** 库的一个组件,允许您将敏感数据安全地存储在钥匙串中。它最适合存储需要安全加密的小块数据,例如令牌或密码。 + +## 主要功能 + +- **安全存储**:使用 `SecureState` 存储的数据经过加密并安全地保存在钥匙串中。 +- **持久性**:数据在应用程序启动之间保持持久,允许安全地检索敏感值。 + +## 钥匙串限制 + +虽然 `SecureState` 非常安全,但它有一定的限制: + +- **有限的存储大小**:钥匙串专为小块数据而设计。它不适合存储大文件或数据集。 +- **性能**:访问钥匙串比访问 `UserDefaults` 慢,因此仅在需要安全存储敏感数据时才使用它。 + +## 用法示例 + +### 存储安全令牌 + +```swift +import AppState +import SwiftUI + +extension Application { + var userToken: SecureState { + secureState(id: "userToken") + } +} + +struct SecureView: View { + @SecureState(\.userToken) var userToken: String? + + var body: some View { + VStack { + if let token = userToken { + Text("用户令牌: \(token)") + } else { + Text("未找到令牌。") + } + Button("设置令牌") { + userToken = "secure_token_value" + } + } + } +} +``` + +### 处理安全数据缺失的情况 + +首次访问钥匙串时,或者如果没有存储任何值,`SecureState` 将返回 `nil`。确保您正确处理这种情况: + +```swift +if let token = userToken { + print("令牌: \(token)") +} else { + print("没有可用的令牌。") +} +``` + +## 最佳实践 + +- **用于小数据**:钥匙串应用于存储小块敏感信息,如令牌、密码和密钥。 +- **避免大数据集**:如果您需要安全地存储大数据集,请考虑使用基于文件的加密或其他方法,因为钥匙串不是为大数据存储而设计的。 +- **处理 nil**:始终处理钥匙串在没有值时返回 `nil` 的情况。 + +--- +该译文由机器自动生成,可能存在错误。如果您是母语使用者,我们期待您通过 Pull Request 提出修改建议。 diff --git a/documentation/zh-CN/usage-slice.md b/documentation/zh-CN/usage-slice.md new file mode 100644 index 0000000..68e1b45 --- /dev/null +++ b/documentation/zh-CN/usage-slice.md @@ -0,0 +1,94 @@ +# Slice 和 OptionalSlice 用法 + +`Slice` 和 `OptionalSlice` 是 **AppState** 库的组件,允许您访问应用程序状态的特定部分。当您需要操作或观察更复杂状态结构的一部分时,它们非常有用。 + +## 概述 + +- **Slice**:允许您访问和修改现有 `State` 对象的特定部分。 +- **OptionalSlice**:与 `Slice` 类似,但旨在处理可选值,例如当您的状态的一部分可能为 `nil` 或不为 `nil` 时。 + +### 主要功能 + +- **选择性状态访问**:仅访问您需要的状态部分。 +- **线程安全**:与 **AppState** 中的其他状态管理类型一样,`Slice` 和 `OptionalSlice` 是线程安全的。 +- **反应性**:当状态的切片发生变化时,SwiftUI 视图会更新,确保您的 UI 保持反应性。 + +## 用法示例 + +### 使用 Slice + +在此示例中,我们使用 `Slice` 访问和更新状态的特定部分——在本例中,是从存储在应用程序状态中的更复杂的 `User` 对象中获取 `username`。 + +```swift +import AppState +import SwiftUI + +struct User { + var username: String + var email: String +} + +extension Application { + var user: State { + state(initial: User(username: "Guest", email: "guest@example.com")) + } +} + +struct SlicingView: View { + @Slice(\.user, \.username) var username: String + + var body: some View { + VStack { + Text("用户名: \(username)") + Button("更新用户名") { + username = "NewUsername" + } + } + } +} +``` + +### 使用 OptionalSlice + +当您的状态的一部分可能为 `nil` 时,`OptionalSlice` 非常有用。在此示例中,`User` 对象本身可能为 `nil`,因此我们使用 `OptionalSlice` 来安全地处理这种情况。 + +```swift +import AppState +import SwiftUI + +extension Application { + var user: State { + state(initial: nil) + } +} + +struct OptionalSlicingView: View { + @OptionalSlice(\.user, \.username) var username: String? + + var body: some View { + VStack { + if let username = username { + Text("用户名: \(username)") + } else { + Text("没有可用的用户名") + } + Button("设置用户名") { + username = "UpdatedUsername" + } + } + } +} +``` + +## 最佳实践 + +- **对非可选状态使用 `Slice`**:如果您的状态保证为非可选,请使用 `Slice` 访问和更新它。 +- **对可选状态使用 `OptionalSlice`**:如果您的状态或状态的一部分是可选的,请使用 `OptionalSlice` 处理值可能为 `nil` 的情况。 +- **线程安全**:与 `State` 一样,`Slice` 和 `OptionalSlice` 是线程安全的,并且设计用于与 Swift 的并发模型一起工作。 + +## 结论 + +`Slice` 和 `OptionalSlice` 提供了以线程安全的方式访问和修改状态特定部分的强大方法。通过利用这些组件,您可以在更复杂的应用程序中简化状态管理,确保您的 UI 保持反应性和最新。 + +--- +该译文由机器自动生成,可能存在错误。如果您是母语使用者,我们期待您通过 Pull Request 提出修改建议。 diff --git a/documentation/zh-CN/usage-state-dependency.md b/documentation/zh-CN/usage-state-dependency.md new file mode 100644 index 0000000..a473c36 --- /dev/null +++ b/documentation/zh-CN/usage-state-dependency.md @@ -0,0 +1,136 @@ +# 状态和依赖用法 + +**AppState** 提供了强大的工具,用于管理应用程序范围的状态并将依赖项注入到 SwiftUI 视图中。通过集中管理您的状态和依赖项,您可以确保您的应用程序保持一致和可维护。 + +## 概述 + +- **状态**:表示可在整个应用程序中共享的值。可以在您的 SwiftUI 视图中修改和观察状态值。 +- **依赖项**:表示可在 SwiftUI 视图中注入和访问的共享资源或服务。 + +### 主要功能 + +- **集中式状态**:在一个地方定义和管理应用程序范围的状态。 +- **依赖注入**:在应用程序的不同组件之间注入和访问共享服务和资源。 + +## 用法示例 + +### 定义应用程序状态 + +要定义应用程序范围的状态,请扩展 `Application` 对象并声明状态属性。 + +```swift +import AppState + +struct User { + var name: String + var isLoggedIn: Bool +} + +extension Application { + var user: State { + state(initial: User(name: "Guest", isLoggedIn: false)) + } +} +``` + +### 在视图中访问和修改状态 + +您可以使用 `@AppState` 属性包装器直接在 SwiftUI 视图中访问和修改状态值。 + +```swift +import AppState +import SwiftUI + +struct ContentView: View { + @AppState(\.user) var user: User + + var body: some View { + VStack { + Text("你好, \(user.name)!") + Button("登录") { + user.name = "John Doe" + user.isLoggedIn = true + } + } + } +} +``` + +### 定义依赖项 + +您可以将共享资源(例如网络服务)定义为 `Application` 对象中的依赖项。这些依赖项可以注入到 SwiftUI 视图中。 + +```swift +import AppState + +protocol NetworkServiceType { + func fetchData() -> String +} + +class NetworkService: NetworkServiceType { + func fetchData() -> String { + return "Data from network" + } +} + +extension Application { + var networkService: Dependency { + dependency(NetworkService()) + } +} +``` + +### 在视图中访问依赖项 + +使用 `@AppDependency` 属性包装器在 SwiftUI 视图中访问依赖项。这允许您将网络服务等服务注入到您的视图中。 + +```swift +import AppState +import SwiftUI + +struct NetworkView: View { + @AppDependency(\.networkService) var networkService: NetworkServiceType + + var body: some View { + VStack { + Text("数据: \(networkService.fetchData())") + } + } +} +``` + +### 在视图中结合状态和依赖项 + +状态和依赖项可以协同工作,构建更复杂的应用程序逻辑。例如,您可以从服务中获取数据并更新状态: + +```swift +import AppState +import SwiftUI + +struct CombinedView: View { + @AppState(\.user) var user: User + @AppDependency(\.networkService) var networkService: NetworkServiceType + + var body: some View { + VStack { + Text("用户: \(user.name)") + Button("获取数据") { + user.name = networkService.fetchData() + user.isLoggedIn = true + } + } + } +} +``` + +### 最佳实践 + +- **集中管理状态**:将您的应用程序范围的状态放在一个地方,以避免重复并确保一致性。 +- **对共享服务使用依赖项**:注入网络服务、数据库或其他共享资源等依赖项,以避免组件之间的紧密耦合。 + +## 结论 + +使用 **AppState**,您可以管理应用程序范围的状态,并将共享依赖项直接注入到您的 SwiftUI 视图中。这种模式有助于保持您的应用程序模块化和可维护性。探索 **AppState** 库的其他功能,例如 [SecureState](usage-securestate.md) 和 [SyncState](usage-syncstate.md),以进一步增强您的应用程序的状态管理。 + +--- +该译文由机器自动生成,可能存在错误。如果您是母语使用者,我们期待您通过 Pull Request 提出修改建议。 diff --git a/documentation/zh-CN/usage-storedstate.md b/documentation/zh-CN/usage-storedstate.md new file mode 100644 index 0000000..2588dab --- /dev/null +++ b/documentation/zh-CN/usage-storedstate.md @@ -0,0 +1,75 @@ +# StoredState 用法 + +`StoredState` 是 **AppState** 库的一个组件,允许您使用 `UserDefaults` 存储和持久化少量数据。它非常适合存储需要在应用程序启动之间持久化的轻量级、非敏感数据。 + +## 概述 + +- **StoredState** 构建在 `UserDefaults` 之上,这意味着它对于存储少量数据(例如用户偏好或应用程序设置)来说是快速高效的。 +- 保存在 **StoredState** 中的数据在应用程序会话之间保持持久,允许您在启动时恢复应用程序状态。 + +### 主要功能 + +- **持久性存储**:保存在 `StoredState` 中的数据在应用程序启动之间保持可用。 +- **小数据处理**:最适合用于轻量级数据,如偏好、切换开关或小型配置。 +- **线程安全**:`StoredState` 确保在并发环境中数据访问保持安全。 + +## 用法示例 + +### 定义 StoredState + +您可以通过扩展 `Application` 对象并声明状态属性来定义 **StoredState**: + +```swift +import AppState + +extension Application { + var userPreferences: StoredState { + storedState(initial: "Default Preferences", id: "userPreferences") + } +} +``` + +### 在视图中访问和修改 StoredState + +您可以使用 `@StoredState` 属性包装器在 SwiftUI 视图中访问和修改 **StoredState** 值: + +```swift +import AppState +import SwiftUI + +struct PreferencesView: View { + @StoredState(\.userPreferences) var userPreferences: String + + var body: some View { + VStack { + Text("偏好设置: \(userPreferences)") + Button("更新偏好设置") { + userPreferences = "Updated Preferences" + } + } + } +} +``` + +## 处理数据迁移 + +随着您的应用程序的发展,您可能会更新通过 **StoredState** 持久化的模型。在更新数据模型时,请确保向后兼容性。例如,您可能需要添加新字段或对模型进行版本控制以处理迁移。 + +有关更多信息,请参阅[迁移注意事项指南](migration-considerations.md)。 + +### 迁移注意事项 + +- **添加新的非可选字段**:确保新字段是可选的或具有默认值,以保持向后兼容性。 +- **版本化模型**:如果您的数据模型随时间变化,请包含一个 `version` 字段来管理持久化数据的不同版本。 + +## 最佳实践 + +- **用于小数据**:存储需要在应用程序启动之间持久化的轻量级、非敏感数据,例如用户偏好。 +- **考虑大数据的替代方案**:如果您需要存储大量数据,请考虑改用 **FileState**。 + +## 结论 + +**StoredState** 是使用 `UserDefaults` 持久化小块数据的简单有效的方法。它非常适合在应用程序启动之间保存偏好和其他小型设置,同时提供安全的访问和与 SwiftUI 的轻松集成。对于更复杂的持久化需求,请探索 **AppState** 的其他功能,例如 [FileState](usage-filestate.md) 或 [SyncState](usage-syncstate.md)。 + +--- +这是使用 [Jules](https://jules.google) 生成的,可能会出现错误。如果您是母语人士,请提出包含任何应有修复的拉取请求。 diff --git a/documentation/zh-CN/usage-syncstate.md b/documentation/zh-CN/usage-syncstate.md new file mode 100644 index 0000000..2f3c7a4 --- /dev/null +++ b/documentation/zh-CN/usage-syncstate.md @@ -0,0 +1,159 @@ +# SyncState 用法 + +`SyncState` 是 **AppState** 库的一个组件,允许您使用 iCloud 在多个设备之间同步应用程序状态。这对于在设备之间保持用户偏好、设置或其他重要数据的一致性特别有用。 + +## 概述 + +`SyncState` 利用 iCloud 的 `NSUbiquitousKeyValueStore` 在设备之间保持少量数据的同步。这使其非常适合同步轻量级应用程序状态,例如偏好或用户设置。 + +### 主要功能 + +- **iCloud 同步**:在登录到同一 iCloud 帐户的所有设备之间自动同步状态。 +- **持久性存储**:数据持久地存储在 iCloud 中,这意味着即使应用程序终止或重新启动,它也会持久存在。 +- **近乎实时的同步**:对状态的更改几乎可以立即传播到其他设备。 + +> **注意**:`SyncState` 在 watchOS 9.0 及更高版本上受支持。 + +## 用法示例 + +### 数据模型 + +假设我们有一个名为 `Settings` 的结构体,它符合 `Codable`: + +```swift +struct Settings: Codable { + var text: String + var isShowingSheet: Bool + var isDarkMode: Bool +} +``` + +### 定义 SyncState + +您可以通过扩展 `Application` 对象并声明应同步的状态属性来定义 `SyncState`: + +```swift +extension Application { + var settings: SyncState { + syncState( + initial: Settings( + text: "Hello, World!", + isShowingSheet: false, + isDarkMode: false + ), + id: "settings" + ) + } +} +``` + +### 处理外部更改 + +为确保应用程序响应来自 iCloud 的外部更改,请通过创建自定义 `Application` 子类来覆盖 `didChangeExternally` 函数: + +```swift +class CustomApplication: Application { + override func didChangeExternally(notification: Notification) { + super.didChangeExternally(notification: notification) + + DispatchQueue.main.async { + self.objectWillChange.send() + } + } +} +``` + +### 创建视图以修改和同步状态 + +在以下示例中,我们有两个视图:`ContentView` 和 `ContentViewInnerView`。这些视图在它们之间共享和同步 `Settings` 状态。`ContentView` 允许用户修改 `text` 和切换 `isDarkMode`,而 `ContentViewInnerView` 显示相同的文本并在点击时更新它。 + +```swift +struct ContentView: View { + @SyncState(\.settings) private var settings: Settings + + var body: some View { + VStack { + TextField("", text: $settings.text) + + Button(settings.isDarkMode ? "Light" : "Dark") { + settings.isDarkMode.toggle() + } + + Button("Show") { settings.isShowingSheet = true } + } + .preferredColorScheme(settings.isDarkMode ? .dark : .light) + .sheet(isPresented: $settings.isShowingSheet, content: ContentViewInnerView.init) + } +} + +struct ContentViewInnerView: View { + @Slice(\.settings, \.text) private var text: String + + var body: some View { + Text("\(text)") + .onTapGesture { + text = Date().formatted() + } + } +} +``` + +### 设置应用程序 + +最后,在 `@main` 结构体中设置应用程序。在初始化中,提升自定义应用程序,启用日志记录,并加载用于同步的 iCloud 存储依赖项: + +```swift +@main +struct SyncStateExampleApp: App { + init() { + Application + .promote(to: CustomApplication.self) + .logging(isEnabled: true) + .load(dependency: \.icloudStore) + } + + var body: some Scene { + WindowGroup { + ContentView() + } + } +} +``` + +### 启用 iCloud 键值存储 + +要启用 iCloud 同步,请确保您按照本指南启用 iCloud 键值存储功能:[开始使用 SyncState](starting-to-use-syncstate.md)。 + +### SyncState:关于 iCloud 存储的说明 + +虽然 `SyncState` 可以轻松同步,但请务必记住 `NSUbiquitousKeyValueStore` 的限制: + +- **存储限制**:您可以使用 `NSUbiquitousKeyValueStore` 在 iCloud 中存储最多 1 MB 的数据,每个键值对的大小限制为 1 MB。 + +### 迁移注意事项 + +在更新数据模型时,考虑潜在的迁移挑战非常重要,尤其是在使用 **StoredState**、**FileState** 或 **SyncState** 处理持久化数据时。如果没有适当的迁移处理,添加新字段或修改数据格式等更改可能会在加载旧数据时导致问题。 + +以下是一些需要牢记的关键点: +- **添加新的非可选字段**:确保新字段是可选的或具有默认值,以保持向后兼容性。 +- **处理数据格式更改**:如果模型的结构发生变化,请实现自定义解码逻辑以支持旧格式。 +- **版本化您的模型**:在您的模型中使用 `version` 字段以帮助进行迁移,并根据数据版本应用逻辑。 + +要了解有关如何管理迁移和避免潜在问题的更多信息,请参阅[迁移注意事项指南](migration-considerations.md)。 + +## SyncState 实现指南 + +有关如何配置 iCloud 并在您的项目中设置 SyncState 的详细说明,请参阅[SyncState 实现指南](syncstate-implementation.md)。 + +## 最佳实践 + +- **用于小的、关键的数据**:`SyncState` 非常适合同步小的、重要的状态片段,例如用户偏好、设置或功能标志。 +- **监控 iCloud 存储**:确保您对 `SyncState` 的使用保持在 iCloud 存储限制内,以防止数据同步问题。 +- **处理外部更新**:如果您的应用程序需要响应在另一台设备上发起的状态更改,请覆盖 `didChangeExternally` 函数以实时更新应用程序的状态。 + +## 结论 + +`SyncState` 提供了一种通过 iCloud 在设备之间同步少量应用程序状态的强大方法。它非常适合确保用户偏好和其他关键数据在登录到同一 iCloud 帐户的所有设备上保持一致。对于更高级的用例,请探索 **AppState** 的其他功能,例如 [SecureState](usage-securestate.md) 和 [FileState](usage-filestate.md)。 + +--- +这是使用 [Jules](https://jules.google) 生成的,可能会出现错误。如果您是母语人士,请提出包含任何应有修复的拉取请求。