{"id":23173283,"url":"https://github.com/pointfreeco/swift-sharing","last_synced_at":"2025-05-15T11:08:46.030Z","repository":{"id":265778453,"uuid":"879961354","full_name":"pointfreeco/swift-sharing","owner":"pointfreeco","description":"A universal solution to persistence and data sharing in surprisingly little code.","archived":false,"fork":false,"pushed_at":"2025-05-07T22:27:16.000Z","size":287,"stargazers_count":615,"open_issues_count":4,"forks_count":46,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-05-07T23:27:30.219Z","etag":null,"topics":["appstorage","filestorage","persistence","swiftui","userdefaults"],"latest_commit_sha":null,"homepage":"https://www.pointfree.co","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pointfreeco.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":".github/CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2024-10-28T21:29:37.000Z","updated_at":"2025-05-07T22:27:20.000Z","dependencies_parsed_at":"2025-01-23T23:21:43.692Z","dependency_job_id":"32693e1e-76db-4dad-b183-b6e959ec6fbe","html_url":"https://github.com/pointfreeco/swift-sharing","commit_stats":null,"previous_names":["pointfreeco/swift-sharing"],"tags_count":30,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pointfreeco%2Fswift-sharing","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pointfreeco%2Fswift-sharing/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pointfreeco%2Fswift-sharing/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pointfreeco%2Fswift-sharing/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pointfreeco","download_url":"https://codeload.github.com/pointfreeco/swift-sharing/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254328385,"owners_count":22052632,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["appstorage","filestorage","persistence","swiftui","userdefaults"],"created_at":"2024-12-18T05:01:58.116Z","updated_at":"2025-05-15T11:08:46.005Z","avatar_url":"https://github.com/pointfreeco.png","language":"Swift","funding_links":[],"categories":["Swift"],"sub_categories":[],"readme":"# Sharing\n\nInstantly share state among your app's features and external persistence layers, including user\ndefaults, the file system, and more.\n\n[![CI](https://github.com/pointfreeco/swift-sharing/workflows/CI/badge.svg)](https://github.com/pointfreeco/swift-sharing/actions?query=workflow%3ACI)\n[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fpointfreeco%2Fswift-sharing%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/pointfreeco/swift-sharing)\n[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fpointfreeco%2Fswift-sharing%2Fbadge%3Ftype%3Dplatforms)](https://swiftpackageindex.com/pointfreeco/swift-sharing)\n\n  * [Learn more](#learn-more)\n  * [Overview](#overview)\n  * [Demos](#demos)\n  * [Documentation](#documentation)\n  * [Installation](#installation)\n  * [Community](#community)\n  * [License](#license)\n\n## Learn more\n\nThis library was motivated and designed over the course of many episodes on\n[Point-Free](https://www.pointfree.co), a video series exploring advanced programming topics in the\nSwift language, hosted by [Brandon Williams](https://twitter.com/mbrandonw) and [Stephen\nCelis](https://twitter.com/stephencelis).\n\n\u003ca href=\"https://www.pointfree.co/collections/tours/tour-of-swift-sharing\"\u003e\n  \u003cimg alt=\"video poster image\" src=\"https://d3rccdn33rt8ze.cloudfront.net/episodes/0305.jpeg\" width=\"600\"\u003e\n\u003c/a\u003e\n\n## Overview\n\nThis library comes with a few tools that allow one to share state with multiple parts of your\napplication, as well as external systems such as user defaults, the file system, and more. The tool\nworks in a variety of contexts, such as SwiftUI views, `@Observable` models, and UIKit view\ncontrollers, and it is completely unit testable.\n\nAs a simple example, you can have two different observable models hold onto a collection of data\nthat is also synchronized to the file system:\n\n```swift\n// MeetingsList.swift\n@Observable\nclass MeetingsListModel {\n  @ObservationIgnored\n  @Shared(.fileStorage(.meetingsURL)) var meetings: [Meeting] = []\n}\n\n// ArchivedMeetings.swift\n@Observable\nclass ArchivedMeetingsModel {\n  @ObservationIgnored\n  @Shared(.fileStorage(.meetingsURL)) var meetings: [Meeting] = []\n}\n```\n\n\u003e [!NOTE]\n\u003e Due to the fact that Swift macros do not play nicely with property wrappers, you must annotate\n\u003e each `@Shared` held by an `@Observable` model with `@ObservationIgnored`. Views will still update\n\u003e when shared state changes since `@Shared` handles its own observation.\n\nIf either model makes a change to `meetings`, the other model will instantly see those changes.\nAnd further, if the file on disk changes from an external write, both instances of `@Shared` will\nalso update to hold the freshest data.\n\n### Automatic persistence\n\nThe [`@Shared`][shared-article] property wrapper gives you a succinct and consistent way to persist\nany kind of data in your application. The library comes with 3 strategies:\n[`appStorage`][app-storage-key-docs],\n[`fileStorage`][file-storage-key-docs], and\n[`inMemory`][in-memory-key-docs].\n\n[shared-article]: https://swiftpackageindex.com/pointfreeco/swift-sharing/main/documentation/sharing/shared\n[app-storage-key-docs]: https://swiftpackageindex.com/pointfreeco/swift-sharing/main/documentation/sharing/appstoragekey\n[file-storage-key-docs]: https://swiftpackageindex.com/pointfreeco/swift-sharing/main/documentation/sharing/filestoragekey\n[in-memory-key-docs]: https://swiftpackageindex.com/pointfreeco/swift-sharing/main/documentation/sharing/inmemorykey\n\nThe [`appStorage`][app-storage-key-docs] strategy is useful for store small pieces of simple data\nin user defaults, such as settings:\n\n```swift\n@Shared(.appStorage(\"soundsOn\")) var soundsOn = true\n@Shared(.appStorage(\"hapticsOn\")) var hapticsOn = true\n@Shared(.appStorage(\"userSort\")) var userSort = UserSort.name\n```\n\nThe [`fileStorage`][file-storage-key-docs] strategy is useful for persisting more complex data\ntypes to the file system by serializing the data to bytes:\n\n```swift\n@Shared(.fileStorage(.meetingsURL)) var meetings: [Meeting] = []\n```\n\nAnd the [`inMemory`][in-memory-key-docs] strategy is useful for sharing any kind of data globally\nwith the entire app, but it will be reset the next time the app is relaunched:\n\n```swift\n@Shared(.inMemory(\"events\")) var events: [String] = []\n```\n\nSee [\"Persistence strategies\"][persistence-docs] for more information on leveraging the persistence\nstrategies that come with the library, as well as creating your own strategies.\n\n[persistence-docs]: https://swiftpackageindex.com/pointfreeco/swift-sharing/main/documentation/sharing/persistencestrategies\n\n### Use anywhere\n\nIt is possible to use `@Shared` state essentially anywhere, including observable models, SwiftUI\nviews, UIKit view controllers, and more. For example, if you have a simple view that needs access\nto some shared state but does not need the full power of an observable model, then you can use\n`@Shared` directly in the view:\n\n```swift\nstruct DebugMeetingsView: View {\n  @Shared(.fileStorage(.meetingsURL)) var meetings: [Meeting] = []\n  var body: some View {\n    ForEach(meetings) { meeting in\n      Text(meeting.title)\n    }\n  }\n}\n```\n\nSimilarly, if you need to use UIKit for a particular feature or have a legacy feature that can't use\nSwiftUI yet, then you can use `@Shared` directly in a view controller:\n\n```swift\nfinal class DebugMeetingsViewController: UIViewController {\n  @Shared(.fileStorage(.meetingsURL)) var meetings: [Meeting] = []\n  // ...\n}\n```\n\nAnd to observe changes to `meetings` so that you can update the UI you can either use the\n``Shared/publisher`` property or the `observe` tool from our [Swift Navigation][swift-navigation]\nlibrary. See  [\"Observing changes\"][observation-docs] for more information.\n\n[swift-navigation]: http://github.com/pointfreeco/swift-navigation\n[observation-docs]: https://swiftpackageindex.com/pointfreeco/swift-sharing/main/documentation/sharing/observingchanges\n\n### Testing shared state\n\nFeatures using the `@Shared` property wrapper remain testable even though they interact with outside\nstorage systems, such as user defaults and the file system. This is possible because each test gets\na fresh storage system that is quarantined to only that test, and so any changes made to it will\nonly be seen by that test.\n\nSee [\"Testing\"][testing-docs] for more information on how to test your features when using `@Shared`.\n\n[testing-docs]: https://swiftpackageindex.com/pointfreeco/swift-sharing/main/documentation/sharing/testing\n\n## Documentation\n\nThe documentation for releases and `main` are available here:\n\n* [`main`](https://swiftpackageindex.com/pointfreeco/swift-sharing/main/documentation/sharing/)\n* [2.0.2](https://swiftpackageindex.com/pointfreeco/swift-sharing/2.0.2/documentation/sharing/)\n* [1.1.1](https://swiftpackageindex.com/pointfreeco/swift-sharing/1.1.1/documentation/sharing/)\n\n### Articles\n\n- [Shared][Shared-article]\n- [Persistence strategies][PersistenceStrategies-article]\n- [Mutating shared state][MutatingSharedState-article]\n- [Observing changes to shared state][ObservingChanges-article]\n- [Deriving shared state][DerivingSharedState-article]\n- [Reusable, type-safe keys][TypeSafeKeys-article]\n- [Initialization rules][InitializationRules-article]\n- [Testing][Testing-article]\n- [Gotchas][Gotchas-article]\n\n[Shared-article]: https://swiftpackageindex.com/pointfreeco/swift-sharing/main/documentation/sharing/shared\n[PersistenceStrategies-article]: https://swiftpackageindex.com/pointfreeco/swift-sharing/main/documentation/sharing/persistencestrategies\n[MutatingSharedState-article]: https://swiftpackageindex.com/pointfreeco/swift-sharing/main/documentation/sharing/mutatingsharedstate\n[ObservingChanges-article]: https://swiftpackageindex.com/pointfreeco/swift-sharing/main/documentation/sharing/observingchanges\n[DerivingSharedState-article]: https://swiftpackageindex.com/pointfreeco/swift-sharing/main/documentation/sharing/derivingsharedstate\n[TypeSafeKeys-article]: https://swiftpackageindex.com/pointfreeco/swift-sharing/main/documentation/sharing/typesafekeys\n[InitializationRules-article]: https://swiftpackageindex.com/pointfreeco/swift-sharing/main/documentation/sharing/initializationrules\n[Testing-article]: https://swiftpackageindex.com/pointfreeco/swift-sharing/main/documentation/sharing/testing\n[Gotchas-article]: https://swiftpackageindex.com/pointfreeco/swift-sharing/main/documentation/sharing/gotchas\n\n## Demos\n\nThis repo comes with _lots_ of examples to demonstrate how to solve common and complex problems with\nSharing. Check out [this](./Examples) directory to see them all, including:\n\n  * [Case Studies](./Examples/CaseStudies):\n    A number of case studies demonstrating the built-in features of the library.\n\n  * [API Client](./Examples/APIClientDemo):\n    A demo showing how shared state can be powered by an API client.\n\n  * [FirebaseDemo](./Examples/FirebaseDemo):\n    A demo showing how shared state can be powered by a remote [Firebase][firebase] config.\n\n  * [GRDB Demos][sharing-grdb-demos]:\n    [SharingGRDB][sharing-grdb-gh] is a lightweight replacement for SwiftData and the `@Query`\n    macro, powered by Sharing and [GRDB][grdb]. The library contains a number of\n    [demos][sharing-grdb-demos].\n\n  * [WasmDemo](./Examples/WasmDemo):\n    A [SwiftWasm][swiftwasm] application that uses this library to share state with your web\n    browser's local storage.\n\n  * [SyncUps][syncups]: We also rebuilt Apple's [Scrumdinger][scrumdinger] demo application using\n    modern, best practices for SwiftUI development, including using this library to share state and\n    persist it to the file system.\n\n[firebase]: https://firebase.google.com\n[grdb]: https://github.com/groue/GRDB.swift\n[swiftwasm]: https://swiftwasm.org\n[scrumdinger]: https://developer.apple.com/tutorials/app-dev-training/getting-started-with-scrumdinger\n[sharing-grdb-gh]: https://github.com/pointfreeco/sharing-grdb\n[sharing-grdb-demos]: https://github.com/pointfreeco/sharing-grdb?tab=readme-ov-file#demos\n[syncups]: https://github.com/pointfreeco/syncups\n\n## Installation\n\nYou can add Sharing to an Xcode project by adding it to your project as a package.\n\n\u003e https://github.com/pointfreeco/swift-sharing\n\nIf you want to use Sharing in a [SwiftPM](https://swift.org/package-manager/) project, it's as\nsimple as adding it to your `Package.swift`:\n\n``` swift\ndependencies: [\n  .package(url: \"https://github.com/pointfreeco/swift-sharing\", from: \"2.0.0\")\n]\n```\n\nAnd then adding the product to any target that needs access to the library:\n\n```swift\n.product(name: \"Sharing\", package: \"swift-sharing\"),\n```\n\n## Community\n\nIf you want to discuss this library or have a question about how to use it to solve a particular\nproblem, there are a number of places you can discuss with fellow\n[Point-Free](http://www.pointfree.co) enthusiasts:\n\n  * For long-form discussions, we recommend the\n    [discussions](http://github.com/pointfreeco/swift-sharing/discussions) tab of this repo.\n\n  * For casual chat, we recommend the\n    [Point-Free Community Slack](http://www.pointfree.co/slack-invite).\n    \n## Companion libraries\n\nSharing is built with extensibility in mind, and there are a number of community-supported libraries\navailable to enhance your applications:\n\n  * [SharingGRDB](https://github.com/pointfreeco/sharing-grdb): A lightweight replacement for\n    SwiftData and the `@Query` macro.    \n  * [SharingCloud](https://github.com/KeithBird/sharing-cloud): Sync shared data across devices via\n    iCloud.\n  * [SharingFirestore](https://github.com/bitkey-oss/sharing-firestore): Real-time synchronization and real-time queries powered by Firebase's Firestore.\n  * [SharingRemoteConfig](https://github.com/zunda-pixel/sharing-remoteconfig): Real-time Remote Config via Firebase.\n\nIf you'd like to contribute a library, please [open a PR][library-pr] with a link to it!\n\n[library-pr]: https://github.com/pointfreeco/swift-sharing/edit/main/README.md\n\n## License\n\nThis library is released under the MIT license. See [LICENSE](LICENSE) for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpointfreeco%2Fswift-sharing","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpointfreeco%2Fswift-sharing","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpointfreeco%2Fswift-sharing/lists"}