Creates a NSPersistentContainer with a specific name (matching the models file) and a set of NSPersistentStores to be created from their individual CoreDataStoreConfiguration.
NOTE: The store descriptions used MUST not have iCloud configured stores.
Initializes the database schema in iCloud for the NSPersistentCloudKitContainer.
In order to be able to initialize a cloud schema:
The type of all stores in the container need to be NSSQLiteStoreType
The database scope used must be CKDatabase.Scope.private (see below how to initialize a public schema)
The cloud database schema should be initialized whenever the models have changed by calling this function from a debug build at start up.
NOTE: iCloud sync will not be active for the session that has initialized the schema.
NOTE: Initializing the cloud database schema for a publicly scoped store should only be done when initially creating the public schema OR when it has changed. Take special care if you get an error when initializing due to missing CDMR records. Creating a fake many-to-many relationship when initializing can help resolve these.
NOTE: Transient store types within the container need to be excluded from the container during schema initializations
or schema creation will fail.
Waits for event notifications from the given container that it has completed its initial cloud kit import. Polls the container event stream at a given interval and waits for a maximum of the requested timeout time for the sync to complete.
NOTE: The import being complete does not mean that data has been fully downloaded from CloudKit, since the user may be offline.
Returns the store with the requested URL (if provided and found) or the single used store within the current container (if no url is specified AND the container contains only a single store).
Returns a new instance (non populated) of the requested NSManagedObject type, connected to the viewContext.
Optionally, can specify if the record should be assigned to a store of a specific type within the container (e.g. in memory store used for transient records).
NOTE: Since this interacts with the viewContext of the container and should be performed on the main thread.
Removes all records that match the the provided NSFetchRequest via a NSBatchDeleteRequest.
NOTE: Applies only to persistent (non transient) records within the container’s NSSQLiteStoreType.
NOTE: This operation does not automatically flush changes, but rather performs the delete on the backing store and then syncs it with the memory store.
NOTE: Since this interacts with the viewContext of the container and should be performed on the main thread.
Providing a NSManagedObjectContext to Views (Source)
Defines a provider that can return the correct NSManagedObjectContext for reading NSManagedObject records of a specific type.
This is required when using the storage property wrappers (@StorageRecords, @StorageRecord, @StorageOptionalRecord) and the application has multiple NSManagedObjectContexts.
Provides access to the results of an NSFetchRequest for the Target type.
Similar to @FetchRequest but processes the fetch via ManagedObjectContextProvider available in the view’s environment. This allows for supporting multiple contexts for an application and routing read operations to specific context instances.
Example:
struct FooView : View {
@StorageRecords(
fetchRequest: ...
) private var records: [MyManagedObjectType]
var body : View {
Text("Loaded: \(records.count)")
}
}
@propertyWrapper
public struct StorageRecord<Target : NSManagedObject> : DynamicProperty {
init(_ fetchRequest: NSFetchRequest<Target>)
var wrappedValue: Target { get }
nonmutating func update()
@dynamicMemberLookup
public struct Wrapper {
subscript<Value>(
dynamicMember keyPath: ReferenceWritableKeyPath<Target, Value>
) -> Binding<Value>
}
var projectedValue: StorageRecord<Target>.Wrapper
}
Provides access to the results of an NSFetchRequest for the Target type.
The result is assumed to be a single managed record. If more than one record is found, or zero, and error is raised.
Similar to @FetchRequest but processes the fetch via ManagedObjectContextProvider available in the view’s environment. This allows for supporting multiple contexts for an application and routing read operations to specific context instances.
Supports expanded binding for specific record fields.
Example:
struct FooView : View {
@StorageRecord(
fetchRequest: ...
) private var record: MyManagedObjectType
var body : View {
Text("Loaded: \(record.myField)")
SomeSubView(binding: $record.myField)
}
}
@propertyWrapper
public struct StorageOptionalRecord<Target : NSManagedObject> : DynamicProperty {
init(_ fetchRequest: NSFetchRequest<Target>)
var wrappedValue: Target? { get }
nonmutating func update()
}
Provides access to the results of an NSFetchRequest for the Target type.
The result is assumed to be a single managed record. If more than one record is found, and error is raised. If zero records are found, the result will be nil.
Similar to @FetchRequest but processes the fetch via ManagedObjectContextProvider available in the view’s environment. This allows for supporting multiple contexts for an application and routing read operations to specific context instances.
Example:
struct FooView : View {
@StorageOptionalRecord(
fetchRequest: ...
) private var record: MyManagedObjectType?
var body : View {
Text("Loaded: \(record.myField ?? "N/A")")
}
}
Provides data transformation short-hand for models that want to expose a type for their attributes that is different than the stored type attribute type (e.g. enum value vs stored String).
Example:
extension SomeNSManagedObjectType {
var aliasedAttribute: String {
get { get(storedAttribute) }
set { storedAttribute = set(newValue) }
}
}
SwiftCoreData Library
An open source library that includes utilities and extensions to help work with
CoreData
.Developed as re-usable components for various projects at XII’s iOS, macOS, and watchOS applications.
Installation
Swift Package Manager
SwiftCoreData
library to add to your projectDependencies
License
See the LICENSE file.
Defining
CoreData
stores (Source)Describes the configuration of a
NSPersistentStore
as described byNSPersistentStoreDescription
.Includes support for:
Extracting the store’s
URL
Returns the full
URL
of the store, based on it’s type and description.Creating
NSPersistentContainer
s (Source)Creates a
NSPersistentContainer
with a specific name (matching the models file) and a set ofNSPersistentStore
s to be created from their individualCoreDataStoreConfiguration
.NOTE: The store descriptions used MUST not have iCloud configured stores.
Support for quick initialiation in previews: Initializes a mock in memory container with the given name.
Extensions for
NSPersistentCloudKitContainer
s (Source)Initializes the database schema in iCloud for the
NSPersistentCloudKitContainer
.In order to be able to initialize a cloud schema:
NSSQLiteStoreType
CKDatabase.Scope.private
(see below how to initialize a public schema)The cloud database schema should be initialized whenever the models have changed by calling this function from a debug build at start up.
NOTE: iCloud sync will not be active for the session that has initialized the schema.
NOTE: Initializing the cloud database schema for a publicly scoped store should only be done when initially creating the public schema OR when it has changed. Take special care if you get an error when initializing due to missing CDMR records. Creating a fake many-to-many relationship when initializing can help resolve these.
NOTE: Transient store types within the container need to be excluded from the container during schema initializations or schema creation will fail.
Waits for event notifications from the given container that it has completed its initial cloud kit import. Polls the container event stream at a given interval and waits for a maximum of the requested timeout time for the sync to complete.
NOTE: The import being complete does not mean that data has been fully downloaded from CloudKit, since the user may be offline.
NSFetchRequest
creation helper (Source)Creates and returns a fetch request for the requested model type.
Fetch helpers (Source)
Fetches a single record using the provided
NSFetchRequest
.It is assumed that the fetch limit in the request is configured correctly and an error is thrown if there is more than one record read.
NSPersistentContainer
helper extensions (Source)Returns the store with the requested
URL
(if provided and found) or the single used store within the current container (if no url is specified AND the container contains only a single store).Returns a new instance (non populated) of the requested
NSManagedObject
type, connected to theviewContext
.Optionally, can specify if the record should be assigned to a store of a specific type within the container (e.g. in memory store used for transient records).
NOTE: Since this interacts with the
viewContext
of the container and should be performed on the main thread.Saves any changes in the container’s
viewContext
to its backing store.Returns true if there were changes to save and the operation succeeds, false if there were no changes.
NOTE: Since this interacts with the
viewContext
of the container and should be performed on the main thread.Removes all records that match the the provided
NSFetchRequest
via aNSBatchDeleteRequest
.NOTE: Applies only to persistent (non transient) records within the container’s
NSSQLiteStoreType
.NOTE: This operation does not automatically flush changes, but rather performs the delete on the backing store and then syncs it with the memory store.
NOTE: Since this interacts with the
viewContext
of the container and should be performed on the main thread.Providing a
NSManagedObjectContext
toView
s (Source)Defines a provider that can return the correct
NSManagedObjectContext
for readingNSManagedObject
records of a specific type.This is required when using the storage property wrappers (
@StorageRecords
,@StorageRecord
,@StorageOptionalRecord
) and the application has multipleNSManagedObjectContext
s.Registers a specific
ManagedObjectContextProvider
with theEnvironment
.Example Usage
SwiftUI fetch property wraoppers
Loading multiple records (Source)
Provides access to the results of an
NSFetchRequest
for theTarget
type.Similar to
@FetchRequest
but processes the fetch viaManagedObjectContextProvider
available in the view’s environment. This allows for supporting multiple contexts for an application and routing read operations to specific context instances.Example:
Loading a single record (Source)
Provides access to the results of an
NSFetchRequest
for theTarget
type.The result is assumed to be a single managed record. If more than one record is found, or zero, and error is raised.
Similar to
@FetchRequest
but processes the fetch viaManagedObjectContextProvider
available in the view’s environment. This allows for supporting multiple contexts for an application and routing read operations to specific context instances.Supports expanded binding for specific record fields.
Example:
Loading record that may not exist (Source)
Provides access to the results of an
NSFetchRequest
for theTarget
type.The result is assumed to be a single managed record. If more than one record is found, and error is raised. If zero records are found, the result will be nil.
Similar to
@FetchRequest
but processes the fetch viaManagedObjectContextProvider
available in the view’s environment. This allows for supporting multiple contexts for an application and routing read operations to specific context instances.Example:
NSManagedObject
extensions (Source)Provides data transformation short-hand for models that want to expose a type for their attributes that is different than the stored type attribute type (e.g. enum value vs stored
String
).Example: