Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Start using the new Sharing library #18

Merged
merged 27 commits into from
Dec 2, 2024
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 20 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ of navigation (_e.g._, sheets, drill-downs, alerts), many side effects (timers,
data persistence), and do so in a way that is testable and modular.

This application was built over the course of [many episodes][modern-swiftui-collection] on
Point-Free, a video series exploring functional programming and the Swift language, hosted by
Point-Free, a video series exploring advanced programming topics in the Swift language, hosted by
[Brandon Williams](https://twitter.com/mbrandonw) and [Stephen
Celis](https://twitter.com/stephencelis).

Expand Down Expand Up @@ -66,25 +66,29 @@ Our SyncUps application is a rebuild of Apple's Scrumdinger application, but wit
modern, best practices for SwiftUI development. We faithfully recreate the Scrumdinger, but with
some key additions:

1. Identifiers are made type safe using our [Tagged library][tagged-gh]. This prevents us from
writing non-sensical code, such as comparing a `SyncUp.ID` to a `Attendee.ID`.
2. Instead of using bare arrays in feature logic we use an "identified" array from our
[IdentifiedCollections][identified-collections-gh] library. This allows you to read and modify
elements of the collection via their ID rather than positional index, which can be error prone
and lead to bugs or crashes.
3. _All_ navigation is driven off of state, including sheets, drill-downs and alerts. This makes
1. _All_ navigation is driven off of state, including sheets, drill-downs and alerts. This makes
it possible to deep link into any screen of the app by just constructing a piece of state and
handing it off to SwiftUI.
4. Further, each view represents its navigation destinations as a single enum, which gives us
compile time proof that two destinations cannot be active at the same time. This cannot be
accomplished with default SwiftUI tools, but can be done with our [SwiftUINavigation
library][swiftui-nav-gh].
5. All side effects are controlled. This includes access to the file system for persistence, access
1. Further, when a feature can navigate to multiple destinations, an enum is used to model the
destinations, which gives us compile time proof that two destinations cannot be active at the
same time. This cannot be accomplished with default SwiftUI tools, but can be done with our
[SwiftNavigation library][swift-nav-gh].
1. Persistence is handled by our [Sharing][sharing-gh] library, which allows one to hold onto
shared state in an observable model or view, and under the hood any changes to the state will be
persisted to external storage, such as the file system. Even the global navigation is persisted
using the Sharing library.
1. All side effects are controlled. This includes access to the file system for persistence, access
to time-based asynchrony for timers, access to speech recognition APIs, and even the creation
of dates and UUIDs. This allows us to run our application in specific execution contexts, which
is very useful in tests and Xcode previews. We accomplish this using our
[Dependencies][dependencies-gh] library.
6. The project includes a full test suite. Since all of navigation is driven off of state, and
1. Identifiers are made type safe using our [Tagged library][tagged-gh]. This prevents us from
writing non-sensical code, such as comparing a `SyncUp.ID` to a `Attendee.ID`.
1. Instead of using bare arrays in feature logic we use an "identified" array from our
[IdentifiedCollections][identified-collections-gh] library. This allows you to read and modify
elements of the collection via their ID rather than positional index, which can be error prone
and lead to bugs or crashes.
1. The project includes a full test suite. Since all of navigation is driven off of state, and
because we controlled all dependencies, we can write very comprehensive and nuanced tests. For
example, we can write a unit test that proves that when a sync-up meeting's timer runs out the
screen pops off the stack and a new transcript is added to the sync-up. Such a test would be
Expand All @@ -103,5 +107,6 @@ Here is a list of ports of the app:
[scrumdinger-dl]: https://docs-assets.developer.apple.com/published/1ea2eec121b90031e354288912a76357/TranscribingSpeechToText.zip
[tagged-gh]: http://github.com/pointfreeco/swift-tagged
[identified-collections-gh]: http://github.com/pointfreeco/swift-identified-collections
[swiftui-nav-gh]: http://github.com/pointfreeco/swiftui-navigation
[swift-nav-gh]: http://github.com/pointfreeco/swift-navigation
[dependencies-gh]: http://github.com/pointfreeco/swift-dependencies
[sharing-gh]: https://github.com/pointfreeco/swift-sharing
43 changes: 26 additions & 17 deletions SyncUps.xcworkspace/xcshareddata/swiftpm/Package.resolved
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"originHash" : "4330f83645f40a08674938f5dee887a1bbc67b200cdcfdc80b3b2c258d0336b8",
"originHash" : "a41d8ea0a7e275eaf005ddc4bfd786d637276802746d02247b43cc5cfb463378",
"pins" : [
{
"identity" : "combine-schedulers",
Expand Down Expand Up @@ -40,16 +40,16 @@
{
"identity" : "swift-concurrency-extras",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-concurrency-extras.git",
"location" : "https://github.com/pointfreeco/swift-concurrency-extras",
"state" : {
"revision" : "6054df64b55186f08b6d0fd87152081b8ad8d613",
"version" : "1.2.0"
"revision" : "163409ef7dae9d960b87f34b51587b6609a76c1f",
"version" : "1.3.0"
}
},
{
"identity" : "swift-custom-dump",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-custom-dump.git",
"location" : "https://github.com/pointfreeco/swift-custom-dump",
"state" : {
"revision" : "82645ec760917961cfa08c9c0c7104a57a0fa4b1",
"version" : "1.3.3"
Expand All @@ -58,16 +58,16 @@
{
"identity" : "swift-dependencies",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-dependencies.git",
"location" : "https://github.com/pointfreeco/swift-dependencies",
"state" : {
"revision" : "0fc0255e780bf742abeef29dec80924f5f0ae7b9",
"version" : "1.4.1"
"branch" : "dependency-trait-fix",
"revision" : "9dcf4357cd12ef91a1c9c35a58c4a063150a50dc"
}
},
{
"identity" : "swift-identified-collections",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-identified-collections.git",
"location" : "https://github.com/pointfreeco/swift-identified-collections",
"state" : {
"revision" : "2f5ab6e091dd032b63dacbda052405756010dc3b",
"version" : "1.1.0"
Expand All @@ -87,23 +87,32 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-perception",
"state" : {
"revision" : "bc67aa8e461351c97282c2419153757a446ae1c9",
"version" : "1.3.5"
"revision" : "dccdf5aed1db969afa11d6fbd36b96a4932ebe8c",
"version" : "1.4.0"
}
},
{
"identity" : "swift-sharing",
"kind" : "remoteSourceControl",
"location" : "http://github.com/pointfreeco/swift-sharing/",
"state" : {
"branch" : "main",
"revision" : "aefeae51b6c246fce58e33f788b2d235e92532c2"
}
},
{
"identity" : "swift-syntax",
"kind" : "remoteSourceControl",
"location" : "https://github.com/swiftlang/swift-syntax",
"state" : {
"revision" : "2bc86522d115234d1f588efe2bcb4ce4be8f8b82",
"version" : "510.0.3"
"revision" : "0687f71944021d616d34d922343dcef086855920",
"version" : "600.0.1"
}
},
{
"identity" : "swift-tagged",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-tagged.git",
"location" : "https://github.com/pointfreeco/swift-tagged",
"state" : {
"revision" : "3907a9438f5b57d317001dc99f3f11b46882272b",
"version" : "0.10.0"
Expand All @@ -112,10 +121,10 @@
{
"identity" : "xctest-dynamic-overlay",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/xctest-dynamic-overlay.git",
"location" : "https://github.com/pointfreeco/xctest-dynamic-overlay",
"state" : {
"revision" : "770f990d3e4eececb57ac04a6076e22f8c97daeb",
"version" : "1.4.2"
"revision" : "a3f634d1a409c7979cabc0a71b3f26ffa9fc8af1",
"version" : "1.4.3"
}
}
],
Expand Down
Loading