{"id":18269809,"url":"https://github.com/onmyway133/EasyStash","last_synced_at":"2025-04-04T23:31:31.309Z","repository":{"id":43175201,"uuid":"188824168","full_name":"onmyway133/EasyStash","owner":"onmyway133","description":"🗳Easy data persistence in Swift","archived":false,"fork":false,"pushed_at":"2024-05-09T15:22:07.000Z","size":108,"stargazers_count":390,"open_issues_count":5,"forks_count":21,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-03-29T00:08:01.422Z","etag":null,"topics":["cache","codable","disk","image","load","save","storage","swift"],"latest_commit_sha":null,"homepage":"https://onmyway133.com","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/onmyway133.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","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},"funding":{"github":"onmyway133","patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":null}},"created_at":"2019-05-27T10:40:48.000Z","updated_at":"2025-02-18T14:20:06.000Z","dependencies_parsed_at":"2024-06-19T10:09:04.367Z","dependency_job_id":null,"html_url":"https://github.com/onmyway133/EasyStash","commit_stats":{"total_commits":62,"total_committers":10,"mean_commits":6.2,"dds":"0.22580645161290325","last_synced_commit":"b1dfeae21290501947a418d99053640abae543b8"},"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/onmyway133%2FEasyStash","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/onmyway133%2FEasyStash/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/onmyway133%2FEasyStash/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/onmyway133%2FEasyStash/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/onmyway133","download_url":"https://codeload.github.com/onmyway133/EasyStash/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247266476,"owners_count":20910831,"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":["cache","codable","disk","image","load","save","storage","swift"],"created_at":"2024-11-05T11:37:18.871Z","updated_at":"2025-04-04T23:31:29.883Z","avatar_url":"https://github.com/onmyway133.png","language":"Swift","funding_links":["https://github.com/sponsors/onmyway133"],"categories":["Swift","swift"],"sub_categories":[],"readme":"# Easy Stash\n\n- [Blog](https://onmyway133.com/)\n- [Apps](https://indiegoodies.com)\n\n\u003cdiv align='center'\u003e\n    \u003cimg src='Screenshots/logo.png'\u003e\n\u003c/div\u003e\n\n[![CI Status](https://img.shields.io/circleci/project/github/onmyway133/EasyStash.svg)](https://circleci.com/gh/onmyway133/EasyStash)\n[![Version](https://img.shields.io/cocoapods/v/EasyStash.svg?style=flat)](http://cocoadocs.org/docsets/EasyStash)\n[![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)\n[![SPM compatible](https://img.shields.io/badge/SPM-compatible-brightgreen.svg)](https://github.com/apple/swift-package-manager)\n[![License](https://img.shields.io/cocoapods/l/EasyStash.svg?style=flat)](http://cocoadocs.org/docsets/EasyStash)\n[![Platform](https://img.shields.io/cocoapods/p/EasyStash.svg?style=flat)](http://cocoadocs.org/docsets/EasyStash)\n![Swift](https://img.shields.io/badge/%20in-swift%205.0-orange.svg)\n\n## Description\n\nEasyStash is an easy and lightweight persistence framework in Swift. With simple abstraction over `NSCache` and `FileManager`, it saves us from tedious work of saving and loading objects. There are no clever async, expiry handling or caching strategy for now, just save and load.\n\n- [x] Swift 5\n- [x] Support iOS, macOS, tvOS, watchOS\n- [x] Synchronous APIs with explicit try catch\n- [x] Persist UIImage/NSImage\n- [x] Persist Codable objects, including primitive types\n- [x] Persist Data\n- [x] Test coverage\n\n## Usage\n\nThe main and only class is `Storage` which encapsulates memory and disk cache. All operations involving disk are error prone, we need to handle error explicitly.\n\nWith `Options`, we can customize `folder` name, `searchPathDirectory`, `encoder` and `decoder` for `Codable`. By default, `folder` and `searchPathDirectory` specify that files will be saved at `/Library/Application Support/{BUNDLE_ID}/Default/`\n\n```swift\nvar storage: Storage? = nil\n\nvar options: Options = Options()\noptions.folder = \"Users\"\n\nstorage = try? Storage(options: options)\n\ndo {\n    try storage?.save(image, forKey: \"image\")\n    try storage?.save(users, forKey: \"codable\")\n} catch {\n    print(error)\n}\n```\n\nMemory cache is checked first before doing disk operations, so we won't hit disk that often.\n\n### Saving and loading images\n\nWorks for both UIImage and NSImage. Because image and data loading uses the same signatures, we need to explicitly specify type\n\n```swift\ntry storage.save(image, forKey: \"image\")\nlet loadedImage: UIImage = try storage.load(forKey: \"image\")\n```\n\n### Saving and loading Codable objects\n\nUses `JSONEncoder` and `JSONDecoder` under the hood to serialize and deserialize to and from `Data`\n\n```swift\nlet user = User(name: \"A\", age: 10)\nlet cities = [City(name: \"Oslo\"), City(name: \"New York\")]\n\ntry storage.save(users, forKey: \"user\")\ntry storage.save(cities, forKey: \"cities\")\n\nlet loadedUser = try storage.load(forKey: \"user\", as: User.self)\nlet loadedCities = try storage.load(forKey: \"cities\", as: [City].self)\n```\n\n### Saving and loading Data\n\n```swift\ntry storage.save(object: data, forKey: \"data\")\nlet loadedData: Data = try storage.load(forKey: \"data\")\n```\n\n### Saving and loading primitives\n\nAlthough primitives like `Int, String, Bool` conform to `Codable`, they can't be serialized into `Data` using `JSONEncoder` because json needs root object. This framework handles this case, so you can just save and load as normal\n\n```swift\ntry storage.save(100, forKey: \"an int\")\ntry storage.save(isLoggedIn, forKey: \"a boolean\")\n```\n\n### Folder informations\n\nEasyStash includes some helpful functions to check file and folder within its `Storage`.\n\nCheck if file exists\n\n```swift\ntry storage.exists(forKey: \"has_updated_profile\")\n```\n\nRemove file\n\n```swift\ntry storage.remove(forKey: \"a flag\")\n```\n\nRemove all files\n\n```swift\ntry storage.removeAll()\n```\n\nList all files. Each file has `name`, `url`, `modificationDate` and `size` information\n\n```swift\nlet files = try storage.files()\n```\n\nCheck folder size\n\n```swift\nlet size = try storage.folderSize()\n```\n\nCheck if folder has content\n\n```swift\ntry storage.isEmpty()\n```\n\nRemove files based on predicate. This is useful when we want to clear expired objects, or objects based certain criteria.\n\n```swift\ntry storage.removeAll(predicate: { $0.modificationDate \u003c migrationDate })\n```\n\n## Async\n\n`EasyStash` is designed to be synchronous. If we want to do async, it's easy as using `DispatchQueue`\n\n```swift\nDispatchQueue.global().async {\n    do {\n        try storage.save(largeImage, forKey: \"large_image\")\n    } catch {\n\n    }\n}\n```\n\n## Installation\n\n**EasyStash** is available through [CocoaPods](http://cocoapods.org). To install\nit, simply add the following line to your Podfile:\n\n```ruby\npod 'EasyStash'\n```\n\n**EasyStash** is also available through [Carthage](https://github.com/Carthage/Carthage).\nTo install just write into your Cartfile:\n\n```ruby\ngithub \"onmyway133/EasyStash\"\n```\n\n**EasyStash** is also available through [Swift Package Manager](https://swift.org/package-manager/).\nAdd EasyStash as a dependency to your Package.swift. For more information, please see the [Swift Package Manager documentation](https://github.com/apple/swift-package-manager/tree/master/Documentation).\n\n```swift\n.package(url: \"https://github.com/onmyway133/EasyStash\", from: \"1.1.8\")\n```\n\n**EasyStash** can also be installed manually. Just download and drop `Sources` folders in your project.\n\n## Author\n\nKhoa Pham, onmyway133@gmail.com\n\n## Contributing\n\nWe would love you to contribute to **EasyStash**, check the [CONTRIBUTING](https://github.com/onmyway133/EasyStash/blob/master/CONTRIBUTING.md) file for more info.\n\n## License\n\n**EasyStash** is available under the MIT license. See the [LICENSE](https://github.com/onmyway133/EasyStash/blob/master/LICENSE.md) file for more info.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fonmyway133%2FEasyStash","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fonmyway133%2FEasyStash","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fonmyway133%2FEasyStash/lists"}