PeakCoreData is a Swift microframework providing enhancements and conveniences to Core Data
. It is part of the Peak Framework.
The ManagedObjectObserver
class can be used to observe changes made to a single managed object. State changes include when it is refreshed, updated or deleted.
var event: Event!
var eventObserver: ManagedObjectObserver<Event>!
override func viewDidLoad() {
super.viewDidLoad()
eventObserver = ManagedObjectObserver(managedObject: event)
eventObserver.startObserving() { [weak self] obj, changeType in
guard let strongSelf = self else { return }
switch changeType {
case .initialised, .refreshed, .updated:
strongSelf.updateView()
case .deleted:
strongSelf.navigationController?.popToRootViewController(animated: true)
}
}
}
The CountObserver
class can be used to observe changes to the number of NSManagedObject
objects as defined by a generic type and an optional NSPredicate
.
var countObserver: CountObserver<Event>!
override func viewDidLoad() {
super.viewDidLoad()
let predicate = NSPredicate(format: "%K == false", argumentArray: [#KeyPath(Event.isHidden)])
countObserver = CountObserver<Event>(predicate: predicate, context: viewContext)
countObserver.startObserving() { [weak self] count in
guard let strongSelf = self else { return }
strongSelf.countLabel.text = String(count)
}
}
FetchedCollection
is a wrapper for NSFetchedResultsController
which acts as its own delegate and exposes changes though a closure.
let fetchedCollection = FetchedCollection(fetchRequest: Event.sortedFetchRequest(), context: viewContext)
fetchedCollection.onChange = { collection, update in
// use collection, or process updates
}
// subscriptable
let object = fetchedCollection[0, 0]
// or with a tuple
let object = fetchedCollection[(0, 0)]
// or with an index path
let object = fetchedCollection[IndexPath(row: 0, section: 0)]
This allows you to decouple the NSFetchedResultsController
from your viewcontroller.
These classes take care of the boiler-plate code needed to use a NSFetchedResultsController
with a UITableView
or UICollectionView
.
class EventsTableViewController: UITableViewController {
var dataSource: FetchedTableViewDataSource<EventsTableViewController>!
override func viewDidLoad() {
super.viewDidLoad()
let frc = NSFetchedResultsController(
fetchRequest: Event.sortedFetchRequest(),
managedObjectContext: viewContext,
sectionNameKeyPath: nil,
cacheName: nil
)
dataSource = FetchedTableViewDataSource(
tableView: tableView,
cellIdentifier: EventTableViewCell.cellIdentifier,
fetchedResultsController: frc,
delegate: self
)
dataSource.animateUpdates = true
dataSource.onDidChangeContent = {
print("Something changed")
}
dataSource.performFetch()
}
}
extension EventsTableViewController: FetchedTableViewDataSourceDelegate {
func identifier(forCellAt indexPath: IndexPath) -> String {
return EventTableViewCell.cellIdentifier
}
func configure(_ cell: EventTableViewCell, with object: Event) {
cell.textLabel?.text = object.date?.description
}
}
CoreDataOperation
is a concurrent Operation
subclass that can be used to perform core data tasks on a background thread. To use, simply subclass CoreDataOperation
then override the performWork(in:)
method.
Things to note about this operation:
CoreDataOperation
simply wraps theperformBackgroundTask((NSManagedObjectContext) -> Void)
method onNSPersistentContainer
in a operation.- To finish the operation you must call
saveAndFinish()
. - Changes will only be merged in to your
viewContext
if you have set theautomaticallyMergesChangesFromParent
onviewContext
totrue
. CoreDataOperation
conforms toProducesResult
and so can be used to produce aResult
.
A CoreDataOperation
subclass that returns a Changeset
struct containing all the NSManagedObjectID
objects that were inserted and updated during the operation.
Two CoreDataChangesetOperation
subclasses that can be used to import an array of intermediate objects or a single intermediate object in to Core Data. They would normally be used to import Decodable
objects from your web service. These operations work automatically as long as the following requirements are met:
- The intermediate object must conform to
ManagedObjectUpdatable
andUniqueIdentifiable
. - The
NSManagedObject
type you are converting to must conform toManagedObjectType
andUniqueIdentifiable
.
To give your NSManagedObject
subclasses access to a range of helper methods for inserting, deleting, fetching and counting, simply make them conform to the ManagedObjectType
and UniqueIdentifiable
protocols. Doing so will also allow you to use CoreDataBatchImportOperation
and CoreDataSingleImportOperation
.
Each view controller that needs access to the NSPersistentContainer
should conform to PersistentContainerSettable
. Conforming to this protocol gives you easy access to the viewContext
property and a method for saving the viewContext
. It also allows your NSPersistentContainer
to be passed around more easily in prepare(for:sender:)
.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let controller = segue.destination as? PersistentContainerSettable {
controller.persistentContainer = persistentContainer
}
if let navController = segue.destination as? UINavigationController, let controller = navController.topViewController as? PersistentContainerSettable {
controller.persistentContainer = persistentContainer
}
}
Please read CONTRIBUTING.md for details on our code of conduct, and the process for submitting pull requests to us.
We use SemVer for versioning.
This project is licensed under the MIT License - see the LICENSE.md file for details
The Peak Framework is a collection of open-source microframeworks created by the team at 3Squared, named for the Peak District. It is made up of:
Name | Description |
---|---|
PeakOperation | Provides enhancement and conveniences to Operation , making use of the Result type. |
PeakNetwork | A networking framework built on top of Session using PeakOperation, leveraging the power of Codable . |