🗂 Never use NSSearchPathForDirectoriesInDomains again

Overview

logo

AppFolder

Swift Platform Build Status

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 "Application Support/" are already present, and you can add yours using just a few lines of code.

AppFolder has a simple and beautiful interface which was made possible with the help of Swift's dark magic: inheritance 😱

If you want to learn more about the idea, check out Introducing AppFolder on Medium.

Usage

import AppFolder

let documents = AppFolder.Documents
let caches = AppFolder.Library.Caches
let cachesURL = caches.url

extension Library.Caches {
    
    class Images: Directory { }
    
    var Images: Images {
        return subdirectory()
    }
    
}

let imageCache = AppFolder.Library.Caches.Images
let imageCacheURL = imageCache.url

Guide

Your app's folder

let documents = AppFolder.Documents
let tmp = AppFolder.tmp
let applicationSupport = AppFolder.Library.Application_Support
let caches = AppFolder.Library.Caches

caches.url // full URL
caches.folderName // "Caches"
caches.subpath // "Library/Caches"

caches.baseURL
// the same as
AppFolder.baseURL

let fileURL = caches.url.appendingPathComponent("cached-file.json")

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:

  • 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
  • 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
  • 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
  • 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

Adding your own folders

Let's assume that we want to declare a "Files" folder inside our "Application Support" directory.

Turns 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:

final class Files : Directory { }

By default, folder name will be automatically generated from the class name.

Now we can access our new folder in a very straightforward way:

let filesFolder = AppFolder.Library.Application_Support.appending(Files.self)

But if we want to get a little bit more type-safety, we should put this whole logic into an extension:

extension Library.Application_Support {
    
    final class Files : Directory { }
    
    var Files: Files {
        return subdirectory()
    }
    
}

Now, you may wonder: since var Files is a property, why is var Files... capitalized?

Well, 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".

Naming your classes with _ (for example, class User_Files : Directory) will automically generate folder name with a space ("User Files" in this case)

So, this part should be clear. Now we can use our folder completely intuitively:

let files = AppFolder.Library.Application_Support.Files
let filesURL = files.url

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.

Using AppFolder with app groups

AppFolder also supports containers shared with app groups via AppGroupContainer:

enum MyAppGroup : AppGroup {
    static var groupIdentifier: String {
        return "group.com.my-app.my-app-group"
    }
}

let sharedCaches = AppGroupContainer<MyAppGroup>.Library.Caches

This way you can, for example, simplify a creation of a shared Core Data stack without losing control over the process:

let applicationSupportURL = AppGroupContainer<MyAppGroup>.Library.Application_Support.url
let sqliteFileURL = applicationSupportURL.appendingPathComponent("db.sql")
let model = NSManagedObjectModel(contentsOf: sqliteFileURL)
let container = NSPersistentContainer(name: "my-app-db", managedObjectModel: model!)

To learn more about app groups, check out the App Extension Programming Guide: Handling Common Scenarios (section "Sharing Data with Your Containing App").

Customizing folder name

If you're not happy with automatically generated name, you can provide your own:

final class CustomNamedFolder : Directory {
    override var folderName: String {
        return "Custom"
    }
}

Using AppFolder on macOS

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:

In macOS, it is the application’s sandbox directory or the current user’s home directory (if the application is not in a sandbox)

NSHomeDirectory() reference

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.

Disclaimer

AppFolder is in a very early stage. Some stuff will probably be broken at some point.

Installation

Swift Package Manager

Starting with Xcode 11, AppFolder is officially available only via Swift Package Manager.

In Xcode 11 or greater, in you project, select: File > Swift Packages > Add Pacakage Dependency

In the search bar type

https://github.com/dreymonde/AppFolder

Then proceed with installation.

If you can't find anything in the panel of the Swift Packages you probably haven't added yet your github account. You can do that under the Preferences panel of your Xcode, in the Accounts section.

For command-line based apps, you can just add this directly to your Package.swift file:

dependencies: [
    .package(url: "https://github.com/dreymonde/AppFolder", from: "0.2.0"),
]

Manual

Of course, you always have an option of just copying-and-pasting the code - AppFolder is just a few files, so feel free.

Deprecated dependency managers

Last AppFolder version to support Carthage and Cocoapods is 0.2.0. Carthage and Cocoapods will no longer be officially supported.

Carthage:

github "dreymonde/AppFolder" ~> 0.2.0

Cocoapods:

