converted *Result types to new Swift.Result

This commit is contained in:
John Estropia
2019-03-30 23:58:26 +09:00
parent bf8a1062e0
commit 0ab52d2f43
9 changed files with 100 additions and 316 deletions

View File

@@ -50,45 +50,11 @@ public final class AsynchronousDataTransaction: BaseDataTransaction {
// MARK: - Result // MARK: - Result
/** /**
The `Result` contains the success or failure information for a completed transaction The `Result` contains the success or failure information for a completed transaction.
`Result<T>.success` indicates that the transaction succeeded, either because the save succeeded or because there were no changes to save. The associated `userInfo` is the value returned from the transaction closure.
`Result<T>.failure` indicates that the transaction either failed or was cancelled. The associated object for this value is a `CoreStoreError` enum value.
*/ */
public enum Result<T> { public typealias Result<UserInfoType> = Swift.Result<UserInfoType, CoreStoreError>
/**
`Result<T>.success` indicates that the transaction succeeded, either because the save succeeded or because there were no changes to save. The associated `userInfo` is the value returned from the transaction closure.
*/
case success(userInfo: T)
/**
`Result<T>.failure` indicates that the transaction either failed or was cancelled. The associated object for this value is a `CoreStoreError` enum value.
*/
case failure(error: CoreStoreError)
/**
Returns `true` if the result indicates `.success`, `false` if the result is `.failure`.
*/
public var boolValue: Bool {
switch self {
case .success: return true
case .failure: return false
}
}
// MARK: Internal
internal init(userInfo: T) {
self = .success(userInfo: userInfo)
}
internal init(error: CoreStoreError) {
self = .failure(error: error)
}
}
// MARK: - // MARK: -

View File

@@ -43,7 +43,7 @@ public final class CSMigrationResult: NSObject, CoreStoreObjectiveCType {
@objc @objc
public var isSuccess: Bool { public var isSuccess: Bool {
return self.bridgeToSwift.isSuccess return (try? self.bridgeToSwift.get()) != nil
} }
/** /**
@@ -52,7 +52,7 @@ public final class CSMigrationResult: NSObject, CoreStoreObjectiveCType {
@objc @objc
public var isFailure: Bool { public var isFailure: Bool {
return !self.bridgeToSwift.isSuccess return !self.isSuccess
} }
/** /**
@@ -173,7 +173,7 @@ public final class CSMigrationResult: NSObject, CoreStoreObjectiveCType {
// MARK: - MigrationResult // MARK: - MigrationResult
extension MigrationResult: CoreStoreSwiftType { extension MigrationResult {
// MARK: CoreStoreSwiftType // MARK: CoreStoreSwiftType

View File

@@ -177,7 +177,7 @@ public final class CSSetupResult: NSObject {
// MARK: - SetupResult // MARK: - SetupResult
extension SetupResult where T: CoreStoreSwiftType, T.ObjectiveCType: CSStorageInterface { extension SetupResult where Success: StorageInterface, Success: CoreStoreSwiftType, Success.ObjectiveCType: CSStorageInterface, Failure == CoreStoreError {
// MARK: CoreStoreSwiftType // MARK: CoreStoreSwiftType

View File

@@ -403,9 +403,16 @@ extension UnsafeDataModelSchema: CustomDebugStringConvertible, CoreStoreDebugStr
// MARK: - ListMonitor // MARK: - ListMonitor
@available(macOS 10.12, *) @available(macOS 10.12, *)
private struct CoreStoreFetchedSectionInfoWrapper: CoreStoreDebugStringConvertible { fileprivate struct CoreStoreFetchedSectionInfoWrapper: CoreStoreDebugStringConvertible {
let sectionInfo: NSFetchedResultsSectionInfo // MARK: CustomDebugStringConvertible
var debugDescription: String {
return formattedDebugDescription(self)
}
// MARK: CoreStoreDebugStringConvertible
var coreStoreDumpString: String { var coreStoreDumpString: String {
@@ -415,6 +422,10 @@ private struct CoreStoreFetchedSectionInfoWrapper: CoreStoreDebugStringConvertib
("indexTitle", self.sectionInfo.indexTitle as Any) ("indexTitle", self.sectionInfo.indexTitle as Any)
) )
} }
// MARK: FilePrivate
let sectionInfo: NSFetchedResultsSectionInfo
} }
@available(macOS 10.12, *) @available(macOS 10.12, *)
@@ -546,41 +557,7 @@ extension MigrationChain: CustomDebugStringConvertible, CoreStoreDebugStringConv
// MARK: - MigrationType // MARK: - MigrationType
extension MigrationResult: CustomDebugStringConvertible, CoreStoreDebugStringConvertible { extension MigrationType: CoreStoreDebugStringConvertible {
// MARK: CustomDebugStringConvertible
public var debugDescription: String {
return formattedDebugDescription(self)
}
// MARK: CoreStoreDebugStringConvertible
public var coreStoreDumpString: String {
switch self {
case .success(let migrationTypes):
return createFormattedString(
".success (", ")",
("migrationTypes", migrationTypes)
)
case .failure(let error):
return createFormattedString(
".failure (", ")",
("error", error)
)
}
}
}
// MARK: - MigrationType
extension MigrationType: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
// MARK: CustomDebugStringConvertible // MARK: CustomDebugStringConvertible
@@ -683,41 +660,6 @@ extension PartialObject: CustomDebugStringConvertible, CoreStoreDebugStringConve
} }
// MARK: - SaveResult
@available(*, deprecated, message: "Use the new DataStack.perform(asynchronous:...) and DataStack.perform(synchronous:...) family of APIs")
extension SaveResult: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
// MARK: CustomDebugStringConvertible
public var debugDescription: String {
return formattedDebugDescription(self)
}
// MARK: CoreStoreDebugStringConvertible
public var coreStoreDumpString: String {
switch self {
case .success(let hasChanges):
return createFormattedString(
".success (", ")",
("hasChanges", hasChanges)
)
case .failure(let error):
return createFormattedString(
".failure (", ")",
("error", error)
)
}
}
}
// MARK: - SectionBy // MARK: - SectionBy
@available(macOS 10.12, *) @available(macOS 10.12, *)
@@ -837,40 +779,6 @@ extension SelectTerm: CustomDebugStringConvertible, CoreStoreDebugStringConverti
} }
// MARK: - SetupResult
extension SetupResult: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
// MARK: CustomDebugStringConvertible
public var debugDescription: String {
return formattedDebugDescription(self)
}
// MARK: CoreStoreDebugStringConvertible
public var coreStoreDumpString: String {
switch self {
case .success(let storage):
return createFormattedString(
".success (", ")",
("storage", storage)
)
case .failure(let error):
return createFormattedString(
".failure (", ")",
("error", error)
)
}
}
}
// MARK: - SQLiteStore // MARK: - SQLiteStore
extension SQLiteStore: CustomDebugStringConvertible, CoreStoreDebugStringConvertible { extension SQLiteStore: CustomDebugStringConvertible, CoreStoreDebugStringConvertible {
@@ -1132,7 +1040,7 @@ extension String {
// MARK: - Private: CoreStoreDebugStringConvertible // MARK: - Private: CoreStoreDebugStringConvertible
public protocol CoreStoreDebugStringConvertible { public protocol CoreStoreDebugStringConvertible: CustomDebugStringConvertible {
var coreStoreDumpString: String { get } var coreStoreDumpString: String { get }
} }
@@ -1213,6 +1121,11 @@ extension NSAttributeDescription: CoreStoreDebugStringConvertible {
extension NSAttributeType: CoreStoreDebugStringConvertible { extension NSAttributeType: CoreStoreDebugStringConvertible {
public var debugDescription: String {
return formattedDebugDescription(self)
}
public var coreStoreDumpString: String { public var coreStoreDumpString: String {
switch self { switch self {
@@ -1248,6 +1161,11 @@ extension Bundle: CoreStoreDebugStringConvertible {
extension NSDeleteRule: CoreStoreDebugStringConvertible { extension NSDeleteRule: CoreStoreDebugStringConvertible {
public var debugDescription: String {
return formattedDebugDescription(self)
}
public var coreStoreDumpString: String { public var coreStoreDumpString: String {
switch self { switch self {
@@ -1420,8 +1338,39 @@ extension Optional: CoreStoreDebugStringConvertible {
} }
} }
extension Result: CoreStoreDebugStringConvertible {
public var debugDescription: String {
return formattedDebugDescription(self)
}
public var coreStoreDumpString: String {
switch self {
case .success(let info):
return createFormattedString(
".success (", ")",
("info", info)
)
case .failure(let error):
return createFormattedString(
".failure (", ")",
("error", error)
)
}
}
}
extension Selector: CoreStoreDebugStringConvertible { extension Selector: CoreStoreDebugStringConvertible {
public var debugDescription: String {
return formattedDebugDescription(self)
}
public var coreStoreDumpString: String { public var coreStoreDumpString: String {
return "\"\(self)\"" return "\"\(self)\""

View File

@@ -31,7 +31,7 @@ import Foundation
extension CoreStore { extension CoreStore {
/** /**
Using the `defaultStack`, performs a transaction asynchronously where `NSManagedObject` or `CoreStoreObject` creates, updates, and deletes can be made. The changes are commited automatically after the `task` closure returns. On success, the value returned from closure will be the wrapped as `.success(userInfo: T)` in the `completion`'s `Result<T>`. Any errors thrown from inside the `task` will be reported as `.failure(error: CoreStoreError)`. To cancel/rollback changes, call `try transaction.cancel()`, which throws a `CoreStoreError.userCancelled`. Using the `defaultStack`, performs a transaction asynchronously where `NSManagedObject` or `CoreStoreObject` creates, updates, and deletes can be made. The changes are commited automatically after the `task` closure returns. On success, the value returned from closure will be the wrapped as `.success(T)` in the `completion`'s `Result<T>`. Any errors thrown from inside the `task` will be reported as `.failure(CoreStoreError)`. To cancel/rollback changes, call `try transaction.cancel()`, which throws a `CoreStoreError.userCancelled`.
- parameter task: the asynchronous closure where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`. - parameter task: the asynchronous closure where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`.
- parameter completion: the closure executed after the save completes. The `Result` argument of the closure will either wrap the return value of `task`, or any uncaught errors thrown from within `task`. Cancelled `task`s will be indicated by `.failure(error: CoreStoreError.userCancelled)`. Custom errors thrown by the user will be wrapped in `CoreStoreError.userError(error: Error)`. - parameter completion: the closure executed after the save completes. The `Result` argument of the closure will either wrap the return value of `task`, or any uncaught errors thrown from within `task`. Cancelled `task`s will be indicated by `.failure(error: CoreStoreError.userCancelled)`. Custom errors thrown by the user will be wrapped in `CoreStoreError.userError(error: Error)`.

View File

@@ -55,7 +55,7 @@ extension DataStack {
DispatchQueue.main.async { DispatchQueue.main.async {
completion(SetupResult(storage)) completion(.success(storage))
} }
return return
} }
@@ -70,7 +70,7 @@ extension DataStack {
DispatchQueue.main.async { DispatchQueue.main.async {
completion(SetupResult(storage)) completion(.success(storage))
} }
} }
catch { catch {
@@ -82,7 +82,7 @@ extension DataStack {
) )
DispatchQueue.main.async { DispatchQueue.main.async {
completion(SetupResult(storeError)) completion(.failure(storeError))
} }
} }
} }
@@ -119,7 +119,7 @@ extension DataStack {
DispatchQueue.main.async { DispatchQueue.main.async {
completion(SetupResult(storage)) completion(.success(storage))
} }
return nil return nil
} }
@@ -131,7 +131,7 @@ extension DataStack {
DispatchQueue.main.async { DispatchQueue.main.async {
completion(SetupResult(existingStorage)) completion(.success(existingStorage))
} }
return nil return nil
} }
@@ -143,7 +143,7 @@ extension DataStack {
) )
DispatchQueue.main.async { DispatchQueue.main.async {
completion(SetupResult(error)) completion(.failure(error))
} }
return nil return nil
} }
@@ -181,17 +181,17 @@ extension DataStack {
DispatchQueue.main.async { DispatchQueue.main.async {
completion(SetupResult(storage)) completion(.success(storage))
} }
} }
catch { catch {
completion(SetupResult(error)) completion(.failure(CoreStoreError(error)))
} }
return return
} }
completion(SetupResult(error)) completion(.failure(CoreStoreError(error)))
return return
} }
@@ -201,12 +201,12 @@ extension DataStack {
DispatchQueue.main.async { DispatchQueue.main.async {
completion(SetupResult(storage)) completion(.success(storage))
} }
} }
catch { catch {
completion(SetupResult(error)) completion(.failure(CoreStoreError(error)))
} }
} }
) )
@@ -220,14 +220,14 @@ extension DataStack {
DispatchQueue.main.async { DispatchQueue.main.async {
completion(SetupResult(storage)) completion(.success(storage))
} }
} }
catch { catch {
DispatchQueue.main.async { DispatchQueue.main.async {
completion(SetupResult(error)) completion(.failure(CoreStoreError(error)))
} }
} }
return nil return nil
@@ -241,7 +241,7 @@ extension DataStack {
) )
DispatchQueue.main.async { DispatchQueue.main.async {
completion(SetupResult(storeError)) completion(.failure(storeError))
} }
return nil return nil
} }
@@ -284,7 +284,7 @@ extension DataStack {
DispatchQueue.main.async { DispatchQueue.main.async {
completion(SetupResult(storage)) completion(.success(storage))
} }
return return
} }
@@ -296,7 +296,7 @@ extension DataStack {
DispatchQueue.main.async { DispatchQueue.main.async {
completion(SetupResult(existingStorage)) completion(.success(existingStorage))
} }
return return
} }
@@ -308,7 +308,7 @@ extension DataStack {
) )
DispatchQueue.main.async { DispatchQueue.main.async {
completion(SetupResult(error)) completion(.failure(error))
} }
return return
} }
@@ -328,7 +328,7 @@ extension DataStack {
) )
DispatchQueue.main.async { DispatchQueue.main.async {
completion(SetupResult(storage)) completion(.success(storage))
} }
} }
catch let error as NSError where storage.cloudStorageOptions.contains(.recreateLocalStoreOnModelMismatch) && error.isCoreDataMigrationError { catch let error as NSError where storage.cloudStorageOptions.contains(.recreateLocalStoreOnModelMismatch) && error.isCoreDataMigrationError {
@@ -358,14 +358,14 @@ extension DataStack {
DispatchQueue.main.async { DispatchQueue.main.async {
completion(SetupResult(storage)) completion(.success(storage))
} }
} }
catch { catch {
DispatchQueue.main.async { DispatchQueue.main.async {
completion(SetupResult(error)) completion(.failure(CoreStoreError(error)))
} }
} }
} }
@@ -378,7 +378,7 @@ extension DataStack {
) )
DispatchQueue.main.async { DispatchQueue.main.async {
completion(SetupResult(storeError)) completion(.failure(storeError))
} }
} }
} }
@@ -514,7 +514,7 @@ extension DataStack {
DispatchQueue.main.async { DispatchQueue.main.async {
completion(MigrationResult(error)) completion(.failure(error))
} }
return nil return nil
} }
@@ -524,7 +524,7 @@ extension DataStack {
DispatchQueue.main.async { DispatchQueue.main.async {
completion(MigrationResult([])) completion(.success([]))
return return
} }
return nil return nil
@@ -538,7 +538,7 @@ extension DataStack {
) )
DispatchQueue.main.async { DispatchQueue.main.async {
completion(MigrationResult(error)) completion(.failure(error))
} }
return nil return nil
} }
@@ -586,7 +586,7 @@ extension DataStack {
migrationError, migrationError,
"Failed to migrate version model \"\(migrationType.sourceVersion)\" to version \"\(migrationType.destinationVersion)\"." "Failed to migrate version model \"\(migrationType.sourceVersion)\" to version \"\(migrationType.destinationVersion)\"."
) )
migrationResult = MigrationResult(migrationError) migrationResult = .failure(migrationError)
cancelled = true cancelled = true
} }
} }
@@ -609,7 +609,7 @@ extension DataStack {
DispatchQueue.main.async { DispatchQueue.main.async {
progress.setProgressHandler(nil) progress.setProgressHandler(nil)
completion(migrationResult ?? MigrationResult(migrationTypes)) completion(migrationResult ?? .success(migrationTypes))
return return
} }
} }

View File

@@ -32,7 +32,7 @@ import CoreData
extension DataStack { extension DataStack {
/** /**
Performs a transaction asynchronously where `NSManagedObject` or `CoreStoreObject` creates, updates, and deletes can be made. The changes are commited automatically after the `task` closure returns. On success, the value returned from closure will be the wrapped as `.success(userInfo: T)` in the `completion`'s `Result<T>`. Any errors thrown from inside the `task` will be reported as `.failure(error: CoreStoreError)`. To cancel/rollback changes, call `try transaction.cancel()`, which throws a `CoreStoreError.userCancelled`. Performs a transaction asynchronously where `NSManagedObject` or `CoreStoreObject` creates, updates, and deletes can be made. The changes are commited automatically after the `task` closure returns. On success, the value returned from closure will be the wrapped as `.success(T)` in the `completion`'s `Result<T>`. Any errors thrown from inside the `task` will be reported as `.failure(CoreStoreError)`. To cancel/rollback changes, call `try transaction.cancel()`, which throws a `CoreStoreError.userCancelled`.
- parameter task: the asynchronous closure where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`. - parameter task: the asynchronous closure where creates, updates, and deletes can be made to the transaction. Transaction blocks are executed serially in a background queue, and all changes are made from a concurrent `NSManagedObjectContext`.
- parameter completion: the closure executed after the save completes. The `Result` argument of the closure will either wrap the return value of `task`, or any uncaught errors thrown from within `task`. Cancelled `task`s will be indicated by `.failure(error: CoreStoreError.userCancelled)`. Custom errors thrown by the user will be wrapped in `CoreStoreError.userError(error: Error)`. - parameter completion: the closure executed after the save completes. The `Result` argument of the closure will either wrap the return value of `task`, or any uncaught errors thrown from within `task`. Cancelled `task`s will be indicated by `.failure(error: CoreStoreError.userCancelled)`. Custom errors thrown by the user will be wrapped in `CoreStoreError.userError(error: Error)`.
@@ -41,8 +41,8 @@ extension DataStack {
self.perform( self.perform(
asynchronous: task, asynchronous: task,
success: { completion(.init(userInfo: $0)) }, success: { completion(.success($0)) },
failure: { completion(.init(error: $0)) } failure: { completion(.failure($0)) }
) )
} }

View File

@@ -30,7 +30,8 @@ import Foundation
/** /**
The `MigrationResult` indicates the result of a migration. The `MigrationResult` indicates the result of a migration.
The `MigrationResult` can be treated as a boolean: `MigrationResult.success` indicates either the migration succeeded, or there were no migrations needed. The associated value is an array of `MigrationType`s reflecting the migration steps completed.
`MigrationResult.failure` indicates that the migration failed. The associated object for this value is the a `CoreStoreError` enum value.
``` ```
CoreStore.upgradeStorageIfNeeded(SQLiteStorage(fileName: "data.sqlite")) { (result) in CoreStore.upgradeStorageIfNeeded(SQLiteStorage(fileName: "data.sqlite")) { (result) in
switch result { switch result {
@@ -42,46 +43,4 @@ import Foundation
} }
``` ```
*/ */
public enum MigrationResult: Hashable { public typealias MigrationResult = Swift.Result<[MigrationType], CoreStoreError>
/**
`MigrationResult.success` indicates either the migration succeeded, or there were no migrations needed. The associated value is an array of `MigrationType`s reflecting the migration steps completed.
*/
case success([MigrationType])
/**
`SaveResult.failure` indicates that the migration failed. The associated object for this value is the a `CoreStoreError` enum value.
*/
case failure(CoreStoreError)
/**
Returns `true` if the result indicates `.success`, `false` if the result is `.failure`.
*/
public var isSuccess: Bool {
switch self {
case .success: return true
case .failure: return false
}
}
// MARK: Internal
internal init(_ migrationTypes: [MigrationType]) {
self = .success(migrationTypes)
}
internal init(_ error: CoreStoreError) {
self = .failure(error)
}
internal init(_ error: Error) {
self = .failure(CoreStoreError(error))
}
}

View File

@@ -31,21 +31,8 @@ import CoreData
/** /**
The `SetupResult` indicates the result of an asynchronous initialization of a persistent store. The `SetupResult` indicates the result of an asynchronous initialization of a persistent store.
The `SetupResult` can be treated as a boolean: `SetupResult.success` indicates that the storage setup succeeded. The associated object for this `enum` value is the related `StorageInterface` instance.
``` `SetupResult.failure` indicates that the storage setup failed. The associated object for this value is the related `CoreStoreError` enum value.
try! CoreStore.addStorage(
SQLiteStore(),
completion: { (result: SetupResult) -> Void in
if result {
// succeeded
}
else {
// failed
}
}
)
```
or as an `enum`, where the resulting associated object can also be inspected:
``` ```
try! CoreStore.addStorage( try! CoreStore.addStorage(
SQLiteStore(), SQLiteStore(),
@@ -60,81 +47,4 @@ import CoreData
) )
``` ```
*/ */
public enum SetupResult<T: StorageInterface>: Hashable { public typealias SetupResult<StorageInterfaceType> = Swift.Result<StorageInterfaceType, CoreStoreError> where StorageInterfaceType: StorageInterface
/**
`SetupResult.success` indicates that the storage setup succeeded. The associated object for this `enum` value is the related `StorageInterface` instance.
*/
case success(T)
/**
`SetupResult.failure` indicates that the storage setup failed. The associated object for this value is the related `CoreStoreError` enum value.
*/
case failure(CoreStoreError)
/**
Returns `true` if the result indicates `.success`, `false` if the result is `.failure`.
*/
public var isSuccess: Bool {
switch self {
case .success: return true
case .failure: return false
}
}
// MARK: Equatable
public static func == <T, U>(lhs: SetupResult<T>, rhs: SetupResult<U>) -> Bool {
switch (lhs, rhs) {
case (.success(let storage1), .success(let storage2)):
return storage1 === storage2
case (.failure(let error1), .failure(let error2)):
return error1 == error2
default:
return false
}
}
// MARK: Hashable
public func hash(into hasher: inout Hasher) {
switch self {
case .success(let storage):
hasher.combine(true)
hasher.combine(ObjectIdentifier(storage))
case .failure(let error):
hasher.combine(false)
hasher.combine(error)
}
}
// MARK: Internal
internal init(_ storage: T) {
self = .success(storage)
}
internal init(_ error: CoreStoreError) {
self = .failure(error)
}
internal init(_ error: Error) {
self = .failure(CoreStoreError(error))
}
}