CocoaPods trunk is moving to be read-only. Read more on the blog, there are 19 months to go.
TestsTested | ✓ |
LangLanguage | SwiftSwift |
License | MIT |
ReleasedLast Release | Nov 2017 |
SwiftSwift Version | 4.0 |
SPMSupports SPM | ✗ |
Maintained by Rob Nash.
A lightweight convenience API for basic CoreData database tasks. Run the RecordsDemo
Xcode scheme for a demonstration.
Scalar or transformable types not supported
Consider the following database schema.
A class for entity 'Performer', may look like the following.
import Foundation
import CoreData
import Records
@objc(Performer)
public class Performer: NSManagedObject, Fetchable {
@NSManaged public var dob: Date
@NSManaged public var firstName: String
@NSManaged public var lastName: String
@NSManaged public var party: Party
@NSManaged public var performances: Set<Performance>?
}
// sourcery:inline:Performer.ManagedObject.Query.stencil
// sourcery:end
By declaring conformance to Fetchable
and adding annotation marks for sourcery, the following auto-completing syntax is at your disposal (after you compile).
let query = Performer.Query(dob: nil, firstName: "Maggie", lastName: nil, party: nil, performances: nil) // Fetch all with first name that BEGINSWITH[cd] `Maggie`
let performers: [Performer] = try! query.all(in: context)
Enjoy!
But wait?...sourcery?
Sourcery is a boiler-plate generation tool that you can optionally use with this framework. A pre-written stencil file is provided here which will instruct soucery to write the 'Query' syntax for any NSManagedObject subclass that implements Fetchable
.
Any change you make to your CoreData schema will trigger the regeneration of boiler-plate code. So for instance, if you removed the property lastName
from Performer
the new initialiser will be as follows.
let query = Performer.Query(dob: nil, firstName: "Maggie", party: nil, performances: nil)
let performers: [Performer] = try! query.all(in: context)
The Xcode compiler will highlight the changed initialiser at compile time. It's useful to individually evaluate each call site effected by your schema changes.
Take a look at the source in the RecordsDemo
target for more details on these features.
To-Many relationship queries.
let restriction = RelationshipRestriction(operation: .allMatching, records: Set(arrayLiteral: performerA, performerB))
let query = Performance.Query(performers: restriction, event: nil, ability: nil, group: nil)
let performances: [Performance] = try! query.all(in: context)
Null predicate searching.
let performer: Performer? = try! Performer.fetchFirst(in: context)
let performer: Performer? = try! Performer.fetchFirst(in: context, sortedBy: NSSortDescriptor(key: "firstName", ascending: true))
Custom predicates are still available.
let performers: [Performer] = try! Performer.fetchAll(withPredicate: NSPredicate(format: "firstName CONTAINS[cd] %@", "Maggie"), in: context)
Small UIViewController subclasses.
import UIKit
class PerformancesViewController: UIViewController {
var fetchedResultsController: PerformancesFetchedResultsController!
@IBOutlet private weak var tableView: PerformancesTableView! {
didSet {
fetchedResultsController.delegate = tableView
fetchedResultsController.dataSource = tableView
tableView.dataSource = fetchedResultsController
tableView.delegate = fetchedResultsController
}
}
override func viewDidLoad() {
super.viewDidLoad()
title = "Performances"
fetchedResultsController.selectPerformance = { performance in
/// do something
}
}
}
String replacement with Enum.
let query = Party.Query(email: email, name: name, phone: phone, performers: nil, type: .school)
To use an enum set the string property on your Entity subclass to private. Then create a var
for your enum.
import Foundation
import CoreData
import Records
@objc(Party)
public class Party: NSManagedObject, Fetchable {
@NSManaged public var email: String
@NSManaged public var name: String
@NSManaged public var phone: String
@NSManaged private var type: String
@NSManaged public var performers: Set<Performer>?
public enum PartyType: String {
case school = "School"
case independent = "Independent"
}
public var type_: PartyType {
get {
return PartyType(rawValue: type)!
}
set {
type = newValue.rawValue
}
}
}
Make sure to set a default value on the property and write a unit test (see here).
For the latest release, select the release tab.
Add github "rob-nash/Records"
to your Cartfile
.
Add pod "Records"
to your Podfile
.
If you like this and you want to buy me a drink, use bitcoin.
Bitcoin Address: 15Gj4DBTzSujnJrfRZ6ivrR9kDnWXNPvNQ