pod 'AppFolder', '~> 0.2.0'
You might also like...
The easiest way to use Bluetooth (BLE )in ios,even bady can use.
The easiest way to use Bluetooth (BLE )in ios,even bady can use.

The easiest way to use Bluetooth (BLE )in ios,even bady can use.

Are you sure the chemical compounds of your daily use are 100% safe? Use Chem-Aware, identify them right now!
Are you sure the chemical compounds of your daily use are 100% safe? Use Chem-Aware, identify them right now!

View Project On Devpost: Built With: PubChem's REST API How To Install Chem Aware: Prerequiste: Latest Version of Xcode and Simulators installed The a

A keychain wrapper that is so easy to use that your cat could use it.

A keychain wrapper that is so easy to use that your cat could use it.

iOS app for Technex, IIT(BHU) Varanasi. This project is closed before completion. You can use this app for learning purpose. You can use this app as a templet of any event related app.
iOS app for Technex, IIT(BHU) Varanasi. This project is closed before completion. You can use this app for learning purpose. You can use this app as a templet of any event related app.

technex-ios iOS app for Technex, IIT(BHU) Varanasi. This project is closed before completion for some reasons. You can use this app for learning purpo

(Animate CSS) animations for iOS. An easy to use library of iOS animations. As easy to use as an easy thing.
(Animate CSS) animations for iOS. An easy to use library of iOS animations. As easy to use as an easy thing.

wobbly See Wobbly in action (examples) Add a drop of honey 🍯 to your project wobbly has a bunch of cool, fun, and easy to use iOS animations for you

Kraken - Simple Dependency Injection container for Swift. Use protocols to resolve dependencies with easy-to-use syntax!
Kraken - Simple Dependency Injection container for Swift. Use protocols to resolve dependencies with easy-to-use syntax!

Kraken Photo courtesy of www.krakenstudios.blogspot.com Introduction Kraken is a simple Dependency Injection Container. It's aimed to be as simple as

Keep track of accessibility settings, leverage high contrast colors, and use scalable fonts to enable users with disabilities to use your app.
Keep track of accessibility settings, leverage high contrast colors, and use scalable fonts to enable users with disabilities to use your app.

Accessibility for iOS, macOS, tvOS, and watchOS 🎉 What's new in Capable 2.0 🎉 Here are the most important changes: 🏛 New framework architecture and

(Animate CSS) animations for iOS. An easy to use library of iOS animations. As easy to use as an easy thing.
(Animate CSS) animations for iOS. An easy to use library of iOS animations. As easy to use as an easy thing.

wobbly See Wobbly in action (examples) Add a drop of honey 🍯 to your project wobbly has a bunch of cool, fun, and easy to use iOS animations for you

Poi - You can use tinder UI like tableview method
Poi - You can use tinder UI like tableview method

Poi You can use tinder UI like tableview method Installation Manual Installation Use this command git clone [email protected]:HideakiTouhara/Poi.git Imp

EVURLCache - a NSURLCache subclass for handling all web requests that use NSURLRequest

EVURLCache What is this? This is a NSURLCache subclass for handeling all web requests that use NSURLRequest. (This includes UIWebView) The EVURLCache

 SwiftCharts - Easy to use and highly customizable charts library for iOS
SwiftCharts - Easy to use and highly customizable charts library for iOS

