一个开源库,包含实用程序和扩展,可帮助使用 CoreData
。
开发为 XII 的 iOS、macOS 和 watchOS 应用程序中的各种项目的可重用组件。
SwiftCoreData
库以添加到您的项目请参阅 LICENSE 文件。
CoreData
存储 (源)enum CoreDataStoreConfiguration {
case CloudSynchedSqliteStore(
sqliteName: String,
cloudContainerId: String,
cloudContainerScope: CKDatabase.Scope,
configurationName: String?
)
case TransientInMemoryStore(
configurationName: String?
)
case LocalSqliteStore(
sqliteName: String,
configurationName: String?
)
}
描述 NSPersistentStore
的配置,如 NSPersistentStoreDescription
所述。
包括对以下内容的支持
extension CoreDataStoreConfiguration {
var storeUrl: URL { get }
}
根据存储的类型和描述返回存储的完整 URL
。
NSPersistentContainer
(源)extension NSPersistentContainer {
static func create(
name: String,
stores: [CoreDataStoreConfiguration]
) async throws -> Self
}
创建一个具有特定名称(与模型文件匹配)的 NSPersistentContainer
,以及一组将从其各自的 CoreDataStoreConfiguration
创建的 NSPersistentStore
。
注意: 使用的存储描述不能具有配置了 iCloud 的存储。
extension NSPersistentContainer {
static func createMockInMemoryContainer(
name: String
) -> NSPersistentContainer
}
支持在预览中快速初始化:使用给定的名称初始化模拟的内存容器。
NSPersistentCloudKitContainer
的扩展 (源)extension NSPersistentCloudKitContainer {
func initializeContainerCloudKitSchema() throws
}
在 iCloud 中初始化 NSPersistentCloudKitContainer
的数据库模式。
为了能够初始化云模式
NSSQLiteStoreType
CKDatabase.Scope.private
(参见下文如何初始化公共模式)每当模型发生更改时,都应通过从启动时的调试版本调用此函数来初始化云数据库模式。
注意: iCloud 同步对于已初始化模式的会话将不会处于活动状态。
注意: 仅当最初创建公共模式或模式已更改时,才应初始化公共范围存储的云数据库模式。 如果在初始化时由于缺少 CDMR 记录而收到错误,请特别注意。 初始化时创建虚假的多对多关系可以帮助解决这些问题。
注意: 容器内的瞬态存储类型需要在模式初始化期间从容器中排除,否则模式创建将失败。
extension NSPersistentCloudKitContainer {
func waitForInitialCloudKitImport(
pollIntervalSeconds: Double,
pollTimeoutSeconds: Double
) async throws
}
等待来自给定容器的事件通知,表明它已完成其初始云套件导入。 以给定的间隔轮询容器事件流,并等待最长请求的超时时间以完成同步。
注意: 导入完成并不意味着数据已从 CloudKit 完全下载,因为用户可能处于离线状态。
NSFetchRequest
创建助手 (源)func createFetchRequest<Target : NSManagedObject>(
_ type: Target.Type,
predicate: NSPredicate? = nil,
sort: [NSSortDescriptor]? = nil,
offset: Int? = nil,
limit: Int? = nil
) -> NSFetchRequest<Target>
创建并返回请求的模型类型的获取请求。
extension NSManagedObjectContext {
func fetchSingle<Target : NSManagedObject>(
_ request: NSFetchRequest<Target>
) throws -> Target
}
使用提供的 NSFetchRequest
获取单个记录。
假定请求中的获取限制配置正确,如果读取了多个记录,则会引发错误。
NSPersistentContainer
助手扩展 (源)extension NSPersistentContainer {
func store(for storeUrl: URL?) throws -> NSPersistentStore
}
返回具有请求的 URL
的存储(如果已提供且已找到),或者当前容器中使用的单个存储(如果没有指定 url 且容器仅包含单个存储)。
extension NSPersistentContainer {
func newRecord<Target : NSManagedObject>(
_ type: Target.Type,
storeUrl: URL?
) throws -> Target
}
返回请求的 NSManagedObject
类型的新实例(未填充),连接到 viewContext
。
(可选)可以指定是否应将记录分配给容器内特定类型的存储(例如,用于瞬态记录的内存存储)。
注意: 由于此操作与容器的 viewContext
交互,因此应在主线程上执行。
extension NSPersistentContainer {
@discardableResult
func flushChanges() throws -> Bool
}
将容器的 viewContext
中的任何更改保存到其后备存储。
如果存在要保存的更改且操作成功,则返回 true;如果不存在更改,则返回 false。
注意: 由于此操作与容器的 viewContext
交互,因此应在主线程上执行。
extension NSPersistentContainer {
func delete<Target : NSManagedObject>(
_ request: NSFetchRequest<Target>,
storeUrl: URL?
) throws
}
通过 NSBatchDeleteRequest
删除与提供的 NSFetchRequest
匹配的所有记录。
注意: 仅适用于容器的 NSSQLiteStoreType
中的持久性(非瞬态)记录。
注意: 此操作不会自动刷新更改,而是在后备存储上执行删除,然后将其与内存存储同步。
注意: 由于此操作与容器的 viewContext
交互,因此应在主线程上执行。
View
提供 NSManagedObjectContext
(源)protocol ManagedObjectContextProvider {
func viewContext<Target : NSManagedObject>(
for type: Target.Type
) throws -> NSManagedObjectContext
}
定义一个提供程序,该提供程序可以返回正确的 NSManagedObjectContext
,用于读取特定类型的 NSManagedObject
记录。
当使用存储属性包装器(@StorageRecords
、@StorageRecord
、@StorageOptionalRecord
)并且应用程序具有多个 NSManagedObjectContext
时,这是必需的。
extension View {
func managedObjectContextProvider(
_ provider: ManagedObjectContextProvider
) -> some View
}
将特定的 ManagedObjectContextProvider
注册到 Environment
。
class CoreDataService : ManagedObjectContextProvider {
...
func viewContext<Target : NSManagedObject>(
for type: Target.Type
) throws -> NSManagedObjectContext {
...
}
}
struct FooView : View {
@StateObject private var coreDataService = CoreDataService()
var body : some View {
ContentView()
.managedObjectContextProvider(coreDataService)
}
}
@propertyWrapper
struct StorageRecords<Target : NSManagedObject> : DynamicProperty {
init(_ fetchRequest: NSFetchRequest<Target>)
var wrappedValue: [Target] { get }
nonmutating func update()
}
提供对 Target
类型的 NSFetchRequest
结果的访问。
类似于 @FetchRequest
,但通过视图环境中可用的 ManagedObjectContextProvider
处理获取。 这允许支持应用程序的多个上下文,并将读取操作路由到特定的上下文实例。
示例
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
}
提供对 Target
类型的 NSFetchRequest
结果的访问。
结果假定为单个托管记录。 如果找到多个记录或零个记录,则会引发错误。
类似于 @FetchRequest
,但通过视图环境中可用的 ManagedObjectContextProvider
处理获取。 这允许支持应用程序的多个上下文,并将读取操作路由到特定的上下文实例。
支持特定记录字段的扩展绑定。
示例
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()
}
提供对 Target
类型的 NSFetchRequest
结果的访问。
结果假定为单个托管记录。 如果找到多个记录,则会引发错误。 如果找到零个记录,则结果将为 nil。
类似于 @FetchRequest
,但通过视图环境中可用的 ManagedObjectContextProvider
处理获取。 这允许支持应用程序的多个上下文,并将读取操作路由到特定的上下文实例。
示例
struct FooView : View {
@StorageOptionalRecord(
fetchRequest: ...
) private var record: MyManagedObjectType?
var body : View {
Text("Loaded: \(record.myField ?? "N/A")")
}
}
NSManagedObject
扩展 (源)extension NSManagedObject {
func get<Target>(_ value: Optional<Target>) -> Target
func get(_ value: NSNumber?) -> Int?
func set(_ value: Int?) -> NSNumber?
func get(_ value: NSNumber?) -> Int
func set(_ value: Int) -> NSNumber?
func get(_ value: NSNumber?) -> Double
func set(_ value: Double) -> NSNumber?
func get<Target : RawRepresentable>(
_ value: String?
) -> Target where Target.RawValue == String
func set<Source : RawRepresentable>(
_ value: Source
) -> String? where Source.RawValue == String
func get<Target : RawRepresentable>(
_ value: String?
) -> Target? where Target.RawValue == String
func set<Source : RawRepresentable>(
_ value: Source?
) -> String? where Source.RawValue == String
func get(_ value: String?) -> TimeZone
func set(_ value: TimeZone) -> String
func get<Target : NSManagedObject>(_ value: NSSet?) -> [Target]
func set<Source : NSManagedObject>(_ value: [Source]) -> NSSet?
func get(_ value: String?) -> URL
func set(_ value: URL) -> String
}
为希望公开其属性的类型的模型提供数据转换简写,该类型与其存储的类型属性类型不同(例如,枚举值与存储的 String
)。
示例
extension SomeNSManagedObjectType {
var aliasedAttribute: String {
get { get(storedAttribute) }
set { storedAttribute = set(newValue) }
}
}