refactor logging functions

This commit is contained in:
John Rommel Estropia
2015-02-28 11:32:41 +09:00
parent 59cd505dc6
commit 55dee6ec2f
11 changed files with 151 additions and 118 deletions

View File

@@ -23,6 +23,7 @@
B5D022661A90CD340070CA63 /* DataStack+Transaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D022651A90CD340070CA63 /* DataStack+Transaction.swift */; }; B5D022661A90CD340070CA63 /* DataStack+Transaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D022651A90CD340070CA63 /* DataStack+Transaction.swift */; };
B5D19BFB1AA14063001D1A99 /* AsynchronousDataTransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D19BFA1AA14063001D1A99 /* AsynchronousDataTransaction.swift */; }; B5D19BFB1AA14063001D1A99 /* AsynchronousDataTransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D19BFA1AA14063001D1A99 /* AsynchronousDataTransaction.swift */; };
B5D19BFF1AA14351001D1A99 /* SynchronousDataTransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D19BFE1AA14351001D1A99 /* SynchronousDataTransaction.swift */; }; B5D19BFF1AA14351001D1A99 /* SynchronousDataTransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D19BFE1AA14351001D1A99 /* SynchronousDataTransaction.swift */; };
B5D19C011AA15E1F001D1A99 /* HardcoreData+Logging.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D19C001AA15E1F001D1A99 /* HardcoreData+Logging.swift */; };
B5D1E22A19FA9E63003B2874 /* PersistentStoreResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D1E22919FA9E63003B2874 /* PersistentStoreResult.swift */; }; B5D1E22A19FA9E63003B2874 /* PersistentStoreResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D1E22919FA9E63003B2874 /* PersistentStoreResult.swift */; };
B5D1E22C19FA9FBC003B2874 /* NSError+HardcoreData.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D1E22B19FA9FBC003B2874 /* NSError+HardcoreData.swift */; }; B5D1E22C19FA9FBC003B2874 /* NSError+HardcoreData.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D1E22B19FA9FBC003B2874 /* NSError+HardcoreData.swift */; };
B5D372841A39CD6900F583D9 /* Model.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = B5D372821A39CD6900F583D9 /* Model.xcdatamodeld */; }; B5D372841A39CD6900F583D9 /* Model.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = B5D372821A39CD6900F583D9 /* Model.xcdatamodeld */; };
@@ -90,6 +91,7 @@
B5D022651A90CD340070CA63 /* DataStack+Transaction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "DataStack+Transaction.swift"; sourceTree = "<group>"; }; B5D022651A90CD340070CA63 /* DataStack+Transaction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "DataStack+Transaction.swift"; sourceTree = "<group>"; };
B5D19BFA1AA14063001D1A99 /* AsynchronousDataTransaction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AsynchronousDataTransaction.swift; sourceTree = "<group>"; }; B5D19BFA1AA14063001D1A99 /* AsynchronousDataTransaction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AsynchronousDataTransaction.swift; sourceTree = "<group>"; };
B5D19BFE1AA14351001D1A99 /* SynchronousDataTransaction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SynchronousDataTransaction.swift; sourceTree = "<group>"; }; B5D19BFE1AA14351001D1A99 /* SynchronousDataTransaction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SynchronousDataTransaction.swift; sourceTree = "<group>"; };
B5D19C001AA15E1F001D1A99 /* HardcoreData+Logging.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "HardcoreData+Logging.swift"; sourceTree = "<group>"; };
B5D1E22919FA9E63003B2874 /* PersistentStoreResult.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PersistentStoreResult.swift; sourceTree = "<group>"; }; B5D1E22919FA9E63003B2874 /* PersistentStoreResult.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PersistentStoreResult.swift; sourceTree = "<group>"; };
B5D1E22B19FA9FBC003B2874 /* NSError+HardcoreData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSError+HardcoreData.swift"; sourceTree = "<group>"; }; B5D1E22B19FA9FBC003B2874 /* NSError+HardcoreData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSError+HardcoreData.swift"; sourceTree = "<group>"; };
B5D372831A39CD6900F583D9 /* Model.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Model.xcdatamodel; sourceTree = "<group>"; }; B5D372831A39CD6900F583D9 /* Model.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Model.xcdatamodel; sourceTree = "<group>"; };
@@ -307,6 +309,7 @@
children = ( children = (
B5F409E81A8B11CE00A228EA /* HardcoreDataLogger.swift */, B5F409E81A8B11CE00A228EA /* HardcoreDataLogger.swift */,
B5F409EA1A8B199600A228EA /* DefaultLogger.swift */, B5F409EA1A8B199600A228EA /* DefaultLogger.swift */,
B5D19C001AA15E1F001D1A99 /* HardcoreData+Logging.swift */,
); );
name = Logging; name = Logging;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -443,6 +446,7 @@
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
B5CFF24019FD383100D6DFC4 /* DataTransaction.swift in Sources */, B5CFF24019FD383100D6DFC4 /* DataTransaction.swift in Sources */,
B5D19C011AA15E1F001D1A99 /* HardcoreData+Logging.swift in Sources */,
B5D399F519FCF4E0000E91BB /* NSPersistentStoreCoordinator+HardcoreData.swift in Sources */, B5D399F519FCF4E0000E91BB /* NSPersistentStoreCoordinator+HardcoreData.swift in Sources */,
B5CFD36E1A0775F000B7885F /* SaveResult.swift in Sources */, B5CFD36E1A0775F000B7885F /* SaveResult.swift in Sources */,
B5D022661A90CD340070CA63 /* DataStack+Transaction.swift in Sources */, B5D022661A90CD340070CA63 /* DataStack+Transaction.swift in Sources */,