SwiftCharts Easy to use and highly customizable charts library for iOS Features: Bars - plain, stacked, grouped, horizontal, vertical Scatter Lines (s

GroupWork is an easy to use Swift framework that helps you orchestrate your concurrent, asynchronous functions in a clean and organized way
GroupWork is an easy to use Swift framework that helps you orchestrate your concurrent, asynchronous functions in a clean and organized way

GroupWork is an easy to use Swift framework that helps you orchestrate your concurrent, asynchronous functions in a clean and organized way. This help

A minimalistic, thread safe, non-boilerplate and super easy to use version of Active Record on Core Data.
A minimalistic, thread safe, non-boilerplate and super easy to use version of Active Record on Core Data.

Skopelos A minimalistic, thread-safe, non-boilerplate and super easy to use version of Active Record on Core Data. Simply all you need for doing Core

The easy to use Swift JSON decoder
The easy to use Swift JSON decoder

Unbox is deprecated in favor of Swift’s built-in Codable API and the Codextended project. All current users are highly encouraged to migrate to Codable as soon as possible.

tl;dr You love Swift's Codable protocol and use it everywhere
tl;dr You love Swift's Codable protocol and use it everywhere

tl;dr You love Swift's Codable protocol and use it everywhere, who doesn't! Here is an easy and very light way to store and retrieve -reasonable amoun

 Zip - A Swift framework for zipping and unzipping files. Simple and quick to use. Built on top of minizip.
Zip - A Swift framework for zipping and unzipping files. Simple and quick to use. Built on top of minizip.

Zip A Swift framework for zipping and unzipping files. Simple and quick to use. Built on top of minizip. Usage Import Zip at the top of the Swift file

Deli is an easy-to-use Dependency Injection Container that creates DI containers
Deli is an easy-to-use Dependency Injection Container that creates DI containers

Deli is an easy-to-use Dependency Injection Container that creates DI containers with all required registrations and corresponding factories.

TopicEventBus is Easy to use, type safe way of implementing Publish–subscribe design pattern.
TopicEventBus is Easy to use, type safe way of implementing Publish–subscribe design pattern.

TopicEventBus Publish–subscribe design pattern implementation framework, with ability to publish events by topic. (NotificationCenter extended alterna

Use FontAwesome in your Swift projects
Use FontAwesome in your Swift projects

FontAwesome.swift Use Font Awesome in your Swift projects To see the complete set of 3,978 icons in Font Awesome 5, please check the FontAwesome.com s

Comments
  • [Fix] Fix ambiguous between variable and class

    [Fix] Fix ambiguous between variable and class

    When using Swift4.1 with Xcode 9.3, the complier would throw an error saying that there are ambiguous usages between the properties and the nested class.

    So I change all properties's first letter to lowercase, and also pass the test case before I summit.

    opened by PandaraWen 2
  • image storing in app folder

    image storing in app folder

    awesome piece of work you have done, you have built the framework, can you please guide me how to use this in one's project, for storing images in app folder rather then storing in photos gallery or any example code that you have implemented using this framework to use its methods..

    opened by AbdulAj 1
Releases(0.1.0)
Owner
Oleg Dreyman
WWDC 2018 Scholarship Winner. iOS Engineer @nicephoton.
Oleg Dreyman
Count It, Never lose the count again

Count It Never lose the count again. Dead simple App with Apple Watch integration that lets you count anything. Laps while exercising. How many beers

Chris Jimenez 62 Nov 28, 2022
JSONNeverDie - Auto reflection tool from JSON to Model, user friendly JSON encoder / decoder, aims to never die

JSONNeverDie is an auto reflection tool from JSON to Model, a user friendly JSON encoder / decoder, aims to never die. Also JSONNeverDie is a very important part of Pitaya.

John Lui 454 Oct 30, 2022
Auto reflection tool from JSON to Model, user friendly JSON encoder / decoder, aims to never die

JSONNeverDie is an auto reflection tool from JSON to Model, a user friendly JSON encoder / decoder, aims to never die. Also JSONNeverDie is a very imp

John Lui 454 Oct 30, 2022
An application focused on managing men's haircuts. It has never been so easy to keep the cut on time

An application focused on managing men's haircuts. It has never been so easy to keep the cut on time

Yago Marques 2 Oct 13, 2022
StatusBarOverlay will automatically show a "No Internet Connection" bar when your app loses connection, and hide it again. It supports apps which hide the status bar and The Notch

StatusBarOverlay StatusBarOverlay will automatically show a "No Internet Connection" bar when your app loses connection, and hide it again. It support

Idle Hands Apps 160 Nov 2, 2022
Log every incoming notification to view them again later, also includes attachments and advanced settings to configure

Vē Natively integrated notification logger Installation Add this repository to your package manager

alexandra 43 Dec 25, 2022
Reliable Server Side Swift ✭ Make Apache great again!

mod_swift mod_swift is a technology demo which shows how to write native modules for the Apache Web Server in the Swift 3 programming language. The de

The ApacheExpress Alliance 174 Oct 22, 2022
StatusBarOverlay will automatically show a "No Internet Connection" bar when your app loses connection, and hide it again

StatusBarOverlay will automatically show a "No Internet Connection" bar when your app loses connection, and hide it again. It supports apps which hide the status bar and The Notch

Idle Hands Apps 160 Nov 2, 2022
Use any custom view as custom callout view for MKMapView with cool animations. Use any image as annotation view.

MapViewPlus About MapViewPlus gives you the missing methods of MapKit which are: imageForAnnotation and calloutViewForAnnotationView delegate methods.

Okhan Okbay 162 Nov 16, 2022