Super awesome Swift minion for Core Data (iOS, macOS, tvOS)

Last update: Jan 29, 2022

Swift 4.2 Platforms iOS | watchOS | tvOS | macOS CocoaPods Carthage Swift Package Manager License MIT

⚠️ 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 and 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

License

AERecord is released under the MIT license. See LICENSE for details.

GitHub

https://github.com/tadija/AERecord
Comments
  • 1. Swift 2.0 support

    Thanks for creating and sharing this library with the world, it's proving quite helpful.

    What plans (if any) do you have for supporting Swift 2.0?

    Thanks.

    Reviewed by jamesbebbington at 2015-06-16 10:37
  • 2. I guess, Stack class name conflicting in my Project with some other framework

    Also another issue: /Users/.../Pods/AERecord/Sources/AERecord.swift:69:82: Class 'Stack' is internal and cannot be referenced from a default argument value (multiple time this issue for different methods/properties) /Users/.../Pods/AERecord/Sources/Query.swift:581:71: Static let 'defaultPredicateType' is private and cannot be referenced from a default argument value (multiple time this issue for different methods/properties)

    I tested your classes in your test project AECoreDataDemo, and its working fine. Suggest me what I do?

    Reviewed by ods2-hamid at 2018-01-16 08:25
  • 3. Add Dynamic Framework support & Carthage support

    This pull request adds iOS, tvOS and OSX targets with shared schemes (for installation via Carthage) and configures those to work as a dynamic framework. Also a section to the README about Carthage installation was added.

    This should solve #8.

    Reviewed by Jeehut at 2016-01-12 20:32
  • 4. Swift2

    Hello @tadija, I've migrated the AERecord code base to swift 2.0 syntax. The migration tool wasn't very helpful here because we had a lot of do try catch usecases to handle. I've also removed a few as? conversions because most CoreData methods uses the proper classes now (rather than AnyObject).

    Let me know if you have any questions or feedback.

    Reviewed by apouche at 2015-06-24 15:06
  • 5. I'm getting this error on latest version of AERecord

    I did a pod update and i started facing this error. This problem is on 3.0.0 on 2.1.0 it works fine

     private class func _firstOrCreateWithAttributes<T>(attributes: [String : AnyObject], predicateType: NSCompoundPredicateType = defaultPredicateType, context: NSManagedObjectContext = AERecord.defaultContext) -> T {
            let predicate = createPredicateForAttributes(attributes, predicateType: predicateType)
            let request = createFetchRequest(predicate: predicate)
            request.fetchLimit = 1
            let objects = AERecord.executeFetchRequest(request, context: context)
    
            return (objects.first ?? createWithAttributes(attributes, context: context)) as! T //Here i get the error
        }
    

    ERROR

    Could not cast value of type 'NSManagedObject_AccountDetails_' (0x7fd43ae881b0) to 'FeedbackChamp.AccountDetails' (0x1081b1220).

    MY CODE

    AccountDetails.firstOrCreateWithAttributes(["data" : readableJSON["result"]["hoteladded"].bool! ? 1 : 0, "detailName": "num_hotels"])
    
    AccountDetails.firstOrCreateWithAttributes(["data" : readableJSON["result"]["num_restaurants"].int!, "detailName": "num_restaurants"])
    
    AERecord.saveContextAndWait()
    
    

    Please fix it as soon as posible

    Reviewed by O-mkar at 2016-06-09 05:03
  • 6. Updated README to reflect correct delete function

    I believe the correct delete function is model.deleteFromContext() rather than model.delete() where model is an instantiated NSManagedObject subclass. I looked through the source to find a reference to delete() and deleteFromContext() was the closest I came to finding something similar.

    If you wanted to implement the delete() function for simplicities sake, you could just map it directly to deleteFromContext() given that the context var is optional and automatically assigned to the default context if not set.

    Reviewed by maxkramer at 2016-06-08 14:59
  • 7. Generic version of methods for creating and finding

    In order to be able to write

    let user: User = User.firstOrCreateWithAttribute("id", value: 123)
    

    or

    func newUser() -> User {
        return User.firstOrCreateWithAttribute("id", value: 123)
    }
    

    instead of

    let user = User.firstOrCreateWithAttribute("id", value: 123) as! User
    

    or

    func newUser() -> User {
        return User.firstOrCreateWithAttribute("id", value: 123) as! User
    }
    
    Reviewed by kafejo at 2016-03-06 16:35
  • 8. tvOS support

    I've updated podspec file and added support for specifying NSSearchPathDirectory for method storeURLForName. The reason is that app cannot access Documents directory on real device, and CachesDirectory must be used.

    Reviewed by jakubknejzlik at 2015-11-11 01:38
  • 9. Property suspendAutomaticTrackingOfChangesInManagedObjectContext is private

    I don't know if I'm missing the point here, but suspendAutomaticTrackingOfChangesInManagedObjectContext is definitely marked as private and therefore can not be changed from anywhere outside the AERecird.swift file.

    Reviewed by marioradonic at 2015-06-26 10:32
  • 10. Swift 1.2 Support

    Hi,

    is there any chance of this (and AEXML) getting updated to Swift 1.2? All the other frameworks i am using already have a 1.2 branch. If there is no plan to do this i would it myself but otherwise it would be a waste of time :).

    Reviewed by Harper04 at 2015-02-28 17:54
  • 11. Download and Save Async Data in Multiple Threads

    hey Marko,

    i have an issue and i-m thinking that i doing something wrong with saving or creating/mapping CoreDataModels while getting data from a Webservice. Situation:

    1. I download from a Webservice all users cardboxes and serialize the Json into an DTO Object and then map the DTO to the CoreData DBOCardBoxModel
    2. ForEach downloaded and mapped Cardbox download the Cards async 2.1) When the Api Call is finished, serialize the Json into a DTO Object 2.1.1) Then i want create a new CoreDataModel when the DTO.cardNbr not exists, else get first and map then the properties from the dto to dbo 2.1.2) In the Mapper.Map(dto->dbo) i want to map all the properties and set relations, so in example a card can have multiple choice answers, so i want to create them and add this relation to the card

    Exception throw at the firstOrCreateWithAttributes methode when my call was for example 25 times called, when it called 5 times the exception didnt throw. I think it is because the NSManagementObjectContext is not on each thread, how can i handle this?

    Here is some of my Code: I using the following extensions:

    • Api: http://vluxe.io/swifthttp.html
    • JSON serialize: https://github.com/daltoniam/JSONJoy-Swift

    Another question from me is where i place my the Save funktion? I¥m not shure about this. 1.) The Api Call that will call 25 Times: (the self.saveDB will call the saveAndWait(default) funktion)

    public func ActiveCardBoxesById(dboCardBoxes : Array<String>){
            //let operationQueue = NSOperationQueue()
            //operationQueue.maxConcurrentOperationCount = dboCardBoxes.count
            for cardBox in dboCardBoxes {
                if self.CanSendRequest() {
                    var request = self.CreateBaseRequest()
                    request.requestSerializer.headers["clientid"] = self.UniqueId
                    request.GET("/cardbox/\(cardBox)/cards", parameters: nil, success: {(response: HTTPResponse) -> Void in
                        if (response.responseObject != nil) {
                            //TODO
                            let dtoCards = Cards(JSONDecoder(response.responseObject!))
                            for dtoCard in dtoCards.cards! {
                                var dboCard = DBOCard.firstOrCreateWithAttribute("cardNbr", value: dtoCard.cardNbr!) as DBOCard
                                Mapper.Map(dtoCard, dbo: dboCard)
                            }
    
                            self.dataDelegate?.ConfirmLastSyncCardBox!()
                            self.logger.info("ConfirmLastSyncCardBox \(cardBox)")
                        }
                        }, failure: {(error: NSError, response: HTTPResponse?) -> Void in
                            self.logger.error("Getting ActiveCardboxesById throw error : \(error)")
                            self.baseDelegate?.ErrorInWebService(error)
                    })
    
    
                }
                else {
                    logger.warn("Can not communicate with API")
                    self.baseDelegate?.ErrorSendingRequest()
                }
            }
            self.saveDB()
    
        }
    
    

    2.) This is the Mapper.Map methode: (the self.saveDB will call the saveAndWait(default) funktion)

    class func Map(dto : DTOCard, dbo : DBOCard) -> DBOCard {
            if let cardNbr = dto.cardNbr {
                dbo.setValue(cardNbr, forKey: "cardNbr")
            }
            if let cardBoxNbr = dto.cardBoxNbr {
                dbo.setValue(cardBoxNbr, forKey: "cardBoxNbr")
            }
            if let daystowait = dto.daystowait {
                dbo.setValue(daystowait, forKey: "daystowait")
            }
            if let delay = dto.delay {
                dbo.setValue(delay, forKey: "delay")
            }
            if let favorite = dto.favorite {
                dbo.setValue(favorite, forKey: "favorite")
            }
            if let knownInPlannedRow = dto.knownInPlannedRow {
                dbo.setValue(knownInPlannedRow, forKey: "knownInPlannedRow")
            }
            if let knownInRow = dto.knownInRow {
                dbo.setValue(knownInRow, forKey: "knownInRow")
            }
            if let lastPlannedPlayed = dto.lastPlannedPlayed {
                dbo.setValue(lastPlannedPlayed, forKey: "lastPlannedPlayed")
            }
            if let lastPlayed = dto.lastPlayed {
                dbo.setValue(lastPlayed, forKey: "lastPlayed")
            }
            if let multipleChoice = dto.multipleChoice {
                dbo.setValue(multipleChoice, forKey: "multipleChoice")
            }
            if let timesKnown = dto.timesKnown {
                dbo.setValue(timesKnown, forKey: "timesKnown")
            }
            if let timesNotKnown = dto.timesNotKnown {
                dbo.setValue(timesNotKnown, forKey: "timesNotKnown")
            }
            if let selectedForLearning = dto.selectedForLearning {
                dbo.setValue(selectedForLearning, forKey: "selectedForLearning")
            }
            if let delete = dto.delete {
                dbo.setValue(delete, forKey: "delete")
            }
            if let answer = dto.answer {
                dbo.setValue(answer, forKey: "answer")
            }
            if let answerImage = dto.answerImage {
                dbo.setValue(answerImage, forKey: "answerImage")
            }
            if let answerPureText = dto.answerPureText {
                dbo.setValue(answerPureText, forKey: "answerPureText")
            }
            if let question = dto.question {
                dbo.setValue(question, forKey: "question")
            }
            if let questionImage = dto.questionImage {
                dbo.setValue(questionImage, forKey: "questionImage")
            }
            if let questionPureText = dto.questionPureText {
                dbo.setValue(questionPureText, forKey: "questionPureText")
            }
    
            if let dtoMultipleChoices = dto.multipleChoiceCards {
                var counter = 1
                for dtoMultipleChoice in dtoMultipleChoices {
                    var acessableOrderIndex = counter
                    if let orderIndex = dtoMultipleChoice.orderIndex {
                        acessableOrderIndex = orderIndex
                    }
                    //TODO LOOK FIRST FOR CARDID AND ORDERINDEX
                    let predicate = NSPredicate(format: "cardId = \(dtoMultipleChoice.cardId! + counter) AND orderIndex = \(acessableOrderIndex)")
                    var mappedMultipleChoice : DBOMultipleChoice
                    if let existingDboMultipleChoice = DBOMultipleChoice.firstWithPredicate(predicate!) as? DBOMultipleChoice {
                        mappedMultipleChoice = self.Map(dtoMultipleChoice, dbo: existingDboMultipleChoice)
                        mappedMultipleChoice.setValue(acessableOrderIndex, forKey: "orderIndex")
                    }
                    else {
                        var dboMultipleChoice = DBOMultipleChoice.firstOrCreateWithAttribute("cardId", value: dtoMultipleChoice.cardId! + counter) as DBOMultipleChoice
                        mappedMultipleChoice = self.Map(dtoMultipleChoice, dbo: dboMultipleChoice)
                        mappedMultipleChoice.setValue(acessableOrderIndex, forKey: "orderIndex")
                    }
    
                    dbo.addMultipleChoice(mappedMultipleChoice)
                }
                counter = 1
            }
            if let dtoCategories = dto.categories {
                for dtoCategory in dtoCategories {
                    var dboCategory = DBOCategory.firstOrCreateWithAttribute("categoryId", value: dtoCategory.categoryId!) as DBOCategory
                    var mappedCategory = self.Map(dtoCategory, dbo: dboCategory)
                    mappedCategory.addCard(dbo)
                    //add category to card
                    dbo.addCategorie(mappedCategory)
                    //add card to category
    
                }
            }
    //        //get cardbox and add card
            if let dboCardBox = DBOCardBox.firstWithAttribute("cardBoxNbr", value: "\(dbo.cardBoxNbr)") as? DBOCardBox {
                //we have an cardbox
                dboCardBox.addCard(dbo)
                dbo.cardInCardBox = dboCardBox
            }
            self.save()
            return dbo
        }
    

    Exceptions sometimes dangling with reference Dangling reference to an invalid object.=null, NSValidationErrorValue

    Or Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <__NSCFSet: 0x7fc1aa487870> was mutated while being enumerated.'

    XCode Version: 6.1

    Reviewed by kheinrich188 at 2014-12-23 10:02
  • 12. Could you give me some tips to the crash `*** Collection <__NSCFSet: 0x28355f810> was mutated while being enumerated.`

    the code is:

        func conversation(whereChatId: String) -> Conversation? {
            guard AERecord.Context.default.persistentStoreCoordinator != nil else {
                return nil
            }
            let predicate = NSPredicate.init(format: "chatId=%@", whereChatId)
            let con = Conversation.first(with: predicate)
            return con
        }
    

    the crash is:

    *** Collection <__NSCFSet: 0x28355f810> was mutated while being enumerated.
    ClouderWork + 8451948
    

    I have got this error some times in my project using AERecord, would you please help me to fix it? I can't fix it by myself, I need your help! Very thanks!

    Reviewed by Insfgg99x at 2020-11-23 03:00
  • 13. How to do this in AERecord

    Sum a property:

        func totalUnreadCount(whereParentChatId: String?) -> Int {
            let req = NSFetchRequest<NSDictionary>.init(entityName: Conversation.entityName())
            if let parentChatId = whereParentChatId {
                req.predicate = NSPredicate.init(format: "parentChatId=%@", parentChatId)
            } else {
                req.predicate = NSPredicate.init(format: "parentChatId = nil")
            }
            let expressDescription = NSExpressionDescription.init()
            let express = NSExpression.init(format: "@sum.unreadCount")
            expressDescription.expression = express
            expressDescription.name = "total"
            expressDescription.expressionResultType = .integer32AttributeType
            req.propertiesToFetch = [expressDescription]
            req.resultType = .dictionaryResultType
            var count = 0
            dbContext().performAndWait {
                let result = try? dbContext().fetch(req)
                if let total = result?.first?["total"] as? Int {
                    count = total
                }
            }
            return count
        }
    
    Reviewed by Insfgg99x at 2019-05-25 05:08
  • 14. iCloud support

    Hi,

    In the readme it is mentioned that AERecord supports iCloud. Besides notification references in the code, I could not find how to set up CloudKit syncing.

    Is there any documentation or references regarding iCloud sync?

    Reviewed by wousser at 2018-01-07 15:22
  • 15. Question: mergePolicy

    I've tried setting the mergePolicy by loading AERecord with the myOptions parameters, but the mergePolicy option or configuration is not read correctly.

    Currently I'm using this code to set the mergePolicy, is this the best (or only) way to do this?

    AERecord.Context.default.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy AERecord.Context.background.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy AERecord.Context.main.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy

    Full loading code:

    ` let myOptions = [NSMigratePersistentStoresAutomaticallyOption: true, NSInferMappingModelAutomaticallyOption : true] do { try AERecord.loadCoreDataStack(options: myOptions) AERecord.Context.default.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy AERecord.Context.background.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy AERecord.Context.main.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy

    } catch { debugPrint(error) } `

    Reviewed by wousser at 2017-01-17 09:35
  • 16. EXC_BAD_INSTRUCTION DispatchQueue

    If I want to create an NSManagedObject in a background thread than EXC_BAD_INSTRUCTION (code=EXC_i386_INVOP, subcode=0x0) arise.

    @discardableResult class func create(in context: NSManagedObjectContext = AERecord.Context.default) -> Self { let entityDescription = NSEntityDescription.entity(forEntityName: entityName, in: context)! let object = self.init(entity: entityDescription, insertInto: context) // error line Line 104 in Query.swift return object }

    Part of my code: DispatchQueue.global(qos: .background).async{ let model = Model.create() }

    Do you know what's going wrong? Thank you for your efforts

    Reviewed by JohnDevC at 2016-11-10 17:25
Related tags
JSON to Core Data and back. Swift Core Data Sync.
JSON to Core Data and back. Swift Core Data Sync.

Notice: Sync was supported from it's creation back in 2014 until March 2021 Moving forward I won't be able to support this project since I'm no longer

Jun 8, 2022
Core Data Generator (CDG for short) is a framework for generation (using Sourcery) of Core Data entities from plain structs/classes/enums.
Core Data Generator (CDG for short) is a framework for generation (using Sourcery) of Core Data entities from plain structs/classes/enums.

Core Data Generator Introduction Features Supported platforms Installation CDG Setup RepositoryType ModelType DataStoreVersion MigrationPolicy Basic U

Feb 7, 2022
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

May 11, 2022
JustPersist is the easiest and safest way to do persistence on iOS with Core Data support out of the box.
JustPersist is the easiest and safest way to do persistence on iOS with Core Data support out of the box.

JustPersist 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

Mar 13, 2022
SwiftUI - iOS notes App that integrates Core Data with SwiftUI App Life Cycle
SwiftUI - iOS notes App that integrates Core Data with SwiftUI App Life Cycle

Devote (Notes App) SwiftUI Masterclass project Integration between Core Data and SwiftUI App Life Cycle Custom Toggle style and checkbox Read, Update

Mar 16, 2022
A powerful and elegant Core Data framework for Swift.
A powerful and elegant Core Data framework for Swift.

A powerful and elegant Core Data framework for Swift. Usage Beta version. New docs soon... Simple do that: let query = persistentContainer.viewContext

May 23, 2022
CloudCore is a framework that manages syncing between iCloud (CloudKit) and Core Data written on native Swift.
CloudCore is a framework that manages syncing between iCloud (CloudKit) and Core Data written on native Swift.

CloudCore CloudCore is a framework that manages syncing between iCloud (CloudKit) and Core Data written on native Swift. Features Leveraging NSPersist

Jun 23, 2022
Unleashing the real power of Core Data with the elegance and safety of Swift
 Unleashing the real power of Core Data with the elegance and safety of Swift

Unleashing the real power of Core Data with the elegance and safety of Swift Dependency managers Contact Swift 5.4: iOS 11+ / macOS 10.13+ / watchOS 4

Jun 25, 2022
HitList is a Swift App shows the implementation of Core Data.
HitList is a Swift App shows the implementation of Core Data.

HitList HitList is a Swift App shows the implementation of Core Data. It is the demo app of Ray Wenderlich's tech blog. For details please reference G

Dec 17, 2021
A type-safe, fluent Swift library for working with Core Data
A type-safe, fluent Swift library for working with Core Data

Core Data Query Interface (CDQI) is a type-safe, fluent, intuitive library for working with Core Data in Swift. CDQI tremendously reduces the amount o

Jun 27, 2020
100% Swift Simple Boilerplate Free Core Data Stack. NSPersistentContainer
100% Swift Simple Boilerplate Free Core Data Stack. NSPersistentContainer

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 wi

Jun 7, 2022
This project server as a demo for anyone who wishes to learn Core Data in Swift.

CoreDataDemo This project server as a demo for anyone who wishes to learn Core Data in Swift. The purpose of this project is to help someone new to Co

May 3, 2022
A type-safe, fluent Swift library for working with Core Data
A type-safe, fluent Swift library for working with Core Data

Core Data Query Interface (CDQI) is a type-safe, fluent, intuitive library for working with Core Data in Swift. CDQI tremendously reduces the amount o

Jun 27, 2020
JSQCoreDataKit - A swifter Core Data stack

JSQCoreDataKit A swifter Core Data stack About This library aims to do the following: Encode Core Data best practices, so you don't have to think "is

Jun 17, 2022
QueryKit, a simple type-safe Core Data query language.
QueryKit, a simple type-safe Core Data query language.

QueryKit QueryKit, a simple type-safe Core Data query language. Usage QuerySet<Person>(context, "Person")

Jun 16, 2022
A synchronization framework for Core Data.

Core Data Ensembles Author: Drew McCormack Created: 29th September, 2013 Last Updated: 15th February, 2017 Ensembles 2 is now available for purchase a

Jun 12, 2022
Core Data code generation

mogenerator Visit the project's pretty homepage. Here's mogenerator's elevator pitch: mogenerator is a command-line tool that, given an .xcdatamodel f

Jun 21, 2022
A feature-light wrapper around Core Data that simplifies common database operations.
A feature-light wrapper around Core Data that simplifies common database operations.

Introduction Core Data Dandy is a feature-light wrapper around Core Data that simplifies common database operations. Feature summary Initializes and m

May 11, 2022
The Big Nerd Ranch Core Data Stack
The Big Nerd Ranch Core Data Stack

BNR Core Data Stack The BNR Core Data Stack is a small Swift framework that makes it both easier and safer to use Core Data. A better fetched results

Jun 6, 2022