View File

@@ -94,7 +94,7 @@ public class DataStack {
public func addInMemoryStore(configuration: String? = nil) -> PersistentStoreResult { public func addInMemoryStore(configuration: String? = nil) -> PersistentStoreResult {
let coordinator = self.coordinator; let coordinator = self.coordinator;
var persistentStoreError: NSError? var error: NSError?
var store: NSPersistentStore? var store: NSPersistentStore?
coordinator.performSynchronously { coordinator.performSynchronously {
@@ -104,7 +104,7 @@ public class DataStack {
configuration: configuration, configuration: configuration,
URL: nil, URL: nil,
options: nil, options: nil,
error: &persistentStoreError) error: &error)
} }
if let store = store { if let store = store {
@@ -112,20 +112,20 @@ public class DataStack {
return PersistentStoreResult(store) return PersistentStoreResult(store)
} }
if let error = persistentStoreError { if let error = error {
HardcoreData.handleError( HardcoreData.handleError(
error, error,
"Failed to add in-memory NSPersistentStore.") "Failed to add in-memory \(NSPersistentStore.self).")
return PersistentStoreResult(error) return PersistentStoreResult(error)
} }
else { else {
HardcoreData.handleError( HardcoreData.handleError(
NSError(hardcoreDataErrorCode: .UnknownError), NSError(hardcoreDataErrorCode: .UnknownError),
"Failed to add in-memory NSPersistentStore.") "Failed to add in-memory \(NSPersistentStore.self).")
return PersistentStoreResult(.UnknownError)
} }
return PersistentStoreResult(.UnknownError)
} }
/** /**
@@ -174,7 +174,8 @@ public class DataStack {
HardcoreData.handleError( HardcoreData.handleError(
NSError(hardcoreDataErrorCode: .DifferentPersistentStoreExistsAtURL), NSError(hardcoreDataErrorCode: .DifferentPersistentStoreExistsAtURL),
"Failed to add SQLite NSPersistentStore at \"\(fileURL)\" because a different NSPersistentStore at that URL already exists.") "Failed to add SQLite \(NSPersistentStore.self) at \"\(fileURL)\" because a different \(NSPersistentStore.self) at that URL already exists.")
return PersistentStoreResult(.DifferentPersistentStoreExistsAtURL) return PersistentStoreResult(.DifferentPersistentStoreExistsAtURL)
} }
@@ -187,7 +188,7 @@ public class DataStack {
error: &directoryError) { error: &directoryError) {
HardcoreData.handleError( HardcoreData.handleError(
directoryError!, directoryError ?? NSError(hardcoreDataErrorCode: .UnknownError),
"Failed to create directory for SQLite store at \"\(fileURL)\".") "Failed to create directory for SQLite store at \"\(fileURL)\".")
return PersistentStoreResult(directoryError!) return PersistentStoreResult(directoryError!)
} }
@@ -211,54 +212,45 @@ public class DataStack {
return PersistentStoreResult(store) return PersistentStoreResult(store)
} }
if let error = persistentStoreError { if let error = persistentStoreError
where (
if resetStoreOnMigrationFailure resetStoreOnMigrationFailure
&& (error.code == NSPersistentStoreIncompatibleVersionHashError && (error.code == NSPersistentStoreIncompatibleVersionHashError
|| error.code == NSMigrationMissingSourceModelError) || error.code == NSMigrationMissingSourceModelError)
&& error.domain == NSCocoaErrorDomain { && error.domain == NSCocoaErrorDomain
) {
fileManager.removeItemAtURL(fileURL, error: nil)
fileManager.removeItemAtPath(
fileURL.path!.stringByAppendingString("-shm"),
error: nil)
fileManager.removeItemAtPath(
fileURL.path!.stringByAppendingString("-wal"),
error: nil)
var store: NSPersistentStore?
coordinator.performSynchronously {
fileManager.removeItemAtURL(fileURL, error: nil) store = coordinator.addPersistentStoreWithType(
fileManager.removeItemAtPath( NSSQLiteStoreType,
fileURL.path!.stringByAppendingString("-shm"), configuration: configuration,
error: nil) URL: fileURL,
fileManager.removeItemAtPath( options: [NSSQLitePragmasOption: ["WAL": "journal_mode"],
fileURL.path!.stringByAppendingString("-wal"), NSInferMappingModelAutomaticallyOption: true,
error: nil) NSMigratePersistentStoresAutomaticallyOption: automigrating],
error: &persistentStoreError)
}
if let store = store {
var store: NSPersistentStore? return PersistentStoreResult(store)
coordinator.performSynchronously { }
store = coordinator.addPersistentStoreWithType(
NSSQLiteStoreType,
configuration: configuration,
URL: fileURL,
options: [NSSQLitePragmasOption: ["WAL": "journal_mode"],
NSInferMappingModelAutomaticallyOption: true,
NSMigratePersistentStoresAutomaticallyOption: automigrating],
error: &persistentStoreError)
}
if let store = store {
return PersistentStoreResult(store)
}
}
} }
if let error = persistentStoreError { HardcoreData.handleError(
persistentStoreError ?? NSError(hardcoreDataErrorCode: .UnknownError),
HardcoreData.handleError( "Failed to add SQLite \(NSPersistentStore.self) at \"\(fileURL)\".")
error,
"Failed to add SQLite NSPersistentStore at \"\(fileURL)\".")
return PersistentStoreResult(error)
}
else {
HardcoreData.handleError(
NSError(hardcoreDataErrorCode: .UnknownError),
"Failed to add SQLite NSPersistentStore at \"\(fileURL)\".")
}
return PersistentStoreResult(.UnknownError) return PersistentStoreResult(.UnknownError)
} }

View File

@@ -46,7 +46,7 @@ public /*abstract*/ class DataTransaction {
public func create<T: NSManagedObject>(entity: T.Type) -> T { public func create<T: NSManagedObject>(entity: T.Type) -> T {
HardcoreData.assert(self.transactionQueue.isCurrentExecutionContext() == true, "Attempted to create an entity of type \(entity) outside a transaction queue.") HardcoreData.assert(self.transactionQueue.isCurrentExecutionContext() == true, "Attempted to create an entity of type \(entity) outside a transaction queue.")
HardcoreData.assert(!self.isCommitted, "Attempted to create an NSManagedObject from an already committed \(self.dynamicType).") HardcoreData.assert(!self.isCommitted, "Attempted to create an entity of type \(entity) from an already committed \(self.dynamicType).")
return T.createInContext(self.context) return T.createInContext(self.context)
} }

View File

@@ -0,0 +1,75 @@
//
// HardcoreData+Logging.swift
// HardcoreData
//
// Copyright (c) 2015 John Rommel Estropia
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
import Foundation
// MARK: - HardcoreData
public extension HardcoreData {
// MARK: Public
/**
The HardcoreDataLogger instance to be used. The default logger is an instance of a DefaultLogger.
*/
public static var logger: HardcoreDataLogger = DefaultLogger()
// MARK: Internal
internal static func log(level: LogLevel, message: String, fileName: StaticString = __FILE__, lineNumber: Int = __LINE__, functionName: StaticString = __FUNCTION__) {
self.logger.log(
level: level,
message: message,
fileName: fileName,
lineNumber:
lineNumber,
functionName:
functionName
)
}
internal static func handleError(error: NSError, _ message: String, fileName: StaticString = __FILE__, lineNumber: Int = __LINE__, functionName: StaticString = __FUNCTION__) {
self.logger.handleError(
error: error,
message: message,
fileName: fileName,
lineNumber: lineNumber,
functionName: functionName)
}
internal static func assert(@autoclosure condition: () -> Bool, _ message: String, fileName: StaticString = __FILE__, lineNumber: Int = __LINE__, functionName: StaticString = __FUNCTION__) {
self.logger.assert(
condition,
message: message,
fileName: fileName,
lineNumber: lineNumber,
functionName: functionName)
}
}

View File

@@ -70,48 +70,6 @@ public enum HardcoreData {
} }
/**
The HardcoreDataLogger instance to be used. The default logger is an instance of a DefaultLogger.
*/
public static var logger: HardcoreDataLogger = DefaultLogger()
// MARK: Internal
internal static func log(level: LogLevel, message: String, fileName: StaticString = __FILE__, lineNumber: Int = __LINE__, functionName: StaticString = __FUNCTION__) {
self.logger.log(
level: level,
message: message,
fileName: fileName,
lineNumber:
lineNumber,
functionName:
functionName
)
}
internal static func handleError(error: NSError, _ message: String, fileName: StaticString = __FILE__, lineNumber: Int = __LINE__, functionName: StaticString = __FUNCTION__) {
self.logger.handleError(
error: error,
message: message,
fileName: fileName,
lineNumber: lineNumber,
functionName: functionName)
}
internal static func assert(@autoclosure condition: () -> Bool, _ message: String, fileName: StaticString = __FILE__, lineNumber: Int = __LINE__, functionName: StaticString = __FUNCTION__) {
self.logger.assert(
condition,
message: message,
fileName: fileName,
lineNumber: lineNumber,
functionName: functionName)
}
// MARK: Private // MARK: Private
private static let defaultStackBarrierQueue = GCDQueue.createConcurrent("com.hardcoreData.defaultStackBarrierQueue") private static let defaultStackBarrierQueue = GCDQueue.createConcurrent("com.hardcoreData.defaultStackBarrierQueue")

View File

@@ -59,25 +59,25 @@ internal extension NSManagedObject {
let objectID = self.objectID let objectID = self.objectID
if objectID.temporaryID { if objectID.temporaryID {
var permanentIDError: NSError? var error: NSError?
if !context.obtainPermanentIDsForObjects([self], error: &permanentIDError) { if !context.obtainPermanentIDsForObjects([self], error: &error) {
HardcoreData.handleError( HardcoreData.handleError(
permanentIDError!, error ?? NSError(hardcoreDataErrorCode: .UnknownError),
"Failed to obtain permanent ID for object.") "Failed to obtain permanent ID for object.")
return nil return nil
} }
} }
var existingObjectError: NSError? var error: NSError?
if let existingObject = context.existingObjectWithID(objectID, error: &existingObjectError) { if let existingObject = context.existingObjectWithID(objectID, error: &error) {
return (existingObject as! T) return (existingObject as! T)
} }
HardcoreData.handleError( HardcoreData.handleError(
existingObjectError!, error ?? NSError(hardcoreDataErrorCode: .UnknownError),
"Failed to load existing NSManagedObject in context.") "Failed to load existing \(T.self) in context.")
return nil; return nil;
} }
} }

