This commit is contained in:
John Rommel Estropia
2017-03-27 01:48:51 +09:00
parent cb6d5b015b
commit 818abfc1a1
12 changed files with 158 additions and 91 deletions

View File

@@ -398,6 +398,10 @@
B59FA0B11CCBACA7007C9BCA /* ICloudStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B59FA0AD1CCBAC95007C9BCA /* ICloudStore.swift */; }; B59FA0B11CCBACA7007C9BCA /* ICloudStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B59FA0AD1CCBAC95007C9BCA /* ICloudStore.swift */; };
B59FA0B21CCBACA8007C9BCA /* ICloudStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B59FA0AD1CCBAC95007C9BCA /* ICloudStore.swift */; }; B59FA0B21CCBACA8007C9BCA /* ICloudStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B59FA0AD1CCBAC95007C9BCA /* ICloudStore.swift */; };
B5A261211B64BFDB006EB6D3 /* MigrationType.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A261201B64BFDB006EB6D3 /* MigrationType.swift */; }; B5A261211B64BFDB006EB6D3 /* MigrationType.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A261201B64BFDB006EB6D3 /* MigrationType.swift */; };
B5A27F861E857C5300203C3E /* TransactionResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A27F851E857C5300203C3E /* TransactionResult.swift */; };
B5A27F871E857C5300203C3E /* TransactionResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A27F851E857C5300203C3E /* TransactionResult.swift */; };
B5A27F881E857C5300203C3E /* TransactionResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A27F851E857C5300203C3E /* TransactionResult.swift */; };
B5A27F891E857C5300203C3E /* TransactionResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A27F851E857C5300203C3E /* TransactionResult.swift */; };
B5A5F2661CAEC50F004AB9AF /* CSSelect.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A5F2651CAEC50F004AB9AF /* CSSelect.swift */; }; B5A5F2661CAEC50F004AB9AF /* CSSelect.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A5F2651CAEC50F004AB9AF /* CSSelect.swift */; };
B5A5F2681CAEC50F004AB9AF /* CSSelect.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A5F2651CAEC50F004AB9AF /* CSSelect.swift */; }; B5A5F2681CAEC50F004AB9AF /* CSSelect.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A5F2651CAEC50F004AB9AF /* CSSelect.swift */; };
B5A5F2691CAEC50F004AB9AF /* CSSelect.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A5F2651CAEC50F004AB9AF /* CSSelect.swift */; }; B5A5F2691CAEC50F004AB9AF /* CSSelect.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A5F2651CAEC50F004AB9AF /* CSSelect.swift */; };
@@ -685,6 +689,7 @@
B59AFF401C6593E400C0ABE2 /* NSPersistentStoreCoordinator+Setup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSPersistentStoreCoordinator+Setup.swift"; sourceTree = "<group>"; }; B59AFF401C6593E400C0ABE2 /* NSPersistentStoreCoordinator+Setup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSPersistentStoreCoordinator+Setup.swift"; sourceTree = "<group>"; };
B59FA0AD1CCBAC95007C9BCA /* ICloudStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ICloudStore.swift; sourceTree = "<group>"; }; B59FA0AD1CCBAC95007C9BCA /* ICloudStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ICloudStore.swift; sourceTree = "<group>"; };
B5A261201B64BFDB006EB6D3 /* MigrationType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MigrationType.swift; sourceTree = "<group>"; }; B5A261201B64BFDB006EB6D3 /* MigrationType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MigrationType.swift; sourceTree = "<group>"; };
B5A27F851E857C5300203C3E /* TransactionResult.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransactionResult.swift; sourceTree = "<group>"; };
B5A5F2651CAEC50F004AB9AF /* CSSelect.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSSelect.swift; sourceTree = "<group>"; }; B5A5F2651CAEC50F004AB9AF /* CSSelect.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSSelect.swift; sourceTree = "<group>"; };
B5AD60CD1C90141E00F2B2E8 /* Package.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = SOURCE_ROOT; }; B5AD60CD1C90141E00F2B2E8 /* Package.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = SOURCE_ROOT; };
B5AEFAB41C9962AE00AD137F /* CoreStoreBridge.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreStoreBridge.swift; sourceTree = "<group>"; }; B5AEFAB41C9962AE00AD137F /* CoreStoreBridge.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreStoreBridge.swift; sourceTree = "<group>"; };
@@ -1160,6 +1165,7 @@
B5E84EEE1AFF846E0064E85B /* CoreStore+Transaction.swift */, B5E84EEE1AFF846E0064E85B /* CoreStore+Transaction.swift */,
B50392F81C478FF3009900CA /* NSManagedObject+Transaction.swift */, B50392F81C478FF3009900CA /* NSManagedObject+Transaction.swift */,
B5E84EF21AFF846E0064E85B /* SaveResult.swift */, B5E84EF21AFF846E0064E85B /* SaveResult.swift */,
B5A27F851E857C5300203C3E /* TransactionResult.swift */,
); );
path = Transactions; path = Transactions;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -1603,6 +1609,7 @@
B549F6731E56A92800FBAB2D /* CoreDataNativeType.swift in Sources */, B549F6731E56A92800FBAB2D /* CoreDataNativeType.swift in Sources */,
B509C7F41E54511B0061C547 /* ImportableAttributeType.swift in Sources */, B509C7F41E54511B0061C547 /* ImportableAttributeType.swift in Sources */,
B5E84F0E1AFF847B0064E85B /* Tweak.swift in Sources */, B5E84F0E1AFF847B0064E85B /* Tweak.swift in Sources */,
B5A27F861E857C5300203C3E /* TransactionResult.swift in Sources */,
B5E1B5931CAA0C15007FD580 /* CSObjectMonitor.swift in Sources */, B5E1B5931CAA0C15007FD580 /* CSObjectMonitor.swift in Sources */,
B5ECDC291CA81CC700C7F112 /* CSDataStack+Transaction.swift in Sources */, B5ECDC291CA81CC700C7F112 /* CSDataStack+Transaction.swift in Sources */,
B5E84F121AFF847B0064E85B /* OrderBy.swift in Sources */, B5E84F121AFF847B0064E85B /* OrderBy.swift in Sources */,
@@ -1759,6 +1766,7 @@
B549F6741E56A92800FBAB2D /* CoreDataNativeType.swift in Sources */, B549F6741E56A92800FBAB2D /* CoreDataNativeType.swift in Sources */,
B509C7F51E54511B0061C547 /* ImportableAttributeType.swift in Sources */, B509C7F51E54511B0061C547 /* ImportableAttributeType.swift in Sources */,
82BA18B31C4BBD3900A0916E /* ImportableUniqueObject.swift in Sources */, 82BA18B31C4BBD3900A0916E /* ImportableUniqueObject.swift in Sources */,
B5A27F871E857C5300203C3E /* TransactionResult.swift in Sources */,
B5E1B5951CAA0C15007FD580 /* CSObjectMonitor.swift in Sources */, B5E1B5951CAA0C15007FD580 /* CSObjectMonitor.swift in Sources */,
B5ECDC2B1CA81CC700C7F112 /* CSDataStack+Transaction.swift in Sources */, B5ECDC2B1CA81CC700C7F112 /* CSDataStack+Transaction.swift in Sources */,
82BA18A11C4BBD1D00A0916E /* CoreStore.swift in Sources */, 82BA18A11C4BBD1D00A0916E /* CoreStore.swift in Sources */,
@@ -1915,6 +1923,7 @@
B549F6761E56A92800FBAB2D /* CoreDataNativeType.swift in Sources */, B549F6761E56A92800FBAB2D /* CoreDataNativeType.swift in Sources */,
B509C7F71E54511B0061C547 /* ImportableAttributeType.swift in Sources */, B509C7F71E54511B0061C547 /* ImportableAttributeType.swift in Sources */,
B5220E1F1D130810009BC71E /* CSListObserver.swift in Sources */, B5220E1F1D130810009BC71E /* CSListObserver.swift in Sources */,
B5A27F891E857C5300203C3E /* TransactionResult.swift in Sources */,
B52DD1941BE1F92500949AFE /* CoreStore.swift in Sources */, B52DD1941BE1F92500949AFE /* CoreStore.swift in Sources */,
B52DD1A61BE1F92F00949AFE /* BaseDataTransaction+Importing.swift in Sources */, B52DD1A61BE1F92F00949AFE /* BaseDataTransaction+Importing.swift in Sources */,
B5220E1D1D13080A009BC71E /* CSDataStack+Observing.swift in Sources */, B5220E1D1D13080A009BC71E /* CSDataStack+Observing.swift in Sources */,
@@ -2071,6 +2080,7 @@
B549F6751E56A92800FBAB2D /* CoreDataNativeType.swift in Sources */, B549F6751E56A92800FBAB2D /* CoreDataNativeType.swift in Sources */,
B509C7F61E54511B0061C547 /* ImportableAttributeType.swift in Sources */, B509C7F61E54511B0061C547 /* ImportableAttributeType.swift in Sources */,
B5E1B5961CAA0C15007FD580 /* CSObjectMonitor.swift in Sources */, B5E1B5961CAA0C15007FD580 /* CSObjectMonitor.swift in Sources */,
B5A27F881E857C5300203C3E /* TransactionResult.swift in Sources */,
B5ECDC2C1CA81CC700C7F112 /* CSDataStack+Transaction.swift in Sources */, B5ECDC2C1CA81CC700C7F112 /* CSDataStack+Transaction.swift in Sources */,
B56321911BD65216006C9394 /* BaseDataTransaction+Importing.swift in Sources */, B56321911BD65216006C9394 /* BaseDataTransaction+Importing.swift in Sources */,
B546F95A1C99B17400D5AC55 /* CSCoreStore+Setup.swift in Sources */, B546F95A1C99B17400D5AC55 /* CSCoreStore+Setup.swift in Sources */,

