diff --git a/CoreStoreDemo/CoreStoreDemo/AppDelegate.swift b/CoreStoreDemo/CoreStoreDemo/AppDelegate.swift index c320623..6cb6bad 100644 --- a/CoreStoreDemo/CoreStoreDemo/AppDelegate.swift +++ b/CoreStoreDemo/CoreStoreDemo/AppDelegate.swift @@ -7,6 +7,7 @@ // import UIKit +import CoreData import CoreStore @@ -24,10 +25,10 @@ class AppDelegate: UIResponder, UIApplicationDelegate { application.statusBarStyle = .LightContent - print(InMemoryStore()) - print(SQLiteStore()) - print(LocalStorageOptions.None) - print([.AllowSynchronousLightweightMigration, .PreventProgressiveMigration] as LocalStorageOptions) + print(CoreStoreError.MappingModelNotFound(localStoreURL: NSURL(string: "file://sample.db")!, targetModel: NSManagedObjectModel.mergedModelFromBundles(nil)!, targetModelVersion: "Sample-1.0.0")) + CoreStore.defaultStack = DataStack(migrationChain: ["Sample-1.0.0": "Sample-1.0.2", "Sample-1.0.1": "Sample-1.0.2"]) + print(CoreStore.defaultStack) + print(CoreStore.beginUnsafe()) return true } diff --git a/CoreStoreDemo/CoreStoreDemo/MIgrations Demo/MigrationsDemoViewController.swift b/CoreStoreDemo/CoreStoreDemo/MIgrations Demo/MigrationsDemoViewController.swift index 945332d..c5a42be 100644 --- a/CoreStoreDemo/CoreStoreDemo/MIgrations Demo/MigrationsDemoViewController.swift +++ b/CoreStoreDemo/CoreStoreDemo/MIgrations Demo/MigrationsDemoViewController.swift @@ -157,7 +157,7 @@ class MigrationsDemoViewController: UIViewController { ) self.setEnabled(false) - let progress = try! dataStack.addStorage( + let progress = dataStack.addStorage( SQLiteStore(fileName: "MigrationDemo.sqlite"), completion: { [weak self] (result) -> Void in diff --git a/Sources/Logging/CoreStore+CustomDebugStringConvertible.swift b/Sources/Logging/CoreStore+CustomDebugStringConvertible.swift index d10d781..7038695 100644 --- a/Sources/Logging/CoreStore+CustomDebugStringConvertible.swift +++ b/Sources/Logging/CoreStore+CustomDebugStringConvertible.swift @@ -26,6 +26,74 @@ import Foundation +// MARK: - AsynchronousDataTransaction + +extension AsynchronousDataTransaction: CustomDebugStringConvertible, IndentableDebugStringConvertible { + + // MARK: CustomDebugStringConvertible + + public var debugDescription: String { + + return self.cs_dump() + } + + + // MARK: IndentableDebugStringConvertible + + private var cs_dumpInfo: DumpInfo { + + return [ + ("context", self.context), + ("supportsUndo", self.supportsUndo), + ("bypassesQueueing", self.bypassesQueueing), + ("isCommitted", self.isCommitted), + ("result", self.result) + ] + } +} + + +// MARK: - CloudStorageOptions + +extension CloudStorageOptions: CustomDebugStringConvertible, IndentableDebugStringConvertible { + + // MARK: CustomDebugStringConvertible + + public var debugDescription: String { + + return self.cs_dump() + } + + + // MARK: IndentableDebugStringConvertible + + private var cs_dumpValue: String { + + var flags = [String]() + if self.contains(.RecreateLocalStoreOnModelMismatch) { + + flags.append(".RecreateLocalStoreOnModelMismatch") + } + if self.contains(.AllowSynchronousLightweightMigration) { + + flags.append(".AllowSynchronousLightweightMigration") + } + switch flags.count { + + case 0: + return "[.None]" + + case 1: + return "[.\(flags[0])]" + + default: + let description = "[\n" + flags.joinWithSeparator(",\n") + return description.indent(1) + "\n]" + } + } +} + + // MARK: - CoreStoreError extension CoreStoreError: CustomDebugStringConvertible, IndentableDebugStringConvertible { @@ -55,8 +123,8 @@ extension CoreStoreError: CustomDebugStringConvertible, IndentableDebugStringCon private var cs_dumpInfo: DumpInfo { var info: DumpInfo = [ - ("_domain", self._domain.cs_dump()), - ("_code", self._code.cs_dump()), + ("_domain", self._domain), + ("_code", self._code), ] switch self { @@ -64,24 +132,78 @@ extension CoreStoreError: CustomDebugStringConvertible, IndentableDebugStringCon break case .DifferentStorageExistsAtURL(let existingPersistentStoreURL): - info.append(("existingPersistentStoreURL", existingPersistentStoreURL.cs_dump())) + info.append(("existingPersistentStoreURL", existingPersistentStoreURL)) case .MappingModelNotFound(let localStoreURL, let targetModel, let targetModelVersion): - info.append(("localStoreURL", localStoreURL.cs_dump())) - info.append(("targetModel", targetModel.cs_dump())) - info.append(("targetModelVersion", targetModelVersion.cs_dump())) + info.append(("localStoreURL", localStoreURL)) + info.append(("targetModel", targetModel)) + info.append(("targetModelVersion", targetModelVersion)) case .ProgressiveMigrationRequired(let localStoreURL): - info.append(("localStoreURL", localStoreURL.cs_dump())) + info.append(("localStoreURL", localStoreURL)) case .InternalError(let NSError): - info.append(("NSError", NSError.cs_dump())) + info.append(("NSError", NSError)) } return info } } +// MARK: - DataStack + +extension DataStack: CustomDebugStringConvertible, IndentableDebugStringConvertible { + + // MARK: CustomDebugStringConvertible + + public var debugDescription: String { + + return self.cs_dump() + } + + + // MARK: IndentableDebugStringConvertible + + private var cs_dumpInfo: DumpInfo { + + // TODO: print entities and persistentStores + return [ + ("coordinator", self.coordinator), + ("rootSavingContext", self.rootSavingContext), + ("mainContext", self.mainContext), + ("model", self.model), + ("migrationChain", self.migrationChain) + ] + } +} + + +// MARK: - ICloudStore + +extension ICloudStore: CustomDebugStringConvertible, IndentableDebugStringConvertible { + + // MARK: CustomDebugStringConvertible + + public var debugDescription: String { + + return self.cs_dump() + } + + + // MARK: IndentableDebugStringConvertible + + private var cs_dumpInfo: DumpInfo { + + return [ + ("configuration", self.configuration), + ("storeOptions", self.storeOptions), + ("cacheFileURL", self.cacheFileURL), + ("cloudStorageOptions", self.cloudStorageOptions) + ] + } +} + + // MARK: - InMemoryStore extension InMemoryStore: CustomDebugStringConvertible, IndentableDebugStringConvertible { @@ -106,6 +228,58 @@ extension InMemoryStore: CustomDebugStringConvertible, IndentableDebugStringConv } +// MARK: - Into + +extension Into: CustomDebugStringConvertible, IndentableDebugStringConvertible { + + // MARK: CustomDebugStringConvertible + + public var debugDescription: String { + + return self.cs_dump() + } + + + // MARK: IndentableDebugStringConvertible + + private var cs_dumpInfo: DumpInfo { + + return [ + ("entityClass", self.entityClass), + ("configuration", self.configuration), + ("inferStoreIfPossible", self.inferStoreIfPossible) + ] + } +} + + +// MARK: - LegacySQLiteStore + +extension LegacySQLiteStore: CustomDebugStringConvertible, IndentableDebugStringConvertible { + + // MARK: CustomDebugStringConvertible + + public var debugDescription: String { + + return self.cs_dump() + } + + + // MARK: IndentableDebugStringConvertible + + private var cs_dumpInfo: DumpInfo { + + return [ + ("configuration", self.configuration), + ("storeOptions", self.storeOptions), + ("fileURL", self.fileURL), + ("mappingModelBundles", self.mappingModelBundles), + ("localStorageOptions", self.localStorageOptions) + ] + } +} + + // MARK: - LocalStorageOptions extension LocalStorageOptions: CustomDebugStringConvertible, IndentableDebugStringConvertible { @@ -151,6 +325,58 @@ extension LocalStorageOptions: CustomDebugStringConvertible, IndentableDebugStri } +// MARK: - MigrationChain + +extension MigrationChain: CustomDebugStringConvertible, IndentableDebugStringConvertible { + + // MARK: CustomDebugStringConvertible + + public var debugDescription: String { + + return self.cs_dump() + } + + + // MARK: IndentableDebugStringConvertible + + private var cs_dumpValue: String { + + guard self.valid else { + + return "" + } + + var paths = [String]() + for var version in self.rootVersions { + + var steps = [version] + while let nextVersion = self.nextVersionFrom(version) { + + steps.append(nextVersion) + version = nextVersion + } + paths.append(steps.joinWithSeparator(" → ")) + } + switch paths.count { + + case 0: + return "[]" + + case 1: + return "[\(paths[0])]" + + default: + var dump = "[" + paths.forEach { + + dump.appendContentsOf("\n\($0);") + } + return dump.indent(1) + "\n]" + } + } +} + + // MARK: - SQLiteStore extension SQLiteStore: CustomDebugStringConvertible, IndentableDebugStringConvertible { @@ -178,9 +404,9 @@ extension SQLiteStore: CustomDebugStringConvertible, IndentableDebugStringConver } -// MARK: - LegacySQLiteStore +// MARK: - SynchronousDataTransaction -extension LegacySQLiteStore: CustomDebugStringConvertible, IndentableDebugStringConvertible { +extension SynchronousDataTransaction: CustomDebugStringConvertible, IndentableDebugStringConvertible { // MARK: CustomDebugStringConvertible @@ -195,19 +421,43 @@ extension LegacySQLiteStore: CustomDebugStringConvertible, IndentableDebugString private var cs_dumpInfo: DumpInfo { return [ - ("configuration", self.configuration), - ("storeOptions", self.storeOptions), - ("fileURL", self.fileURL), - ("mappingModelBundles", self.mappingModelBundles), - ("localStorageOptions", self.localStorageOptions) + ("context", self.context), + ("supportsUndo", self.supportsUndo), + ("bypassesQueueing", self.bypassesQueueing), + ("isCommitted", self.isCommitted), + ("result", self.result) ] } } -// MARK: - Private +// MARK: - UnsafeDataTransaction -private typealias DumpInfo = [(key: String, value: IndentableDebugStringConvertible)] +extension UnsafeDataTransaction: CustomDebugStringConvertible, IndentableDebugStringConvertible { + + // MARK: CustomDebugStringConvertible + + public var debugDescription: String { + + return self.cs_dump() + } + + + // MARK: IndentableDebugStringConvertible + + private var cs_dumpInfo: DumpInfo { + + return [ + ("context", self.context), + ("supportsUndo", self.supportsUndo) + ] + } +} + + +// MARK: - Private: Utilities + +private typealias DumpInfo = [(key: String, value: Any)] private func formattedValue(any: Any) -> String { @@ -223,6 +473,41 @@ private func formattedValue(any: IndentableDebugStringConvertible) -> String { return any.cs_dumpValue } +private extension String { + + private static func indention(level: Int = 1) -> String { + + return String(count: level * 4, repeatedValue: Character(" ")) + } + + private func trimSwiftModuleName() -> String { + + if self.hasPrefix("Swift.") { + + return self.substringFromIndex("Swift.".endIndex) + } + return self + } + + private func indent(level: Int) -> String { + + return self.stringByReplacingOccurrencesOfString("\n", withString: "\n\(String.indention(level))") + } + + private mutating func appendDumpInfo(key: String, _ value: Any) { + + self.appendContentsOf("\n.\(key) = \(formattedValue(value));") + } + + private mutating func appendDumpInfo(key: String, _ value: IndentableDebugStringConvertible) { + + self.appendContentsOf("\n.\(key) = \(formattedValue(value));") + } +} + + +// MARK: - Private: IndentableDebugStringConvertible + private protocol IndentableDebugStringConvertible { static func cs_typeString() -> String @@ -267,70 +552,17 @@ private extension IndentableDebugStringConvertible { else { dump.appendContentsOf(" {") - for (key, value) in info { + info.forEach { - dump.appendContentsOf("\n.\(key) = \(formattedValue(value))") + dump.appendDumpInfo($0, $1) } return dump.indent(1) + "\n}" } } } -extension String: IndentableDebugStringConvertible { - - private var cs_dumpValue: String { - - return "\"\(self)\"" - } -} -extension NSURL: IndentableDebugStringConvertible { - - private var cs_dumpValue: String { - - return "\"\(self)\"" - } -} - -extension Int: IndentableDebugStringConvertible { - - private var cs_dumpValue: String { - - return "\(self)" - } -} - -extension NSManagedObjectModel: IndentableDebugStringConvertible { - - private var cs_dumpValue: String { - - return "\(self)" - } -} - -extension NSMappingModel: IndentableDebugStringConvertible { - - private var cs_dumpValue: String { - - return "\(self)" - } -} - -extension NSError: IndentableDebugStringConvertible { - - private var cs_dumpValue: String { - - return "\(self)" - } -} - -extension NSBundle: IndentableDebugStringConvertible { - - private var cs_dumpValue: String { - - return "\(self.bundleURL.lastPathComponent ?? "") (\(self.bundleIdentifier ?? ""))" - } -} +// MARK: - extension Array: IndentableDebugStringConvertible { @@ -374,6 +606,172 @@ extension Dictionary: IndentableDebugStringConvertible { } } +extension NSAttributeDescription: IndentableDebugStringConvertible { + + private var cs_dumpValue: String { + + var string = "{" + + string.appendDumpInfo("attributeType", self.attributeType) + string.appendDumpInfo("attributeValueClassName", self.attributeValueClassName) + string.appendDumpInfo("defaultValue", self.defaultValue) + string.appendDumpInfo("valueTransformerName", self.valueTransformerName) + string.appendDumpInfo("allowsExternalBinaryDataStorage", self.allowsExternalBinaryDataStorage) + + string.appendDumpInfo("entity", self.entity.name) + string.appendDumpInfo("name", self.name) + string.appendDumpInfo("optional", self.optional) + string.appendDumpInfo("transient", self.transient) + string.appendDumpInfo("userInfo", self.userInfo) + string.appendDumpInfo("indexed", self.indexed) + string.appendDumpInfo("versionHash", self.versionHash) + string.appendDumpInfo("versionHashModifier", self.versionHashModifier) + string.appendDumpInfo("indexedBySpotlight", self.indexedBySpotlight) + string.appendDumpInfo("storedInExternalRecord", self.storedInExternalRecord) + string.appendDumpInfo("renamingIdentifier", self.renamingIdentifier) + + return string.indent(1) + "\n}" + } +} + +extension NSAttributeType: IndentableDebugStringConvertible { + + private var cs_dumpValue: String { + + switch self { + + case .UndefinedAttributeType: return ".UndefinedAttributeType" + case .Integer16AttributeType: return ".Integer16AttributeType" + case .Integer32AttributeType: return ".Integer32AttributeType" + case .Integer64AttributeType: return ".Integer64AttributeType" + case .DecimalAttributeType: return ".DecimalAttributeType" + case .DoubleAttributeType: return ".DoubleAttributeType" + case .FloatAttributeType: return ".FloatAttributeType" + case .StringAttributeType: return ".StringAttributeType" + case .BooleanAttributeType: return ".BooleanAttributeType" + case .DateAttributeType: return ".DateAttributeType" + case .BinaryDataAttributeType: return ".BinaryDataAttributeType" + case .TransformableAttributeType: return ".TransformableAttributeType" + case .ObjectIDAttributeType: return ".ObjectIDAttributeType" + } + } +} + +extension NSBundle: IndentableDebugStringConvertible { + + private var cs_dumpValue: String { + + return "\(self.bundleIdentifier.flatMap({ "\"\($0)\"" }) ?? "") (\(self.bundleURL.lastPathComponent ?? ""))" + } +} + +extension NSDeleteRule: IndentableDebugStringConvertible { + + private var cs_dumpValue: String { + + switch self { + + case .NoActionDeleteRule: return ".NoActionDeleteRule" + case .NullifyDeleteRule: return ".NullifyDeleteRule" + case .CascadeDeleteRule: return ".CascadeDeleteRule" + case .DenyDeleteRule: return ".DenyDeleteRule" + } + } +} + +extension NSEntityDescription: IndentableDebugStringConvertible { + + private var cs_dumpValue: String { + + var string = "{" + string.appendDumpInfo("managedObjectClassName", self.managedObjectClassName!) + string.appendDumpInfo("name", self.name) + string.appendDumpInfo("abstract", self.abstract) + string.appendDumpInfo("superentity", self.superentity?.name) + string.appendDumpInfo("subentities", self.subentities.map({ $0.name })) + string.appendDumpInfo("properties", self.properties) + string.appendDumpInfo("userInfo", self.userInfo) + string.appendDumpInfo("versionHash", self.versionHash) + string.appendDumpInfo("versionHashModifier", self.versionHashModifier) + string.appendDumpInfo("renamingIdentifier", self.renamingIdentifier) + string.appendDumpInfo("compoundIndexes", self.compoundIndexes) + if #available(iOS 9.0, *) { + + string.appendDumpInfo("uniquenessConstraints", self.uniquenessConstraints) + } + return string.indent(1) + "\n}" + } +} + +extension NSError: IndentableDebugStringConvertible { + + private var cs_dumpValue: String { + + var string = "{" + string.appendDumpInfo("domain", self.domain) + string.appendDumpInfo("code", self.code) + string.appendDumpInfo("userInfo", self.userInfo) + return string.indent(1) + "\n}" + } +} + +extension NSManagedObjectModel: IndentableDebugStringConvertible { + + private var cs_dumpValue: String { + + var string = "{" + string.appendDumpInfo("configurations", self.configurations) + string.appendDumpInfo("entities", self.entities) + return string.indent(1) + "\n}" + } +} + +extension NSMappingModel: IndentableDebugStringConvertible { + + private var cs_dumpValue: String { + + return "\(self)" + } +} + +extension NSRelationshipDescription: IndentableDebugStringConvertible { + + private var cs_dumpValue: String { + + var string = "{" + + string.appendDumpInfo("destinationEntity", self.destinationEntity?.name) + string.appendDumpInfo("inverseRelationship", self.inverseRelationship?.name) + string.appendDumpInfo("minCount", self.minCount) + string.appendDumpInfo("maxCount", self.maxCount) + string.appendDumpInfo("deleteRule", self.deleteRule) + string.appendDumpInfo("toMany", self.toMany) + string.appendDumpInfo("ordered", self.ordered) + + string.appendDumpInfo("entity", self.entity.name) + string.appendDumpInfo("name", self.name) + string.appendDumpInfo("optional", self.optional) + string.appendDumpInfo("transient", self.transient) + string.appendDumpInfo("userInfo", self.userInfo) + string.appendDumpInfo("indexed", self.indexed) + string.appendDumpInfo("versionHash", self.versionHash) + string.appendDumpInfo("versionHashModifier", self.versionHashModifier) + string.appendDumpInfo("indexedBySpotlight", self.indexedBySpotlight) + string.appendDumpInfo("storedInExternalRecord", self.storedInExternalRecord) + string.appendDumpInfo("renamingIdentifier", self.renamingIdentifier) + + return string.indent(1) + "\n}" + } +} + +extension NSURL: IndentableDebugStringConvertible { + + private var cs_dumpValue: String { + + return "\"\(self)\"" + } +} + extension Optional: IndentableDebugStringConvertible { private var cs_dumpValue: String { @@ -386,24 +784,10 @@ extension Optional: IndentableDebugStringConvertible { } } -private extension String { +extension String: IndentableDebugStringConvertible { - private static func indention(level: Int = 1) -> String { + private var cs_dumpValue: String { - return String(count: level * 4, repeatedValue: Character(" ")) - } - - private func trimSwiftModuleName() -> String { - - if self.hasPrefix("Swift.") { - - return self.substringFromIndex("Swift.".endIndex) - } - return self - } - - private func indent(level: Int) -> String { - - return self.stringByReplacingOccurrencesOfString("\n", withString: "\n\(String.indention(level))") + return "\"\(self)\"" } } diff --git a/Sources/Migrating/DataStack+Migration.swift b/Sources/Migrating/DataStack+Migration.swift index f3d2433..70559e1 100644 --- a/Sources/Migrating/DataStack+Migration.swift +++ b/Sources/Migrating/DataStack+Migration.swift @@ -845,27 +845,20 @@ public extension DataStack { @available(*, deprecated=2.0.0, message="Use addStorage(_:completion:) by passing a InMemoryStore instance.") public func addInMemoryStore(configuration configuration: String? = nil, completion: (PersistentStoreResult) -> Void) { - do { - - try self.addStorage( - InMemoryStore(configuration: configuration), - completion: { result in + self.addStorage( + InMemoryStore(configuration: configuration), + completion: { result in + + switch result { - switch result { - - case .Success(let storage): - completion(PersistentStoreResult(self.persistentStoreForStorage(storage)!)) - - case .Failure(let error): - completion(PersistentStoreResult(error as NSError)) - } + case .Success(let storage): + completion(PersistentStoreResult(self.persistentStoreForStorage(storage)!)) + + case .Failure(let error): + completion(PersistentStoreResult(error as NSError)) } - ) - } - catch { - - completion(PersistentStoreResult(error as NSError)) - } + } + ) } /** @@ -876,7 +869,7 @@ public extension DataStack { @available(*, deprecated=2.0.0, message="Use addStorage(_:completion:) by passing a LegacySQLiteStore instance. Warning: The default SQLite file location for the LegacySQLiteStore and SQLiteStore are different. If the app was using this method prior to 2.0.0, make sure to use LegacySQLiteStore.") public func addSQLiteStore(fileName fileName: String, configuration: String? = nil, mappingModelBundles: [NSBundle]? = nil, resetStoreOnModelMismatch: Bool = false, completion: (PersistentStoreResult) -> Void) throws -> NSProgress? { - return try self.addStorage( + return self.addStorage( LegacySQLiteStore( fileName: fileName, configuration: configuration, @@ -905,7 +898,7 @@ public extension DataStack { @available(*, deprecated=2.0.0, message="Use addSQLiteStore(_:completion:) by passing a LegacySQLiteStore instance. Warning: The default SQLite file location for the LegacySQLiteStore and SQLiteStore are different. If the app was using this method prior to 2.0.0, make sure to use LegacySQLiteStore.") public func addSQLiteStore(fileURL fileURL: NSURL = LegacySQLiteStore.defaultFileURL, configuration: String? = nil, mappingModelBundles: [NSBundle]? = NSBundle.allBundles(), resetStoreOnModelMismatch: Bool = false, completion: (PersistentStoreResult) -> Void) throws -> NSProgress? { - return try self.addStorage( + return self.addStorage( LegacySQLiteStore( fileURL: fileURL, configuration: configuration, diff --git a/Sources/Migrating/MigrationChain.swift b/Sources/Migrating/MigrationChain.swift index 452037d..0567082 100644 --- a/Sources/Migrating/MigrationChain.swift +++ b/Sources/Migrating/MigrationChain.swift @@ -248,31 +248,3 @@ public struct MigrationChain: NilLiteralConvertible, StringLiteralConvertible, D private let versionTree: [String: String] } - - -// MARK: - MigrationChain: CustomDebugStringConvertible - -extension MigrationChain: CustomDebugStringConvertible { - - public var debugDescription: String { - - guard self.valid else { - - return "" - } - - var paths = [String]() - for var version in self.rootVersions { - - var steps = [version] - while let nextVersion = self.nextVersionFrom(version) { - - steps.append(nextVersion) - version = nextVersion - } - paths.append(steps.joinWithSeparator(" → ")) - } - - return "[" + paths.joinWithSeparator("], [") + "]" - } -} diff --git a/Sources/ObjectiveC/CSDataStack+Migrating.swift b/Sources/ObjectiveC/CSDataStack+Migrating.swift index f47481b..5d7869c 100644 --- a/Sources/ObjectiveC/CSDataStack+Migrating.swift +++ b/Sources/ObjectiveC/CSDataStack+Migrating.swift @@ -83,7 +83,7 @@ public extension CSDataStack { return bridge(error) { - try self.bridgeToSwift.addStorage( + self.bridgeToSwift.addStorage( storage.bridgeToSwift, completion: { completion($0.bridgeToObjectiveC) } )