View File

@@ -75,23 +75,21 @@ internal extension NSManagedObjectContext {
let context = note.object as! NSManagedObjectContext let context = note.object as! NSManagedObjectContext
let insertedObjects = context.insertedObjects let insertedObjects = context.insertedObjects
if insertedObjects.count <= 0 { let numberOfInsertedObjects = insertedObjects.count
if numberOfInsertedObjects <= 0 {
return return
} }
var permanentIDError: NSError? var error: NSError?
if context.obtainPermanentIDsForObjects(Array(insertedObjects), error: &permanentIDError) { if context.obtainPermanentIDsForObjects(Array(insertedObjects), error: &error) {
return return
} }
if let error = permanentIDError { HardcoreData.handleError(
error ?? NSError(hardcoreDataErrorCode: .UnknownError),
HardcoreData.handleError( "Failed to obtain permanent ID(s) for \(numberOfInsertedObjects) inserted object(s).")
error,
"Failed to obtain permanent IDs for inserted objects.")
}
}) })
} }

View File

@@ -58,7 +58,9 @@ public extension NSManagedObjectContext {
} }
if fetchResults == nil { if fetchResults == nil {
HardcoreData.handleError(error!, "Failed executing fetch request.") HardcoreData.handleError(
error ?? NSError(hardcoreDataErrorCode: .UnknownError),
"Failed executing fetch request.")
return nil return nil
} }
@@ -90,7 +92,9 @@ public extension NSManagedObjectContext {
} }
if fetchResults == nil { if fetchResults == nil {
HardcoreData.handleError(error!, "Failed executing fetch request.") HardcoreData.handleError(
error ?? NSError(hardcoreDataErrorCode: .UnknownError),
"Failed executing fetch request.")
return nil return nil
} }
@@ -120,7 +124,9 @@ public extension NSManagedObjectContext {
} }
if count == NSNotFound { if count == NSNotFound {
HardcoreData.handleError(error!, "Failed executing fetch request.") HardcoreData.handleError(
error ?? NSError(hardcoreDataErrorCode: .UnknownError),
"Failed executing fetch request.")
return 0 return 0
} }

