{"id":1125,"url":"https://github.com/dreymonde/AppFolder","last_synced_at":"2025-07-30T20:32:32.396Z","repository":{"id":56902178,"uuid":"118031244","full_name":"dreymonde/AppFolder","owner":"dreymonde","description":"🗂 Never use NSSearchPathForDirectoriesInDomains again","archived":false,"fork":false,"pushed_at":"2022-04-23T21:35:59.000Z","size":136,"stargazers_count":936,"open_issues_count":0,"forks_count":26,"subscribers_count":18,"default_branch":"master","last_synced_at":"2024-10-30T00:33:36.208Z","etag":null,"topics":["filesystem","ios","swift"],"latest_commit_sha":null,"homepage":"https://medium.com/anysuggestion","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/dreymonde.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-01-18T19:58:05.000Z","updated_at":"2024-10-22T11:22:20.000Z","dependencies_parsed_at":"2022-08-20T18:50:41.931Z","dependency_job_id":null,"html_url":"https://github.com/dreymonde/AppFolder","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dreymonde%2FAppFolder","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dreymonde%2FAppFolder/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dreymonde%2FAppFolder/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dreymonde%2FAppFolder/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dreymonde","download_url":"https://codeload.github.com/dreymonde/AppFolder/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228017951,"owners_count":17856841,"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":["filesystem","ios","swift"],"created_at":"2024-01-05T20:15:39.441Z","updated_at":"2024-12-04T20:31:00.979Z","avatar_url":"https://github.com/dreymonde.png","language":"Swift","funding_links":[],"categories":["Files","HarmonyOS","Swift"],"sub_categories":["Getting Started","Other free courses","Windows Manager","Linter"],"readme":"![logo](Configs/Logo.png)\n\n# AppFolder\n\n[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fdreymonde%2FAppFolder%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/dreymonde/AppFolder)\n[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fdreymonde%2FAppFolder%2Fbadge%3Ftype%3Dplatforms)](https://swiftpackageindex.com/dreymonde/AppFolder)\n\n**AppFolder** is a lightweight framework that lets you design a friendly, strongly-typed representation of a directories inside your app's container. All the system directories like **\"Caches/\"** and \n**\"Application Support/\"** are already present, and you can add yours using just a few lines of code.\n\n**AppFolder** has a simple and beautiful interface which was made possible with the help of **Swift**'s dark magic: _inheritance_ 😱\n\nIf you want to learn more about the idea, check out [Introducing AppFolder](https://medium.com/anysuggestion/introducing-appfolder-704b007bd83b) on Medium.\n\n## Usage\n\n```swift\nimport AppFolder\n\nlet documents = AppFolder.Documents\nlet caches = AppFolder.Library.Caches\nlet cachesURL = caches.url\n\nextension Library.Caches {\n    \n    class Images: Directory { }\n    \n    var Images: Images {\n        return subdirectory()\n    }\n    \n}\n\nlet imageCache = AppFolder.Library.Caches.Images\nlet imageCacheURL = imageCache.url\n```\n\n## Guide\n\n### Your app's folder\n\n```swift\nlet documents = AppFolder.Documents\nlet tmp = AppFolder.tmp\nlet applicationSupport = AppFolder.Library.Application_Support\nlet caches = AppFolder.Library.Caches\n\ncaches.url // full URL\ncaches.folderName // \"Caches\"\ncaches.subpath // \"Library/Caches\"\n\ncaches.baseURL\n// the same as\nAppFolder.baseURL\n\nlet fileURL = caches.url.appendingPathComponent(\"cached-file.json\")\n```\n\n**AppFolder** represents a file structure of your app's container and gives you a better understanding of where your files are stored. `AppFolder` is a main entrance point to your folders. Inside you can find:\n\n- **Documents** (`AppFolder.Documents`). Inside this directory you should store *\"only documents and other data that is user-generated, or that cannot otherwise be recreated by your application.\"* - [iOS Data Storage Guidelines][storage-guidelines-url]\n- **Library/Application Support** (`AppFolder.Library.Application_Support`). *\"The Application Support directory is a good place to store files that might be in your Documents directory but that shouldn't be seen by users. For example, a database that your app needs but that the user would never open manually.\"* - [iOS Storage Best Practices][storage-practices-url]\n- **Library/Caches** (`AppFolder.Library.Caches`). Caches directory is the place for *\"...data that can be downloaded again or regenerated. ...Examples of files you should put in the Caches directory include database cache files and downloadable content, such as that used by magazine, newspaper, and map applications.\"* - [iOS Data Storage Guidelines][storage-guidelines-url]\n- **tmp** (`AppFolder.tmp`). *\"Use this directory to write temporary files that do not need to persist between launches of your app. Your app should remove files from this directory when they are no longer needed; however, the system may purge this directory when your app is not running.\"* - [File System Programming Guide][fs-guide-url]\n\n### Adding your own folders\n\nLet's assume that we want to declare a **\"Files\"** folder inside our **\"Application Support\"** directory.\n\nTurns out that each folder in **AppFolder** is represented by a concrete `Directory` sublcass. For example, **\"Application Support** is of type `Library.Application_Support`. To declare our own folder, we need to create a new `Directory` subclass:\n\n```swift\nfinal class Files : Directory { }\n```\n\nBy default, folder name will be automatically generated from the class name.\n\nNow we can access our new folder in a very straightforward way:\n\n```swift\nlet filesFolder = AppFolder.Library.Application_Support.appending(Files.self)\n```\n\nBut if we want to get a little bit more type-safety, we should put this whole logic into an extension:\n\n```swift\nextension Library.Application_Support {\n    \n    final class Files : Directory { }\n    \n    var Files: Files {\n        return subdirectory()\n    }\n    \n}\n```\n\nNow, you may wonder: since `var Files` is a property, why is `var Files`... capitalized?\n\nWell, it's an intentional **AppFolder** design decision. In order to represent a folder structure as accurate as possible, all properties must be written according to their real world names (with spaces substituted by `_`). So, for example, **\"Documents\"** is `AppFolder.Documents`, and **\"tmp\"** is `AppFolder.tmp` - just as in the \"real world\".\n\n*Naming your classes with `_` (for example, `class User_Files : Directory`) will automically generate folder name with a space (\"User Files\" in this case)*\n\nSo, this part should be clear. Now we can use our folder completely intuitively:\n\n```swift\nlet files = AppFolder.Library.Application_Support.Files\nlet filesURL = files.url\n```\n\n**IMPORTANT:** Describing folders doesn't automatically create them. **AppFolder** provides a way to organize your folder structure in code, not to actively manage it on disk. In order to be used, all non-system directories should be explicitly created with `FileManager.default.createDirectory(at:)` or similar APIs.\n\n### Using AppFolder with app groups\n\n**AppFolder** also supports containers shared with app groups via `AppGroupContainer`:\n\n```swift\nenum MyAppGroup : AppGroup {\n    static var groupIdentifier: String {\n        return \"group.com.my-app.my-app-group\"\n    }\n}\n\nlet sharedCaches = AppGroupContainer\u003cMyAppGroup\u003e.Library.Caches\n```\n\nThis way you can, for example, simplify a creation of a shared **Core Data** stack without losing control over the process:\n\n```swift\nlet applicationSupportURL = AppGroupContainer\u003cMyAppGroup\u003e.Library.Application_Support.url\nlet sqliteFileURL = applicationSupportURL.appendingPathComponent(\"db.sql\")\nlet model = NSManagedObjectModel(contentsOf: sqliteFileURL)\nlet container = NSPersistentContainer(name: \"my-app-db\", managedObjectModel: model!)\n```\n\nTo learn more about app groups, check out the [App Extension Programming Guide: Handling Common Scenarios](https://developer.apple.com/library/content/documentation/General/Conceptual/ExtensibilityPG/ExtensionScenarios.html) (section \"Sharing Data with Your Containing App\").\n\n### Customizing folder name\n\nIf you're not happy with automatically generated name, you can provide your own:\n\n```swift\nfinal class CustomNamedFolder : Directory {\n    override var folderName: String {\n        return \"Custom\"\n    }\n}\n```\n\n### Using AppFolder on macOS\n\n`AppFolder` uses `NSHomeDirectory()` under the hood, so, depending on your **macOS** app, it might just locate you to the user's home directory, as documentation states:\n\n\u003e In macOS, it is the application’s sandbox directory or the current user’s home directory (if the application is not in a sandbox)\n\n*[NSHomeDirectory() reference](https://developer.apple.com/documentation/foundation/1413045-nshomedirectory)*\n\n`AppFolder.tmp` is also *deprecated* on macOS because it may give results different from `NSTemporaryDirectory()`. To use temporary directory on macOS, we recommend using `FileManager.default.temporaryDirectory`.\n\n## Disclaimer\n\n**AppFolder** is in a very early stage. Some stuff will probably be broken at some point.\n\n## Installation\n\n#### Swift Package Manager\n\nStarting with Xcode 11, **AppFolder** is officially available *only* via Swift Package Manager.\n\nIn Xcode 11 or greater, in you project, select: `File \u003e Swift Packages \u003e Add Pacakage Dependency`\n\nIn the search bar type\n\n```\nhttps://github.com/dreymonde/AppFolder\n``` \n\nThen proceed with installation.\n\n\u003e If you can't find anything in the panel of the Swift Packages you probably haven't added yet your github account.\nYou can do that under the **Preferences** panel of your Xcode, in the **Accounts** section.\n\nFor command-line based apps, you can just add this directly to your **Package.swift** file:\n\n```swift\ndependencies: [\n    .package(url: \"https://github.com/dreymonde/AppFolder\", from: \"0.2.0\"),\n]\n```\n\n#### Manual\n\nOf course, you always have an option of just copying-and-pasting the code - **AppFolder** is just a few files, so feel free.\n\n#### Deprecated dependency managers\n\nLast **AppFolder** version to support [Carthage][carthage-url] and [Cocoapods][cocoapods-url] is **0.2.0**. Carthage and Cocoapods will no longer be officially supported.\n\nCarthage:\n\n```ruby\ngithub \"dreymonde/AppFolder\" ~\u003e 0.2.0\n```\n\nCocoapods:\n\n```ruby\npod 'AppFolder', '~\u003e 0.2.0'\n```\n\n[swift-badge]: https://img.shields.io/badge/Swift-5.1-orange.svg?style=flat\n[swift-url]: https://swift.org\n[platform-badge]: https://img.shields.io/badge/platform-iOS%20%7C%20macOS%20%7C%20watchOS%20%7C%20tvOS-lightgrey.svg\n[platform-url]: https://developer.apple.com/swift/\n[storage-guidelines-url]: https://developer.apple.com/icloud/documentation/data-storage/index.html\n[storage-practices-url]: https://developer.apple.com/videos/play/fall2017/204/\n[fs-guide-url]: https://developer.apple.com/library/content/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html\n[carthage-url]: https://github.com/Carthage/Carthage\n[cocoapods-url]: https://github.com/CocoaPods/CocoaPods\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdreymonde%2FAppFolder","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdreymonde%2FAppFolder","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdreymonde%2FAppFolder/lists"}