View File

@@ -42,7 +42,7 @@ final class TransactionTests: BaseTestCase {
do { do {
let createExpectation = self.expectation(description: "create") let createExpectation = self.expectation(description: "create")
let hasChanges: Bool = stack.perform( let hasChanges: Bool = try! stack.perform(
synchronous: { (transaction) in synchronous: { (transaction) in
defer { defer {
@@ -84,7 +84,7 @@ final class TransactionTests: BaseTestCase {
do { do {
let updateExpectation = self.expectation(description: "update") let updateExpectation = self.expectation(description: "update")
let hasChanges: Bool = stack.perform( let hasChanges: Bool = try! stack.perform(
synchronous: { (transaction) in synchronous: { (transaction) in
defer { defer {
@@ -92,9 +92,9 @@ final class TransactionTests: BaseTestCase {
updateExpectation.fulfill() updateExpectation.fulfill()
} }
guard let object = transaction.fetchOne(From<TestEntity1>()) else { guard let object = transaction.fetchOne(From<TestEntity1>()) else {
// TODO: convert fetch methods to throwing methods
XCTFail() XCTFail()
return // TODO: convert fetch methods to throwing methods try transaction.cancel()
} }
object.testString = "string1_edit" object.testString = "string1_edit"
object.testNumber = 200 object.testNumber = 200

View File

@@ -55,6 +55,7 @@ extension NSManagedObjectID: QueryableAttributeType {
@nonobjc @inline(__always) @nonobjc @inline(__always)
public class func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Self? { public class func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Self? {
@inline(__always)
func forceCast<T: NSManagedObjectID>(_ value: Any) -> T? { func forceCast<T: NSManagedObjectID>(_ value: Any) -> T? {
return value as? T return value as? T
@@ -84,6 +85,7 @@ extension NSNumber: QueryableAttributeType {
@nonobjc @inline(__always) @nonobjc @inline(__always)
public class func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Self? { public class func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Self? {
@inline(__always)
func forceCast<T: NSNumber>(_ value: Any) -> T? { func forceCast<T: NSNumber>(_ value: Any) -> T? {
return value as? T return value as? T
@@ -121,6 +123,7 @@ extension NSString: QueryableAttributeType {
@nonobjc @inline(__always) @nonobjc @inline(__always)
public class func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Self? { public class func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Self? {
@inline(__always)
func forceCast<T: NSString>(_ value: Any) -> T? { func forceCast<T: NSString>(_ value: Any) -> T? {
return value as? T return value as? T
@@ -147,6 +150,7 @@ extension NSDate: QueryableAttributeType {
@nonobjc @inline(__always) @nonobjc @inline(__always)
public class func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Self? { public class func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Self? {
@inline(__always)
func forceCast<T: NSDate>(_ value: Any) -> T? { func forceCast<T: NSDate>(_ value: Any) -> T? {
return value as? T return value as? T
@@ -173,6 +177,7 @@ extension NSData: QueryableAttributeType {
@nonobjc @inline(__always) @nonobjc @inline(__always)
public class func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Self? { public class func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Self? {
@inline(__always)
func forceCast<T: NSData>(_ value: Any) -> T? { func forceCast<T: NSData>(_ value: Any) -> T? {
return value as? T return value as? T
@@ -204,7 +209,7 @@ extension Bool: QueryableAttributeType {
case let decimal as NSDecimalNumber: case let decimal as NSDecimalNumber:
// iOS: NSDecimalNumber(string: "0.5").boolValue // true // iOS: NSDecimalNumber(string: "0.5").boolValue // true
// OSX: NSDecimalNumber(string: "0.5").boolValue // false // OSX: NSDecimalNumber(string: "0.5").boolValue // false
return NSNumber(value: decimal.doubleValue).boolValue return decimal != NSDecimalNumber.zero
default: default:
return value.boolValue return value.boolValue

View File

@@ -59,17 +59,13 @@ extension NSNumber: ImportableAttributeType {
@nonobjc @inline(__always) @nonobjc @inline(__always)
public class func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Self? { public class func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Self? {
func forceCast<T: NSNumber>(_ value: Any) -> T? { return self.cs_fromQueryableNativeType(value)
return value as? T
}
return forceCast(value)
} }
@nonobjc @inline(__always) @nonobjc @inline(__always)
public func cs_toImportableNativeType() -> ImportableNativeType { public func cs_toImportableNativeType() -> ImportableNativeType {
return self return self.cs_toQueryableNativeType()
} }
} }
@@ -89,17 +85,13 @@ extension NSString: ImportableAttributeType {
@nonobjc @inline(__always) @nonobjc @inline(__always)
public class func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Self? { public class func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Self? {
func forceCast<T: NSString>(_ value: Any) -> T? { return self.cs_fromQueryableNativeType(value)
return value as? T
}
return forceCast(value)
} }
@nonobjc @inline(__always) @nonobjc @inline(__always)
public func cs_toImportableNativeType() -> ImportableNativeType { public func cs_toImportableNativeType() -> ImportableNativeType {
return self return self.cs_toQueryableNativeType()
} }
} }
@@ -119,17 +111,13 @@ extension NSDate: ImportableAttributeType {
@nonobjc @inline(__always) @nonobjc @inline(__always)
public class func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Self? { public class func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Self? {
func forceCast<T: NSDate>(_ value: Any) -> T? { return self.cs_fromQueryableNativeType(value)
return value as? T
}
return forceCast(value)
} }
@nonobjc @inline(__always) @nonobjc @inline(__always)
public func cs_toImportableNativeType() -> ImportableNativeType { public func cs_toImportableNativeType() -> ImportableNativeType {
return self return self.cs_toQueryableNativeType()
} }
} }
@@ -149,17 +137,13 @@ extension NSData: ImportableAttributeType {
@nonobjc @inline(__always) @nonobjc @inline(__always)
public class func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Self? { public class func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Self? {
func forceCast<T: NSData>(_ value: Any) -> T? { return self.cs_fromQueryableNativeType(value)
return value as? T
}
return forceCast(value)
} }
@nonobjc @inline(__always) @nonobjc @inline(__always)
public func cs_toImportableNativeType() -> ImportableNativeType { public func cs_toImportableNativeType() -> ImportableNativeType {
return self return self.cs_toQueryableNativeType()
} }
} }
@@ -179,22 +163,13 @@ extension Bool: ImportableAttributeType {
@inline(__always) @inline(__always)
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Bool? { public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Bool? {
switch value { return self.cs_fromQueryableNativeType(value)
case let decimal as NSDecimalNumber:
// iOS: NSDecimalNumber(string: "0.5").boolValue // true
// OSX: NSDecimalNumber(string: "0.5").boolValue // false
return decimal != NSDecimalNumber.zero
default:
return value.boolValue
}
} }
@inline(__always) @inline(__always)
public func cs_toImportableNativeType() -> ImportableNativeType { public func cs_toImportableNativeType() -> ImportableNativeType {
return self as NSNumber return self.cs_toQueryableNativeType()
} }
} }
@@ -214,13 +189,13 @@ extension Int16: ImportableAttributeType {
@inline(__always) @inline(__always)
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Int16? { public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Int16? {
return value.int16Value return self.cs_fromQueryableNativeType(value)
} }
@inline(__always) @inline(__always)
public func cs_toImportableNativeType() -> ImportableNativeType { public func cs_toImportableNativeType() -> ImportableNativeType {
return self as NSNumber return self.cs_toQueryableNativeType()
} }
} }
@@ -240,13 +215,13 @@ extension Int32: ImportableAttributeType {
@inline(__always) @inline(__always)
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Int32? { public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Int32? {
return value.int32Value return self.cs_fromQueryableNativeType(value)
} }
@inline(__always) @inline(__always)
public func cs_toImportableNativeType() -> ImportableNativeType { public func cs_toImportableNativeType() -> ImportableNativeType {
return self as NSNumber return self.cs_toQueryableNativeType()
} }
} }
@@ -266,13 +241,13 @@ extension Int64: ImportableAttributeType {
@inline(__always) @inline(__always)
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Int64? { public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Int64? {
return value.int64Value return self.cs_fromQueryableNativeType(value)
} }
@inline(__always) @inline(__always)
public func cs_toImportableNativeType() -> ImportableNativeType { public func cs_toImportableNativeType() -> ImportableNativeType {
return self as NSNumber return self.cs_toQueryableNativeType()
} }
} }
@@ -292,13 +267,13 @@ extension Double: ImportableAttributeType {
@inline(__always) @inline(__always)
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Double? { public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Double? {
return value.doubleValue return self.cs_fromQueryableNativeType(value)
} }
@inline(__always) @inline(__always)
public func cs_toImportableNativeType() -> ImportableNativeType { public func cs_toImportableNativeType() -> ImportableNativeType {
return self as NSNumber return self.cs_toQueryableNativeType()
} }
} }
@@ -318,13 +293,13 @@ extension Float: ImportableAttributeType {
@inline(__always) @inline(__always)
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Float? { public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Float? {
return value.floatValue return self.cs_fromQueryableNativeType(value)
} }
@inline(__always) @inline(__always)
public func cs_toImportableNativeType() -> ImportableNativeType { public func cs_toImportableNativeType() -> ImportableNativeType {
return self as NSNumber return self.cs_toQueryableNativeType()
} }
} }
@@ -344,13 +319,13 @@ extension Date: ImportableAttributeType {
@inline(__always) @inline(__always)
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Date? { public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Date? {
return value as Date return self.cs_fromQueryableNativeType(value)
} }
@inline(__always) @inline(__always)
public func cs_toImportableNativeType() -> ImportableNativeType { public func cs_toImportableNativeType() -> ImportableNativeType {
return self as NSDate return self.cs_toQueryableNativeType()
} }
} }
@@ -370,13 +345,13 @@ extension String: ImportableAttributeType {
@inline(__always) @inline(__always)
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> String? { public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> String? {
return value as String return self.cs_fromQueryableNativeType(value)
} }
@inline(__always) @inline(__always)
public func cs_toImportableNativeType() -> ImportableNativeType { public func cs_toImportableNativeType() -> ImportableNativeType {
return self as NSString return self.cs_toQueryableNativeType()
} }
} }
@@ -396,12 +371,12 @@ extension Data: ImportableAttributeType {
@inline(__always) @inline(__always)
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Data? { public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Data? {
return value as Data return self.cs_fromQueryableNativeType(value)
} }
@inline(__always) @inline(__always)
public func cs_toImportableNativeType() -> ImportableNativeType { public func cs_toImportableNativeType() -> ImportableNativeType {
return self as NSData return self.cs_toQueryableNativeType()
} }
} }

View File

@@ -33,7 +33,7 @@ internal extension CoreStoreFetchRequest {
// MARK: Internal // MARK: Internal
@nonobjc @nonobjc @inline(__always)
internal func dynamicCast<U: NSFetchRequestResult>() -> NSFetchRequest<U> { internal func dynamicCast<U: NSFetchRequestResult>() -> NSFetchRequest<U> {
return unsafeBitCast(self, to: NSFetchRequest<U>.self) return unsafeBitCast(self, to: NSFetchRequest<U>.self)

View File

@@ -30,7 +30,7 @@ import Foundation
internal extension DispatchQueue { internal extension DispatchQueue {
@nonobjc @nonobjc @inline(__always)
internal static func serial(_ label: String, qos: DispatchQoS = .default) -> DispatchQueue { internal static func serial(_ label: String, qos: DispatchQoS = .default) -> DispatchQueue {
return DispatchQueue( return DispatchQueue(
@@ -42,7 +42,7 @@ internal extension DispatchQueue {
) )
} }
@nonobjc @nonobjc @inline(__always)
internal static func concurrent(_ label: String, qos: DispatchQoS = .default) -> DispatchQueue { internal static func concurrent(_ label: String, qos: DispatchQoS = .default) -> DispatchQueue {
return DispatchQueue( return DispatchQueue(
@@ -54,7 +54,7 @@ internal extension DispatchQueue {
) )
} }
@nonobjc @nonobjc @inline(__always)
internal func cs_isCurrentExecutionContext() -> Bool { internal func cs_isCurrentExecutionContext() -> Bool {
let specific = ObjectIdentifier(self) let specific = ObjectIdentifier(self)
@@ -63,25 +63,25 @@ internal extension DispatchQueue {
return DispatchQueue.getSpecific(key: Static.specificKey) == specific return DispatchQueue.getSpecific(key: Static.specificKey) == specific
} }
@nonobjc @nonobjc @inline(__always)
internal func cs_sync<T>(_ closure: () throws -> T) rethrows -> T { internal func cs_sync<T>(_ closure: () throws -> T) rethrows -> T {
return try self.sync { try autoreleasepool(invoking: closure) } return try self.sync { try autoreleasepool(invoking: closure) }
} }
@nonobjc @nonobjc @inline(__always)
internal func cs_async(_ closure: @escaping () -> Void) { internal func cs_async(_ closure: @escaping () -> Void) {
self.async { autoreleasepool(invoking: closure) } self.async { autoreleasepool(invoking: closure) }
} }
@nonobjc @nonobjc @inline(__always)
internal func cs_barrierSync<T>(_ closure: () throws -> T) rethrows -> T { internal func cs_barrierSync<T>(_ closure: () throws -> T) rethrows -> T {
return try self.sync(flags: .barrier) { try autoreleasepool(invoking: closure) } return try self.sync(flags: .barrier) { try autoreleasepool(invoking: closure) }
} }
@nonobjc @nonobjc @inline(__always)
internal func cs_barrierAsync(_ closure: @escaping () -> Void) { internal func cs_barrierAsync(_ closure: @escaping () -> Void) {
self.async(flags: .barrier) { autoreleasepool(invoking: closure) } self.async(flags: .barrier) { autoreleasepool(invoking: closure) }

View File

@@ -27,6 +27,7 @@ import Foundation
// MARK: Associated Objects // MARK: Associated Objects
@inline(__always)
internal func cs_getAssociatedObjectForKey<T: AnyObject>(_ key: UnsafeRawPointer, inObject object: Any) -> T? { internal func cs_getAssociatedObjectForKey<T: AnyObject>(_ key: UnsafeRawPointer, inObject object: Any) -> T? {
switch objc_getAssociatedObject(object, key) { switch objc_getAssociatedObject(object, key) {
@@ -42,16 +43,19 @@ internal func cs_getAssociatedObjectForKey<T: AnyObject>(_ key: UnsafeRawPointer
} }
} }
@inline(__always)
internal func cs_setAssociatedRetainedObject<T: AnyObject>(_ associatedObject: T?, forKey key: UnsafeRawPointer, inObject object: Any) { internal func cs_setAssociatedRetainedObject<T: AnyObject>(_ associatedObject: T?, forKey key: UnsafeRawPointer, inObject object: Any) {
objc_setAssociatedObject(object, key, associatedObject, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) objc_setAssociatedObject(object, key, associatedObject, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
} }
@inline(__always)
internal func cs_setAssociatedCopiedObject<T: AnyObject>(_ associatedObject: T?, forKey key: UnsafeRawPointer, inObject object: Any) { internal func cs_setAssociatedCopiedObject<T: AnyObject>(_ associatedObject: T?, forKey key: UnsafeRawPointer, inObject object: Any) {
objc_setAssociatedObject(object, key, associatedObject, .OBJC_ASSOCIATION_COPY_NONATOMIC) objc_setAssociatedObject(object, key, associatedObject, .OBJC_ASSOCIATION_COPY_NONATOMIC)
} }
@inline(__always)
internal func cs_setAssociatedWeakObject<T: AnyObject>(_ associatedObject: T?, forKey key: UnsafeRawPointer, inObject object: Any) { internal func cs_setAssociatedWeakObject<T: AnyObject>(_ associatedObject: T?, forKey key: UnsafeRawPointer, inObject object: Any) {
if let associatedObject = associatedObject { if let associatedObject = associatedObject {
@@ -67,26 +71,31 @@ internal func cs_setAssociatedWeakObject<T: AnyObject>(_ associatedObject: T?, f
// MARK: Printing Utilities // MARK: Printing Utilities
@inline(__always)
internal func cs_typeName<T>(_ value: T) -> String { internal func cs_typeName<T>(_ value: T) -> String {
return "'\(String(reflecting: type(of: value)))'" return "'\(String(reflecting: type(of: value)))'"
} }
@inline(__always)
internal func cs_typeName<T>(_ value: T.Type) -> String { internal func cs_typeName<T>(_ value: T.Type) -> String {
return "'\(value)'" return "'\(value)'"
} }
@inline(__always)
internal func cs_typeName(_ value: AnyClass) -> String { internal func cs_typeName(_ value: AnyClass) -> String {
return "'\(value)'" return "'\(value)'"
} }
@inline(__always)
internal func cs_typeName(_ name: String) -> String { internal func cs_typeName(_ name: String) -> String {
return "<\(name)>" return "<\(name)>"
} }
@inline(__always)
internal func cs_typeName(_ name: String?) -> String { internal func cs_typeName(_ name: String?) -> String {
return "<\(name ?? "unknown")>" return "<\(name ?? "unknown")>"

View File

@@ -34,6 +34,11 @@ import CoreData
*/ */
public final class AsynchronousDataTransaction: BaseDataTransaction { public final class AsynchronousDataTransaction: BaseDataTransaction {
public func cancel() throws -> Never {
throw CoreStoreError.userCancelled
}
/** /**
Saves the transaction changes. This method should not be used after the `commit()` method was already called once. Saves the transaction changes. This method should not be used after the `commit()` method was already called once.

View File

@@ -36,12 +36,6 @@ public /*abstract*/ class BaseDataTransaction {
// MARK: Object management // MARK: Object management
public func cancel() throws -> Never {
throw CoreStoreError.userCancelled
}
/** /**
Indicates if the transaction has pending changes Indicates if the transaction has pending changes
*/ */

View File

@@ -31,6 +31,16 @@ import CoreData
public extension DataStack { public extension DataStack {
public func perform<T>(asynchronous task: @escaping (_ transaction: AsynchronousDataTransaction) throws -> T, completion: @escaping (TransactionResult<T>) -> Void) {
self.perform(
asynchronous: task,
success: { completion(TransactionResult(userInfo: $0)) },
failure: { completion(TransactionResult(error: $0)) }
)
}
public func perform<T>(asynchronous task: @escaping (_ transaction: AsynchronousDataTransaction) throws -> T, success: @escaping (T) -> Void, failure: @escaping (CoreStoreError) -> Void) { public func perform<T>(asynchronous task: @escaping (_ transaction: AsynchronousDataTransaction) throws -> T, success: @escaping (T) -> Void, failure: @escaping (CoreStoreError) -> Void) {
let transaction = AsynchronousDataTransaction( let transaction = AsynchronousDataTransaction(
@@ -40,28 +50,28 @@ public extension DataStack {
) )
transaction.transactionQueue.cs_async { transaction.transactionQueue.cs_async {
let userInfo: T
do { do {
let extraInfo = try task(transaction) userInfo = try task(transaction)
transaction.commit { (result) in
switch result {
case .success:
success(extraInfo)
case .failure(let error):
failure(error)
}
}
} }
catch let error as CoreStoreError { catch let error as CoreStoreError {
DispatchQueue.main.async { failure(error) } DispatchQueue.main.async { failure(error) }
return
} }
catch let error { catch let error {
DispatchQueue.main.async { failure(.userError(error: error)) } DispatchQueue.main.async { failure(.userError(error: error)) }
return
}
transaction.commit { (result) in
switch result {
case .success: success(userInfo)
case .failure(let error): failure(error)
}
} }
} }
} }
@@ -75,10 +85,10 @@ public extension DataStack {
) )
return try transaction.transactionQueue.cs_sync { return try transaction.transactionQueue.cs_sync {
let extraInfo: T let userInfo: T
do { do {
extraInfo = try task(transaction) userInfo = try task(transaction)
} }
catch let error as CoreStoreError { catch let error as CoreStoreError {
@@ -88,17 +98,13 @@ public extension DataStack {
throw CoreStoreError.userError(error: error) throw CoreStoreError.userError(error: error)
} }
let result = waitForObserverNotifications let result = waitForObserverNotifications
? transaction.commitAndWait() ? transaction.commitAndWait()
: transaction.commit() : transaction.commit()
switch result { switch result {
case .success: case .success: return userInfo
return extraInfo case .failure(let error): throw error
case .failure(let error):
throw error
} }
} }
} }

View File

@@ -34,6 +34,11 @@ import CoreData
*/ */
public final class SynchronousDataTransaction: BaseDataTransaction { public final class SynchronousDataTransaction: BaseDataTransaction {
public func cancel() throws -> Never {
throw CoreStoreError.userCancelled
}
/** /**
Saves the transaction changes and waits for completion synchronously. This method should not be used after the `commit()` or `commitAndWait()` method was already called once. Saves the transaction changes and waits for completion synchronously. This method should not be used after the `commit()` or `commitAndWait()` method was already called once.
- Important: Unlike `SynchronousDataTransaction.commit()`, this method waits for all observers to be notified of the changes before returning. This results in more predictable data update order, but may risk triggering deadlocks. - Important: Unlike `SynchronousDataTransaction.commit()`, this method waits for all observers to be notified of the changes before returning. This results in more predictable data update order, but may risk triggering deadlocks.

View File

@@ -0,0 +1,58 @@
//
// TransactionResult.swift
// CoreStore
//
// Copyright © 2017 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: - TransactionResult
public enum TransactionResult<T> {
case success(T)
case failure(CoreStoreError)
public var boolValue: Bool {
switch self {
case .success: return true
case .failure: return false
}
}
// MARK: Internal
internal init(userInfo: T) {
self = .success(userInfo)
}
internal init(error: CoreStoreError) {
self = .failure(error)
}
}