• Stars
    star
    302
  • Rank 138,002 (Top 3 %)
  • Language
    Swift
  • License
    MIT License
  • Created almost 10 years ago
  • Updated about 6 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

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

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.

More Repositories

1

AEXML

Swift minion for simple and lightweight XML parsing
Swift
996
star
2

AEIconizer

Sketch plugin for automatic scaling of iOS app icon artwork in all needed sizes
441
star
3

AEFlowchart

Sketch plugin for fast and convenient creation of flowcharts
378
star
4

xcode-project-renamer

Swift script for renaming Xcode project
Swift
354
star
5

AEAccordion

Simple and lightweight UITableViewController with accordion effect (expand / collapse cells)
Swift
210
star
6

AEConsole

Customizable Console UI overlay with debug log on top of your iOS App
Swift
148
star
7

AEConicalGradient

Conical (angular) gradient for iOS written in Swift
Swift
83
star
8

TouchDemo

Demo from WWDC 2014 Session 235 - Advanced Scrollviews and Touch Handling Techniques
Swift
38
star
9

AELog

Simple, lightweight and flexible debug logging framework written in Swift
Swift
31
star
10

AEViewModel

Swift minion for convenient creation of tables and collection views
Swift
19
star
11

AEImage

Adaptive image viewer for iOS (with support for zoom, gyro motion and infinite scroll)
Swift
17
star
12

swift-greenfield

greenfield swift app project
Swift
12
star
13

AEAppVersion

Simple and Lightweight App Version Tracking for iOS written in Swift
Swift
12
star
14

AECoreDataUI

Super awesome Core Data driven UI for iOS written in Swift
Swift
11
star
15

AEDotFiles

From vanilla to personalized macOS in less than 30 minutes
Shell
11
star
16

bitrise-step-xcode-project-info

Bitrise step which extracts Xcode project information to environment variables
Shell
9
star
17

AETransition

Custom transitions for iOS - simple yet powerful
Swift
4
star
18

AESound

Convenience API for playing iOS system sounds
Swift
3
star
19

SwiftLook

Swift file viewer for iOS - it's like a QuickLook for Swift files
Swift
3
star
20

AECli

Swift package for making simple command line tools
Swift
3
star
21

AENetwork

Simple and lightweight networking in Swift
Swift
2
star
22

cs193p-matchismo

CS193p Winter 2013 - Matchismo - Card matching game
Objective-C
2
star
23

AECoreDataDemo

Demo project for AERecord and AECoreDataUI
Swift
2
star
24

swift-minions

Single-file helpers written in Swift, reusable across multiple projects
Swift
2
star
25

mappable

Swift package for simple and lightweight models mapping (with JSON support out of the box)
Swift
2
star
26

ae

command line personal assistant
Swift
1
star
27

AETool

Swift package for driving "ae" - command line personal assistant
Swift
1
star