mirror of
https://github.com/JohnEstropia/CoreStore.git
synced 2026-03-21 08:59:24 +01:00
user #keyPath() for keys in demo app and in unit tests
This commit is contained in:
@@ -32,7 +32,7 @@ import CoreData
|
||||
/**
|
||||
All errors thrown from CoreStore are expressed in `CoreStoreError` enum values.
|
||||
*/
|
||||
public enum CoreStoreError: Error, Hashable {
|
||||
public enum CoreStoreError: Error, CustomNSError, Hashable {
|
||||
|
||||
/**
|
||||
A failure occured because of an unknown error.
|
||||
@@ -60,14 +60,14 @@ public enum CoreStoreError: Error, Hashable {
|
||||
case internalError(NSError: NSError)
|
||||
|
||||
|
||||
// MARK: ErrorType
|
||||
// MARK: CustomNSError
|
||||
|
||||
public var _domain: String {
|
||||
public static var errorDomain: String {
|
||||
|
||||
return CoreStoreErrorDomain
|
||||
}
|
||||
|
||||
public var _code: Int {
|
||||
public var errorCode: Int {
|
||||
|
||||
switch self {
|
||||
|
||||
@@ -88,6 +88,37 @@ public enum CoreStoreError: Error, Hashable {
|
||||
}
|
||||
}
|
||||
|
||||
public var errorUserInfo: [String : Any] {
|
||||
|
||||
switch self {
|
||||
|
||||
case .unknown:
|
||||
return [:]
|
||||
|
||||
case .differentStorageExistsAtURL(let existingPersistentStoreURL):
|
||||
return [
|
||||
"existingPersistentStoreURL": existingPersistentStoreURL
|
||||
]
|
||||
|
||||
case .mappingModelNotFound(let localStoreURL, let targetModel, let targetModelVersion):
|
||||
return [
|
||||
"localStoreURL": localStoreURL,
|
||||
"targetModel": targetModel,
|
||||
"targetModelVersion": targetModelVersion
|
||||
]
|
||||
|
||||
case .progressiveMigrationRequired(let localStoreURL):
|
||||
return [
|
||||
"localStoreURL": localStoreURL
|
||||
]
|
||||
|
||||
case .internalError(let NSError):
|
||||
return [
|
||||
"NSError": NSError
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: Hashable
|
||||
|
||||
|
||||
@@ -322,13 +322,14 @@ public func == (lhs: SelectTerm, rhs: SelectTerm) -> Bool {
|
||||
- `Double`
|
||||
- `Float`
|
||||
- `String`
|
||||
- `Date`
|
||||
- `Data`
|
||||
- `NSNumber`
|
||||
- `NSString`
|
||||
- `NSDecimalNumber`
|
||||
- `NSDate`
|
||||
- `NSData`
|
||||
- `NSManagedObjectID`
|
||||
- `NSString`
|
||||
- for `queryAttributes(...)` methods:
|
||||
- `NSDictionary`
|
||||
|
||||
|
||||
@@ -65,6 +65,6 @@ public struct Tweak: FetchClause, QueryClause, DeleteClause {
|
||||
|
||||
public func applyToFetchRequest<ResultType: NSFetchRequestResult>(_ fetchRequest: NSFetchRequest<ResultType>) {
|
||||
|
||||
self.closure(unsafeBitCast(fetchRequest, to: NSFetchRequest<NSFetchRequestResult>.self))
|
||||
self.closure(fetchRequest as! NSFetchRequest<NSFetchRequestResult>)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ internal final class CoreStoreFetchedResultsController: NSFetchedResultsControll
|
||||
context: context,
|
||||
applyAffectedStores: false
|
||||
)
|
||||
applyFetchClauses(unsafeBitCast(fetchRequest, to: NSFetchRequest<NSManagedObject>.self))
|
||||
applyFetchClauses(fetchRequest)
|
||||
|
||||
if let from = from {
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ public protocol CoreStoreLogger {
|
||||
|
||||
/**
|
||||
Handles fatal errors made throughout the `CoreStore` framework. The app wil terminate after this method is called.
|
||||
- Important: Implementers may guarantee that the function doesn't return, either by calling another `@noreturn` function such as `fatalError()` or `abort()`, or by raising an exception. If the implementation does not terminate the app, CoreStore will call an internal `fatalError()` to do so.
|
||||
- Important: Implementers may guarantee that the function doesn't return, either by calling another `Never` function such as `fatalError()` or `abort()`, or by raising an exception. If the implementation does not terminate the app, CoreStore will call an internal `fatalError()` to do so.
|
||||
|
||||
- parameter message: the fatal error message
|
||||
- parameter fileName: the source file name
|
||||
|
||||
@@ -113,7 +113,7 @@ public final class DefaultLogger: CoreStoreLogger {
|
||||
|
||||
/**
|
||||
Handles fatal errors made throughout the `CoreStore` framework.
|
||||
- Important: This method should be marked `@noreturn` and implementers should guarantee that the function doesn't, either by calling another `@noreturn` function such as `fatalError()` or `abort()`, or by raising an exception.
|
||||
- Important: Implementers should guarantee that this function doesn't return, either by calling another `Never` function such as `fatalError()` or `abort()`, or by raising an exception.
|
||||
|
||||
- parameter message: the fatal error message
|
||||
- parameter fileName: the source file name
|
||||
|
||||
@@ -74,7 +74,7 @@ public extension CSDataStack {
|
||||
sectionBy: nil,
|
||||
applyFetchClauses: { (fetchRequest) in
|
||||
|
||||
fetchClauses.forEach { $0.applyToFetchRequest(unsafeBitCast(fetchRequest, to: NSFetchRequest<NSFetchRequestResult>.self)) }
|
||||
fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest as! NSFetchRequest<NSFetchRequestResult>) }
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -104,7 +104,7 @@ public extension CSDataStack {
|
||||
sectionBy: nil,
|
||||
applyFetchClauses: { (fetchRequest) in
|
||||
|
||||
fetchClauses.forEach { $0.applyToFetchRequest(unsafeBitCast(fetchRequest, to: NSFetchRequest<NSFetchRequestResult>.self)) }
|
||||
fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest as! NSFetchRequest<NSFetchRequestResult>) }
|
||||
},
|
||||
createAsynchronously: {
|
||||
|
||||
@@ -140,7 +140,7 @@ public extension CSDataStack {
|
||||
sectionBy: sectionBy.bridgeToSwift,
|
||||
applyFetchClauses: { (fetchRequest) in
|
||||
|
||||
fetchClauses.forEach { $0.applyToFetchRequest(unsafeBitCast(fetchRequest, to: NSFetchRequest<NSFetchRequestResult>.self)) }
|
||||
fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest as! NSFetchRequest<NSFetchRequestResult>) }
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -170,7 +170,7 @@ public extension CSDataStack {
|
||||
sectionBy: sectionBy.bridgeToSwift,
|
||||
applyFetchClauses: { (fetchRequest) in
|
||||
|
||||
fetchClauses.forEach { $0.applyToFetchRequest(unsafeBitCast(fetchRequest, to: NSFetchRequest<NSFetchRequestResult>.self)) }
|
||||
fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest as! NSFetchRequest<NSFetchRequestResult>) }
|
||||
},
|
||||
createAsynchronously: {
|
||||
|
||||
|
||||
@@ -76,58 +76,7 @@ public final class CSError: NSError, CoreStoreObjectiveCType {
|
||||
|
||||
return swift
|
||||
}
|
||||
|
||||
func createSwiftObject(_ error: CSError) -> CoreStoreError {
|
||||
|
||||
guard error.domain == CoreStoreErrorDomain else {
|
||||
|
||||
return .internalError(NSError: self)
|
||||
}
|
||||
|
||||
guard let code = CoreStoreErrorCode(rawValue: error.code) else {
|
||||
|
||||
return .unknown
|
||||
}
|
||||
|
||||
let info = error.userInfo
|
||||
switch code {
|
||||
|
||||
case .unknownError:
|
||||
return .unknown
|
||||
|
||||
case .differentStorageExistsAtURL:
|
||||
guard case let existingPersistentStoreURL as URL = info["existingPersistentStoreURL"] else {
|
||||
|
||||
return .unknown
|
||||
}
|
||||
return .differentStorageExistsAtURL(existingPersistentStoreURL: existingPersistentStoreURL)
|
||||
|
||||
case .mappingModelNotFound:
|
||||
guard let localStoreURL = info["localStoreURL"] as? URL,
|
||||
let targetModel = info["targetModel"] as? NSManagedObjectModel,
|
||||
let targetModelVersion = info["targetModelVersion"] as? String else {
|
||||
|
||||
return .unknown
|
||||
}
|
||||
return .mappingModelNotFound(localStoreURL: localStoreURL, targetModel: targetModel, targetModelVersion: targetModelVersion)
|
||||
|
||||
case .progressiveMigrationRequired:
|
||||
guard let localStoreURL = info["localStoreURL"] as? URL else {
|
||||
|
||||
return .unknown
|
||||
}
|
||||
return .progressiveMigrationRequired(localStoreURL: localStoreURL)
|
||||
|
||||
case .internalError:
|
||||
guard case let NSError as NSError = info["NSError"] else {
|
||||
|
||||
return .unknown
|
||||
}
|
||||
return .internalError(NSError: NSError)
|
||||
}
|
||||
}
|
||||
|
||||
let swift = createSwiftObject(self)
|
||||
let swift = CoreStoreError(_bridgedNSError: self) ?? .unknown
|
||||
self.swiftError = swift
|
||||
return swift
|
||||
}
|
||||
@@ -138,43 +87,7 @@ public final class CSError: NSError, CoreStoreObjectiveCType {
|
||||
public init(_ swiftValue: CoreStoreError) {
|
||||
|
||||
self.swiftError = swiftValue
|
||||
|
||||
let code: CoreStoreErrorCode
|
||||
let info: [AnyHashable: Any]
|
||||
switch swiftValue {
|
||||
|
||||
case .unknown:
|
||||
code = .unknownError
|
||||
info = [:]
|
||||
|
||||
case .differentStorageExistsAtURL(let existingPersistentStoreURL):
|
||||
code = .differentStorageExistsAtURL
|
||||
info = [
|
||||
"existingPersistentStoreURL": existingPersistentStoreURL
|
||||
]
|
||||
|
||||
case .mappingModelNotFound(let localStoreURL, let targetModel, let targetModelVersion):
|
||||
code = .mappingModelNotFound
|
||||
info = [
|
||||
"localStoreURL": localStoreURL,
|
||||
"targetModel": targetModel,
|
||||
"targetModelVersion": targetModelVersion
|
||||
]
|
||||
|
||||
case .progressiveMigrationRequired(let localStoreURL):
|
||||
code = .progressiveMigrationRequired
|
||||
info = [
|
||||
"localStoreURL": localStoreURL
|
||||
]
|
||||
|
||||
case .internalError(let NSError):
|
||||
code = .internalError
|
||||
info = [
|
||||
"NSError": NSError
|
||||
]
|
||||
}
|
||||
|
||||
super.init(domain: CoreStoreErrorDomain, code: code.rawValue, userInfo: info)
|
||||
super.init(domain: CoreStoreError.errorDomain, code: swiftValue.errorCode, userInfo: swiftValue.errorUserInfo)
|
||||
}
|
||||
|
||||
public required init?(coder aDecoder: NSCoder) {
|
||||
@@ -229,7 +142,7 @@ public enum CSErrorCode: Int {
|
||||
|
||||
// MARK: - CoreStoreError
|
||||
|
||||
extension CoreStoreError: CoreStoreSwiftType {
|
||||
extension CoreStoreError: CoreStoreSwiftType, _ObjectiveCBridgeableError {
|
||||
|
||||
// MARK: CoreStoreSwiftType
|
||||
|
||||
@@ -237,6 +150,73 @@ extension CoreStoreError: CoreStoreSwiftType {
|
||||
|
||||
return CSError(self)
|
||||
}
|
||||
|
||||
|
||||
// MARK: _ObjectiveCBridgeableError
|
||||
|
||||
public init?(_bridgedNSError error: NSError) {
|
||||
|
||||
guard error.domain == CoreStoreErrorDomain else {
|
||||
|
||||
if error is CSError {
|
||||
|
||||
self = .internalError(NSError: error)
|
||||
return
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
guard let code = CoreStoreErrorCode(rawValue: error.code) else {
|
||||
|
||||
if error is CSError {
|
||||
|
||||
self = .unknown
|
||||
return
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
let info = error.userInfo
|
||||
switch code {
|
||||
|
||||
case .unknownError:
|
||||
self = .unknown
|
||||
|
||||
case .differentStorageExistsAtURL:
|
||||
guard case let existingPersistentStoreURL as URL = info["existingPersistentStoreURL"] else {
|
||||
|
||||
self = .unknown
|
||||
return
|
||||
}
|
||||
self = .differentStorageExistsAtURL(existingPersistentStoreURL: existingPersistentStoreURL)
|
||||
|
||||
case .mappingModelNotFound:
|
||||
guard let localStoreURL = info["localStoreURL"] as? URL,
|
||||
let targetModel = info["targetModel"] as? NSManagedObjectModel,
|
||||
let targetModelVersion = info["targetModelVersion"] as? String else {
|
||||
|
||||
self = .unknown
|
||||
return
|
||||
}
|
||||
self = .mappingModelNotFound(localStoreURL: localStoreURL, targetModel: targetModel, targetModelVersion: targetModelVersion)
|
||||
|
||||
case .progressiveMigrationRequired:
|
||||
guard let localStoreURL = info["localStoreURL"] as? URL else {
|
||||
|
||||
self = .unknown
|
||||
return
|
||||
}
|
||||
self = .progressiveMigrationRequired(localStoreURL: localStoreURL)
|
||||
|
||||
case .internalError:
|
||||
guard case let NSError as NSError = info["NSError"] else {
|
||||
|
||||
self = .unknown
|
||||
return
|
||||
}
|
||||
self = .internalError(NSError: NSError)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -503,7 +503,7 @@ public final class CSListMonitor: NSObject, CoreStoreObjectiveCType {
|
||||
|
||||
self.bridgeToSwift.refetch { (fetchRequest) in
|
||||
|
||||
fetchClauses.forEach { $0.applyToFetchRequest(unsafeBitCast(fetchRequest, to: NSFetchRequest<NSFetchRequestResult>.self)) }
|
||||
fetchClauses.forEach { $0.applyToFetchRequest(fetchRequest as! NSFetchRequest<NSFetchRequestResult>) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -99,11 +99,11 @@ public extension CoreStore {
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `LocalStorageface` of the specified store type with default values and adds it to the `defaultStack`. This method blocks until completion.
|
||||
Creates a `LocalStorageInterface` of the specified store type with default values and adds it to the `defaultStack`. This method blocks until completion.
|
||||
```
|
||||
try CoreStore.addStorageAndWait(SQLiteStore.self)
|
||||
```
|
||||
- parameter storeType: the `LocalStorageface` type
|
||||
- parameter storeType: the `LocalStorageInterface` type
|
||||
- throws: a `CoreStoreError` value indicating the failure
|
||||
- returns: the local storage added to the `defaultStack`
|
||||
*/
|
||||
|
||||
@@ -177,11 +177,11 @@ public final class DataStack {
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `LocalStorageface` of the specified store type with default values and adds it to the stack. This method blocks until completion.
|
||||
Creates a `LocalStorageInterface` of the specified store type with default values and adds it to the stack. This method blocks until completion.
|
||||
```
|
||||
try dataStack.addStorageAndWait(SQLiteStore.self)
|
||||
```
|
||||
- parameter storeType: the `LocalStorageface` type
|
||||
- parameter storeType: the `LocalStorageInterface` type
|
||||
- throws: a `CoreStoreError` value indicating the failure
|
||||
- returns: the local storage added to the stack
|
||||
*/
|
||||
@@ -424,36 +424,33 @@ public final class DataStack {
|
||||
|
||||
internal func persistentStoreForEntityClass(_ entityClass: AnyClass, configuration: String?, inferStoreIfPossible: Bool) -> (store: NSPersistentStore?, isAmbiguous: Bool) {
|
||||
|
||||
var returnValue: (store: NSPersistentStore?, isAmbiguous: Bool) = (store: nil, isAmbiguous: false)
|
||||
self.storeMetadataUpdateQueue.sync(flags: .barrier) {
|
||||
return self.storeMetadataUpdateQueue.sync(flags: .barrier) { () -> (store: NSPersistentStore?, isAmbiguous: Bool) in
|
||||
|
||||
let configurationsForEntity = self.entityConfigurationsMapping[NSStringFromClass(entityClass)] ?? []
|
||||
if let configuration = configuration {
|
||||
|
||||
if configurationsForEntity.contains(configuration) {
|
||||
|
||||
returnValue = (store: self.configurationStoreMapping[configuration], isAmbiguous: false)
|
||||
return
|
||||
return (store: self.configurationStoreMapping[configuration], isAmbiguous: false)
|
||||
}
|
||||
else if !inferStoreIfPossible {
|
||||
|
||||
return
|
||||
return (store: nil, isAmbiguous: false)
|
||||
}
|
||||
}
|
||||
|
||||
switch configurationsForEntity.count {
|
||||
|
||||
case 0:
|
||||
return
|
||||
return (store: nil, isAmbiguous: false)
|
||||
|
||||
case 1 where inferStoreIfPossible:
|
||||
returnValue = (store: self.configurationStoreMapping[configurationsForEntity.first!], isAmbiguous: false)
|
||||
return (store: self.configurationStoreMapping[configurationsForEntity.first!], isAmbiguous: false)
|
||||
|
||||
default:
|
||||
returnValue = (store: nil, isAmbiguous: true)
|
||||
return (store: nil, isAmbiguous: true)
|
||||
}
|
||||
}
|
||||
return returnValue
|
||||
}
|
||||
|
||||
internal func createPersistentStoreFromStorage(_ storage: StorageInterface, finalURL: URL?, finalStoreOptions: [AnyHashable: Any]?) throws -> NSPersistentStore {
|
||||
|
||||
@@ -34,7 +34,7 @@ import CoreData
|
||||
/**
|
||||
A storage interface backed by an SQLite database managed by iCloud.
|
||||
*/
|
||||
public class ICloudStore: CloudStorage {
|
||||
public final class ICloudStore: CloudStorage {
|
||||
|
||||
/**
|
||||
Initializes an iCloud store interface from the given ubiquitous store information. Returns `nil` if the container could not be located or if iCloud storage is unavailable for the current user or device
|
||||
|
||||
@@ -454,8 +454,6 @@ public /*abstract*/ class BaseDataTransaction {
|
||||
internal let childTransactionQueue = DispatchQueue.serial("com.corestore.datastack.childtransactionqueue")
|
||||
internal let supportsUndo: Bool
|
||||
internal let bypassesQueueing: Bool
|
||||
|
||||
|
||||
internal var isCommitted = false
|
||||
internal var result: SaveResult?
|
||||
|
||||
|
||||
Reference in New Issue
Block a user