{"id":13995116,"url":"https://github.com/shaps80/SwiftUIBackports","last_synced_at":"2025-07-22T21:32:13.539Z","repository":{"id":39733020,"uuid":"507156043","full_name":"shaps80/SwiftUIBackports","owner":"shaps80","description":"A collection of SwiftUI backports for iOS, macOS, tvOS and watchOS","archived":false,"fork":false,"pushed_at":"2024-05-01T19:15:33.000Z","size":19021,"stargazers_count":966,"open_issues_count":5,"forks_count":61,"subscribers_count":12,"default_branch":"main","last_synced_at":"2024-11-21T13:12:29.276Z","etag":null,"topics":["backport","ios","macos","modal","photopicker","presentation","propertywrapper","sharesheet","swift","swiftui","textview","tvos","watchos"],"latest_commit_sha":null,"homepage":"","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/shaps80.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"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}},"created_at":"2022-06-24T22:10:45.000Z","updated_at":"2024-11-11T09:12:27.000Z","dependencies_parsed_at":"2023-02-14T13:15:53.717Z","dependency_job_id":"b980e55f-da1e-49e4-ac52-7455a3945b1b","html_url":"https://github.com/shaps80/SwiftUIBackports","commit_stats":{"total_commits":175,"total_committers":22,"mean_commits":7.954545454545454,"dds":"0.20571428571428574","last_synced_commit":"f5f23b016eeda6642a0fe1020241af19c9c05556"},"previous_names":[],"tags_count":49,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shaps80%2FSwiftUIBackports","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shaps80%2FSwiftUIBackports/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shaps80%2FSwiftUIBackports/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shaps80%2FSwiftUIBackports/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/shaps80","download_url":"https://codeload.github.com/shaps80/SwiftUIBackports/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":227177779,"owners_count":17743165,"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":["backport","ios","macos","modal","photopicker","presentation","propertywrapper","sharesheet","swift","swiftui","textview","tvos","watchos"],"created_at":"2024-08-09T14:03:15.483Z","updated_at":"2024-11-29T17:31:02.967Z","avatar_url":"https://github.com/shaps80.png","language":"Swift","readme":"![watchOS](https://img.shields.io/badge/watchOS-DE1F51)\n![macOS](https://img.shields.io/badge/macOS-EE751F)\n![tvOS](https://img.shields.io/badge/tvOS-00B9BB)\n![ios](https://img.shields.io/badge/iOS-0C62C7)\n[![swift](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fshaps80%2FSwiftUIBackports%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/shaps80/SwiftUIBackports)\n\n# SwiftUI Backports\n\nIntroducing a collection of SwiftUI backports to make your iOS development easier.\n\nMany backports support iOS 13+ but where UIKIt features were introduced in later versions, the same will be applicable to these backports, to keep parity with UIKit.\n\nIn some cases, I've also included additional APIs that bring more features to your SwiftUI development.\n\n\u003e Note, **all** backports will be API-matching to Apple's official APIs, any additional features will be provided separately.\n\nAll backports are fully documented, in most cases using Apple's own documentation for consistency. Please refer to the header docs or Apple's original documentation for more details.\n\nThere is also a [Demo project](https://github.com/shaps80/SwiftUIBackportsDemo) available where you can see full demonstrations of all backports and additional features, including reference code to help you get started.\n\n\u003e Lastly, I hope this repo also serves as a great resource for _how_ you can backport effectively with minimal hacks 👍\n\n## Documentation\n\nFull [documentation](https://shaps80.github.io/SwiftUIBackports/documentation/SwiftUIBackports) can be found [here](https://shaps80.github.io/SwiftUIBackports/documentation/SwiftUIBackports).\n\n## Sponsor\n\nBuilding useful libraries like these, takes time away from my family. I build these tools in my spare time because I feel its important to give back to the community. Please consider [Sponsoring](https://github.com/sponsors/shaps80) me as it helps keep me working on useful libraries like these 😬\n\nYou can also give me a follow and a 'thanks' anytime.\n\n[![Twitter](https://img.shields.io/badge/Twitter-@shaps-4AC71B)](http://twitter.com/shaps)\n\n## Usage\n\nThe library adopts a backport design by [Dave DeLong](https://davedelong.com/blog/2021/10/09/simplifying-backwards-compatibility-in-swift/) that makes use of a single type to improve discoverability and maintainability when the time comes to remove your backport implementations, in favour of official APIs.\n\nBackports of pure types, can easily be discovered under the `Backport` namespace. Similarly, modifiers are discoverable under the `.backport` namespace.\n\n\u003e Unfortunately `Environment` backports cannot be access this way, in those cases the Apple API values will be prefixed with `backport` to simplify discovery.\n\nTypes:\n\n```swift\n@Backport.AppStorage(\"filter-enabled\")\nprivate var filterEnabled: Bool = false\n```\n\nModifier:\n\n```swift\nButton(\"Show Prompt\") {\n    showPrompt = true\n}\n.sheet(isPresented: $showPrompt) {\n    Prompt()\n        .backport.presentationDetents([.medium, .large])\n}\n```\n\nEnvironment:\n\n```swift\n@Environment(\\.backportRefresh) private var refreshAction\n```\n\n## Backports\n\n**SwiftUI**\n\n- `AsyncImage`\n- `AppStorage`\n- `background` – ViewBuilder API\n- `DismissAction`\n- `DynamicTypeSize`\n– `Label`\n– `LabeledContent`\n- `NavigationDestination` – uses a standard NavigationView\n- `navigationTitle` – newer API\n- `overlay` – ViewBuilder API\n- `onChange`\n- `openURL`\n- `ProgressView`\n- `presentationDetents`\n- `presentationDragIndicator`\n- `quicklookPreview`\n- `requestReview`\n- `Refreshable` – includes pull-to-refresh \n- `ScaledMetric`\n- `ShareLink`\n- `StateObject`\n- `scrollDisabled`\n- `scrollDismissesKeyboard`\n- `scrollIndicators`\n- `Section(_ header:)`\n- `task` – async/await modifier\n\n**UIKit**\n\n- `UIHostingConfiguration` – simplifies embedding SwiftUI in `UICollectionViewCell` and `UITableViewCell`\n\n## Extras\n\n**Modal Presentations**\n\nAdding this to your presented view, you can use the provided closure to present an `ActionSheet` to a user when they attempt to dismiss interactively. You can also use this to disable interactive dismissals entirely.\n\n```swift\npresentation(isModal: true) { /* attempt */ }\n```\n\n**FittingGeometryReader**\n\nA custom `GeometryReader` implementation that correctly auto-sizes itself to its content. This is useful in many cases where you need a `GeometryReader` but don't want it to implicitly take up its parent View's bounds.\n\n**FittingScrollView**\n\nA custom `ScrollView` that respects `Spacer`'s when the content is not scrollable. This is useful when you need to place a view at the edges of your scrollview while its content is small enough to not require scrolling. Another great use case is vertically centered content that becomes `top` aligned once the content requires scrolling.\n\n## Installation\n\nYou can install manually (by copying the files in the `Sources` directory) or using Swift Package Manager (**preferred**)\n\nTo install using Swift Package Manager, add this to the `dependencies` section of your `Package.swift` file:\n\n`.package(url: \"https://github.com/shaps80/SwiftUIBackports.git\", .upToNextMajor(from: \"2.0.0\"))`\n","funding_links":["https://github.com/sponsors/shaps80"],"categories":["Swift"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshaps80%2FSwiftUIBackports","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshaps80%2FSwiftUIBackports","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshaps80%2FSwiftUIBackports/lists"}