{"id":957,"url":"https://github.com/3lvis/DATAStack","last_synced_at":"2025-07-30T19:33:13.075Z","repository":{"id":15071305,"uuid":"17797649","full_name":"3lvis/DATAStack","owner":"3lvis","description":"100% Swift Simple Boilerplate Free Core Data Stack. NSPersistentContainer","archived":true,"fork":false,"pushed_at":"2020-10-06T08:06:47.000Z","size":14528,"stargazers_count":214,"open_issues_count":5,"forks_count":44,"subscribers_count":11,"default_branch":"master","last_synced_at":"2024-11-24T16:48:54.504Z","etag":null,"topics":["core-data","coredata","nspersistentcontainer"],"latest_commit_sha":null,"homepage":"","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/3lvis.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-03-16T11:20:08.000Z","updated_at":"2024-02-12T07:56:12.000Z","dependencies_parsed_at":"2022-07-17T04:46:08.513Z","dependency_job_id":null,"html_url":"https://github.com/3lvis/DATAStack","commit_stats":null,"previous_names":["nselvis/andydatamanager","nselvis/andydatabasemanager","nselvis/andydatastack"],"tags_count":73,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/3lvis%2FDATAStack","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/3lvis%2FDATAStack/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/3lvis%2FDATAStack/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/3lvis%2FDATAStack/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/3lvis","download_url":"https://codeload.github.com/3lvis/DATAStack/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228179061,"owners_count":17881132,"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":["core-data","coredata","nspersistentcontainer"],"created_at":"2024-01-05T20:15:35.548Z","updated_at":"2024-12-04T19:32:30.018Z","avatar_url":"https://github.com/3lvis.png","language":"Swift","funding_links":[],"categories":["Core Data"],"sub_categories":["Linter","Other free courses"],"readme":"![DATAStack](https://raw.githubusercontent.com/SyncDB/DATAStack/master/Images/datastack-logo2.png)\n\n\u003cdiv align = \"center\"\u003e\n  \u003ca href=\"https://cocoapods.org/pods/DATAStack\"\u003e\n    \u003cimg src=\"https://img.shields.io/cocoapods/v/DATAStack.svg?style=flat\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://github.com/SyncDB/DATAStack\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://github.com/SyncDB/DATAStack#installation\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/compatible-swift%202.3,%203%20and%204-orange.svg\" /\u003e\n  \u003c/a\u003e\n\u003c/div\u003e\n\n\u003cdiv align = \"center\"\u003e\n  \u003ca href=\"https://cocoapods.org/pods/DATAStack\" target=\"blank\"\u003e\n    \u003cimg src=\"https://img.shields.io/cocoapods/p/DATAStack.svg?style=flat\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://cocoapods.org/pods/DATAStack\" target=\"blank\"\u003e\n    \u003cimg src=\"https://img.shields.io/cocoapods/l/DATAStack.svg?style=flat\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://gitter.im/SyncDB/DATAStack\"\u003e\n    \u003cimg src=\"https://img.shields.io/gitter/room/nwjs/nw.js.svg\" /\u003e\n  \u003c/a\u003e\n  \u003cbr\u003e\n  \u003cbr\u003e\n\u003c/div\u003e\n\n**DATAStack** helps you to alleviate the Core Data boilerplate. Now you can go to your AppDelegate remove all the Core Data related code and replace it with an instance of DATAStack ([ObjC](DemoObjectiveC/AppDelegate.m), [Swift](DemoSwift/AppDelegate.swift)).\n\n- Easier thread safety\n- Runs synchronously when using unit tests\n- No singletons\n- SQLite and InMemory support out of the box\n- Easy database drop method\n- Shines with Swift\n- Compatible with Objective-C\n- Free\n\n## Table of Contents\n\n* [Running the demos](#running-the-demos)\n* [Initialization](#initialization)\n* [Main Thread NSManagedObjectContext](#main-thread-nsmanagedobjectcontext)\n* [Background Thread NSManagedObjectContext](#background-thread-nsmanagedobjectcontext)\n* [Clean up](#clean-up)\n* [Testing](#testing)\n* [Migrations](#migrations)\n* [Installation](#installation)\n* [Be Awesome](#be-awesome)\n* [Author](#author)\n* [License](#license)\n\n## Running the demos\n\n- Clone the repository\n- Open the `Demo.xcodeproj`\n- Enjoy!\n\n## Initialization\n\nYou can easily initialize a new instance of **DATAStack** with just your Core Data Model name (xcdatamodel).\n\n**Swift**\n``` swift\nlet dataStack = DATAStack(modelName:\"MyAppModel\")\n```\n\n**Objective-C**\n``` objc\nDATAStack *dataStack = [[DATAStack alloc] initWithModelName:@\"MyAppModel\"];\n```\n\nThere are plenty of other ways to intialize a DATAStack:\n\n- Using a custom store type.\n\n``` swift\nlet dataStack = DATAStack(modelName:\"MyAppModel\", storeType: .InMemory)\n```\n\n- Using another bundle and a store type, let's say your test bundle and .InMemory store type, perfect for running unit tests.\n\n``` swift\nlet dataStack = DATAStack(modelName: \"Model\", bundle: NSBundle(forClass: Tests.self), storeType: .InMemory)\n```\n\n- Using a different name for your .sqlite file than your model name, like `CustomStoreName.sqlite`.\n\n``` swift\nlet dataStack = DATAStack(modelName: \"Model\", bundle: NSBundle.mainBundle(), storeType: .SQLite, storeName: \"CustomStoreName\")\n```\n\n- Providing a diferent container url, by default we'll use the documents folder, most apps do this, but if you want to share your sqlite file between your main app and your app extension you'll want this.\n\n``` swift\nlet dataStack = DATAStack(modelName: \"Model\", bundle: NSBundle.mainBundle(), storeType: .SQLite, storeName: \"CustomStoreName\", containerURL: sharedURL)\n```\n\n## Main Thread NSManagedObjectContext\n\nGetting access to the NSManagedObjectContext attached to the main thread is as simple as using the `mainContext` property.\n\n```swift\nself.dataStack.mainContext\n```\n\nor\n\n```swift\nself.dataStack.viewContext\n```\n\n## Background Thread NSManagedObjectContext\n\nYou can easily create a new background NSManagedObjectContext for data processing. This block is completely asynchronous and will be run on a background thread.\n\nTo be compatible with NSPersistentContainer you can also use `performBackgroundTask` instead of `performInNewBackgroundContext`.\n\n**Swift**\n```swift\nfunc createUser() {\n    self.dataStack.performInNewBackgroundContext { backgroundContext in\n        let entity = NSEntityDescription.entityForName(\"User\", inManagedObjectContext: backgroundContext)!\n        let object = NSManagedObject(entity: entity, insertIntoManagedObjectContext: backgroundContext)\n        object.setValue(\"Background\", forKey: \"name\")\n        object.setValue(NSDate(), forKey: \"createdDate\")\n        try! backgroundContext.save()\n    }\n}\n```\n\n**Objective-C**\n```objc\n- (void)createUser {\n    [self.dataStack performInNewBackgroundContext:^(NSManagedObjectContext * _Nonnull backgroundContext) {\n        NSEntityDescription *entity = [NSEntityDescription entityForName:@\"User\" inManagedObjectContext:backgroundContext];\n        NSManagedObject *object = [[NSManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:backgroundContext];\n        [object setValue:@\"Background\" forKey:@\"name\"];\n        [object setValue:[NSDate date] forKey:@\"createdDate\"];\n        [backgroundContext save:nil];\n    }];\n}\n```\n\nWhen using Xcode's Objective-C autocompletion the `backgroundContext` parameter name doesn't get included. Make sure to add it.\n\n## Clean up\n\nDeleting the `.sqlite` file and resetting the state of your **DATAStack** is as simple as just calling `drop`.\n\n**Swift**\n```swift\nself.dataStack.drop()\n```\n\n**Objective-C**\n```objc\n[self.dataStack forceDrop];\n```\n\n## Testing\n\n**DATAStack** is optimized for unit testing and it runs synchronously in testing enviroments. Hopefully you'll have to use less XCTestExpectations now.\n\nYou can create a stack that uses in memory store like this if your Core Data model is located in your app bundle:\n\n**Swift**\n```swift\nlet dataStack = DATAStack(modelName: \"MyAppModel\", bundle: NSBundle.mainBundle(), storeType: .InMemory)\n```\n\n**Objective-C**\n```objc\nDATAStack *dataStack = [[DATAStack alloc] initWithModelName:@\"MyAppModel\"\n                                                     bundle:[NSBundle mainBundle]\n                                                  storeType:DATAStackStoreTypeInMemory];\n```\n\nIf your Core Data model is located in your test bundle:\n\n**Swift**\n```swift\nlet dataStack = DATAStack(modelName: \"MyAppModel\", bundle: NSBundle(forClass: Tests.self), storeType: .InMemory)\n```\n\n**Objective-C**\n```objc\nDATAStack *dataStack = [[DATAStack alloc] initWithModelName:@\"MyAppModel\"\n                                                     bundle:[NSBundle bundleForClass:[self class]]\n                                                  storeType:DATAStackStoreTypeInMemory];\n```\n\n_(Hint: Maybe you haven't found the best way to use NSFetchedResultsController, well [here it is](https://github.com/SyncDB/DATASource).)_\n\n## Migrations\n\nIf `DATAStack` has troubles creating your persistent coordinator because a migration wasn't properly handled it will destroy your data and create a new sqlite file. The normal Core Data behaviour for this is making your app crash on start. This is not fun.\n\n## Installation\n\n**DATAStack** is available through [CocoaPods](http://cocoapods.org). To install it, simply add the following line to your Podfile:\n\n```ruby\nuse_frameworks!\n\npod 'DATAStack', '~\u003e 6'\n```\n\n**DATAStack** is also available through [Carthage](https://github.com/Carthage/Carthage). To install\nit, simply add the following line to your Cartfile:\n\n```ruby\ngithub \"SyncDB/DATAStack\" ~\u003e 6.0\n```\n\n## Be Awesome\n\nIf something looks stupid, please create a friendly and constructive issue, getting your feedback would be awesome.\n\nHave a great day.\n\n## Author\n\nElvis Nuñez, [@3lvis](https://twitter.com/3lvis)\n\n## License\n\n**DATAStack** is available under the MIT license. See the LICENSE file for more info.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F3lvis%2FDATAStack","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F3lvis%2FDATAStack","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F3lvis%2FDATAStack/lists"}