View File

@@ -94,7 +94,7 @@ internal extension NSManagedObjectContext {
HardcoreData.handleError( HardcoreData.handleError(
error, error,
"Failed to save NSManagedObjectContext.") "Failed to save \(NSManagedObjectContext.self).")
result = SaveResult(error) result = SaveResult(error)
} }
else { else {
@@ -153,7 +153,7 @@ internal extension NSManagedObjectContext {
HardcoreData.handleError( HardcoreData.handleError(
error, error,
"Failed to save NSManagedObjectContext.") "Failed to save \(NSManagedObjectContext.self).")
if let completion = completion { if let completion = completion {
GCDQueue.Main.async { GCDQueue.Main.async {

View File

@@ -100,7 +100,7 @@ public struct SortedBy: FetchClause {
if fetchRequest.sortDescriptors != nil { if fetchRequest.sortDescriptors != nil {
HardcoreData.log(.Warning, message: "Existing sortDescriptors for the NSFetchRequest was overwritten by SortedBy query clause.") HardcoreData.log(.Warning, message: "Existing sortDescriptors for the \(NSFetchRequest.self) was overwritten by \(self.dynamicType) query clause.")
} }
fetchRequest.sortDescriptors = self.sortDescriptors fetchRequest.sortDescriptors = self.sortDescriptors

View File

@@ -89,7 +89,7 @@ public struct Where: FetchClause {
if fetchRequest.predicate != nil { if fetchRequest.predicate != nil {
HardcoreData.log(.Warning, message: "An existing predicate for the NSFetchRequest was overwritten by Where query clause.") HardcoreData.log(.Warning, message: "An existing predicate for the \(NSFetchRequest.self) was overwritten by \(self.dynamicType) query clause.")
} }
fetchRequest.predicate = self.predicate fetchRequest.predicate = self.predicate