AERecord alternatives and similar libraries
Based on the "Core Data" category.
Alternatively, view AERecord alternatives based on common mentions on social networks and blogs.
-
PrediKit
An NSPredicate DSL for iOS, OSX, tvOS, & watchOS. Inspired by SnapKit and lovingly written in Swift. -
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 Data. Swift flavour. -
JustPersist
DISCONTINUED. JustPersist is the easiest and safest way to do persistence on iOS with Core Data support out of the box. It also allows you to migrate to any other persistence framework with minimal effort. -
SLRESTfulCoreData
Objc naming conventions, autogenerated accessors at runtime, URL substitutions and intelligent attribute mapping -
CloudCore
Robust CoreData-CloudKit synchronization, including offline queuing, relationships, private, shared and public databases, field-level deltas, encrypted values, maskable attributes, cacheable assets, and more. -
Cadmium
A Swift framework that wraps CoreData, hides context complexity, and helps facilitate best practices. -
CoreDataDandy
DISCONTINUED. A feature-light wrapper around Core Data that simplifies common database operations.
CodeRabbit: AI Code Reviews for Developers
* Code Quality Rankings and insights are calculated and provided by Lumnify.
They vary from L1 to L5 with "L5" being the highest.
Do you think we are missing an alternative of AERecord or a related project?
README
⚠️ Since this repository is going to be archived soon, I suggest migrating to NSPersistentContainer instead (available since iOS 10). For other convenience helpers, beside managing stack, I'm currently just using this.
AERecord
Super awesome Swift minion for Core Data (iOS, macOS, tvOS)
I made this for personal use, but feel free to use it or contribute. For more examples check out [Sources](Sources) and [Tests](Tests).
Index
Intro
AECoreDataUI was previously part of AERecord, so you may want to check that also.
Why do we need yet another one Core Data wrapper? You tell me!
Inspired by many different (spoiler alert) magical solutions, I wanted something which combines complexity and functionality just about right.
All that boilerplate code for setting up of Core Data stack, passing the right NSManagedObjectContext
all accross the project and different threads, not to mention that boring NSFetchRequest
boilerplates for any kind of creating or querying the data - should be more simple with this.
Features
- Create default or custom Core Data stack (or more stacks) easily accessible from everywhere
- Have main and background contexts, always in sync, but don't worry about it
- CRUD data in many ways with generic one liners
- iCloud support
- Covered with unit tests
- Covered with inline docs
Usage
You may see this demo project for example.
Create Core Data stack
Almost everything in AERecord
is made with 'optional' parameters (which have default values if you don't specify anything).
So you can load (create if doesn't already exist) CoreData stack like this:
do {
try AERecord.loadCoreDataStack()
} catch {
print(error)
}
or like this:
let myModel: NSManagedObjectModel = AERecord.modelFromBundle(for: MyClass.self)
let myStoreType = NSInMemoryStoreType
let myConfiguration = ...
let myStoreURL = AERecord.storeURL(for: "MyName")
let myOptions = [NSMigratePersistentStoresAutomaticallyOption : true]
do {
try AERecord.loadCoreDataStack(managedObjectModel: myModel, storeType: myStoreType, configuration: myConfiguration, storeURL: myStoreURL, options: myOptions)
} catch {
print(error)
}
or any combination of these.
If for any reason you want to completely remove your stack and start over (separate demo data stack for example) you can do it as simple as this:
do {
try AERecord.destroyCoreDataStack() // destroy default stack
} catch {
print(error)
}
do {
let demoStoreURL = AERecord.storeURL(for: "Demo")
try AERecord.destroyCoreDataStack(storeURL: demoStoreURL) // destroy custom stack
} catch {
print(error)
}
Similarly you can delete all data from all entities (without messing with the stack) like this:
AERecord.truncateAllData()
Context operations
Context for current thread (Context.default
) is used if you don't specify any (all examples below are using Context.default
).
// get context
AERecord.Context.main // get NSManagedObjectContext for main thread
AERecord.Context.background // get NSManagedObjectContext for background thread
AERecord.Context.default // get NSManagedObjectContext for current thread
// execute NSFetchRequest
let request = ...
let managedObjects = AERecord.execute(fetchRequest: request) // returns array of objects
// save context
AERecord.save() // save default context
AERecord.saveAndWait() // save default context and wait for save to finish
// turn managed objects into faults (you don't need this often, but sometimes you do)
let objectIDs = ...
AERecord.refreshObjects(with: [objectIDs], mergeChanges: true) // turn objects for given IDs into faults
AERecord.refreshRegisteredObjects(mergeChanges: true) // turn all registered objects into faults
Easy Queries
Easy querying helpers are created as NSManagedObject
extension.
All queries are called on generic NSManagedObject
, and Context.default
is used if you don't specify any (all examples below are using Context.default
). All finders have optional parameter for NSSortDescriptor
which is not used in these examples.
For even more examples check out unit tests.
General
If you need custom NSFetchRequest
, you can use createPredicate(with:)
and createFetchRequest(predicate:sortdDescriptors:)
, tweak it as you wish and execute with AERecord
.
// create request for any entity type
let attributes = ...
let predicate = NSManagedObject.createPredicate(with: attributes)
let sortDescriptors = ...
let request = NSManagedObject.createFetchRequest(predicate: predicate, sortDescriptors: sortDescriptors)
// set some custom request properties
request.someProperty = someValue
// execute request and get array of entity objects
let managedObjects = AERecord.execute(fetchRequest: request)
Of course, all of the often needed requests for creating, finding, counting or deleting entities are already there, so just keep reading.
Create
NSManagedObject.create() // create new object
let attributes = ...
NSManagedObject.create(with: attributes) // create new object and sets it's attributes
NSManagedObject.firstOrCreate(with: "city", value: "Belgrade") // get existing object (or create new if it doesn't already exist) with given attribute
let attributes = ...
NSManagedObject.firstOrCreate(with: attributes) // get existing object (or create new if it doesn't already exist) with given attributes
Find first
NSManagedObject.first() // get first object
let predicate = ...
NSManagedObject.first(with: predicate) // get first object with predicate
NSManagedObject.first(with: "bike", value: "KTM") // get first object with given attribute name and value
let attributes = ...
NSManagedObject.first(with: attributes) // get first object with given attributes
NSManagedObject.first(orderedBy: "speed", ascending: false) // get first object ordered by given attribute name
Find all
NSManagedObject.all() // get all objects
let predicate = ...
NSManagedObject.all(with: predicate) // get all objects with predicate
NSManagedObject.all(with: "year", value: 1984) // get all objects with given attribute name and value
let attributes = ...
NSManagedObject.all(with: attributes) // get all objects with given attributes
Delete
let managedObject = ...
managedObject.delete() // delete object (call on instance)
NSManagedObject.deleteAll() // delete all objects
NSManagedObject.deleteAll(with: "fat", value: true) // delete all objects with given attribute name and value
let attributes = ...
NSManagedObject.deleteAll(with: attributes) // delete all objects with given attributes
let predicate = ...
NSManagedObject.deleteAll(with: predicate) // delete all objects with given predicate
Count
NSManagedObject.count() // count all objects
let predicate = ...
NSManagedObject.count(with: predicate) // count all objects with predicate
NSManagedObject.count(with: "selected", value: true) // count all objects with given attribute name and value
let attributes = ...
NSManagedObject.count(with: attributes) // count all objects with given attributes
Distinct
do {
try NSManagedObject.distinctValues(for: "city") // get array of all distinct values for given attribute name
} catch {
print(error)
}
do {
let attributes = ["country", "city"]
try NSManagedObject.distinctRecords(for: attributes) // get dictionary with name and values of all distinct records for multiple given attributes
} catch {
print(error)
}
Auto Increment
If you need to have auto incremented attribute, just create one with Int type and get next ID like this:
NSManagedObject.autoIncrementedInteger(for: "myCustomAutoID") // returns next ID for given attribute of Integer type
Turn managed object into fault
NSFetchedResultsController
is designed to watch only one entity at a time, but when there is a bit more complex UI (ex. showing data from related entities too),
you sometimes have to manually refresh this related data, which can be done by turning 'watched' entity object into fault.
This is shortcut for doing just that (mergeChanges
parameter defaults to true
). You can read more about turning objects into faults in Core Data documentation.
let managedObject = ...
managedObject.refresh() // turns instance of managed object into fault
Batch update
Batch updating is the 'new' feature from iOS 8. It's doing stuff directly in persistent store, so be carefull with this and read the docs first. Btw, NSPredicate
is also optional parameter here.
NSManagedObject.batchUpdate(properties: ["timeStamp" : NSDate()]) // returns NSBatchUpdateResult?
NSManagedObject.objectsCountForBatchUpdate(properties: ["timeStamp" : NSDate()]) // returns count of updated objects
NSManagedObject.batchUpdateAndRefreshObjects(properties: ["timeStamp" : NSDate()]) // turns updated objects into faults after updating them in persistent store
Installation
-
.Package(url: "https://github.com/tadija/AERecord.git", majorVersion: 4)
-
github "tadija/AERecord"
-
pod 'AERecord'
License
AERecord is released under the MIT license. See [LICENSE](LICENSE) for details.
*Note that all licence references and agreements mentioned in the AERecord README section above
are relevant to that project's source code only.