mirror of
https://github.com/JohnEstropia/CoreStore.git
synced 2026-03-26 11:21:18 +01:00
WIP
This commit is contained in:
@@ -398,6 +398,10 @@
|
||||
B59FA0B11CCBACA7007C9BCA /* 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 */; };
|
||||
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 */; };
|
||||
B5A5F2681CAEC50F004AB9AF /* 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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
@@ -1160,6 +1165,7 @@
|
||||
B5E84EEE1AFF846E0064E85B /* CoreStore+Transaction.swift */,
|
||||
B50392F81C478FF3009900CA /* NSManagedObject+Transaction.swift */,
|
||||
B5E84EF21AFF846E0064E85B /* SaveResult.swift */,
|
||||
B5A27F851E857C5300203C3E /* TransactionResult.swift */,
|
||||
);
|
||||
path = Transactions;
|
||||
sourceTree = "<group>";
|
||||
@@ -1603,6 +1609,7 @@
|
||||
B549F6731E56A92800FBAB2D /* CoreDataNativeType.swift in Sources */,
|
||||
B509C7F41E54511B0061C547 /* ImportableAttributeType.swift in Sources */,
|
||||
B5E84F0E1AFF847B0064E85B /* Tweak.swift in Sources */,
|
||||
B5A27F861E857C5300203C3E /* TransactionResult.swift in Sources */,
|
||||
B5E1B5931CAA0C15007FD580 /* CSObjectMonitor.swift in Sources */,
|
||||
B5ECDC291CA81CC700C7F112 /* CSDataStack+Transaction.swift in Sources */,
|
||||
B5E84F121AFF847B0064E85B /* OrderBy.swift in Sources */,
|
||||
@@ -1759,6 +1766,7 @@
|
||||
B549F6741E56A92800FBAB2D /* CoreDataNativeType.swift in Sources */,
|
||||
B509C7F51E54511B0061C547 /* ImportableAttributeType.swift in Sources */,
|
||||
82BA18B31C4BBD3900A0916E /* ImportableUniqueObject.swift in Sources */,
|
||||
B5A27F871E857C5300203C3E /* TransactionResult.swift in Sources */,
|
||||
B5E1B5951CAA0C15007FD580 /* CSObjectMonitor.swift in Sources */,
|
||||
B5ECDC2B1CA81CC700C7F112 /* CSDataStack+Transaction.swift in Sources */,
|
||||
82BA18A11C4BBD1D00A0916E /* CoreStore.swift in Sources */,
|
||||
@@ -1915,6 +1923,7 @@
|
||||
B549F6761E56A92800FBAB2D /* CoreDataNativeType.swift in Sources */,
|
||||
B509C7F71E54511B0061C547 /* ImportableAttributeType.swift in Sources */,
|
||||
B5220E1F1D130810009BC71E /* CSListObserver.swift in Sources */,
|
||||
B5A27F891E857C5300203C3E /* TransactionResult.swift in Sources */,
|
||||
B52DD1941BE1F92500949AFE /* CoreStore.swift in Sources */,
|
||||
B52DD1A61BE1F92F00949AFE /* BaseDataTransaction+Importing.swift in Sources */,
|
||||
B5220E1D1D13080A009BC71E /* CSDataStack+Observing.swift in Sources */,
|
||||
@@ -2071,6 +2080,7 @@
|
||||
B549F6751E56A92800FBAB2D /* CoreDataNativeType.swift in Sources */,
|
||||
B509C7F61E54511B0061C547 /* ImportableAttributeType.swift in Sources */,
|
||||
B5E1B5961CAA0C15007FD580 /* CSObjectMonitor.swift in Sources */,
|
||||
B5A27F881E857C5300203C3E /* TransactionResult.swift in Sources */,
|
||||
B5ECDC2C1CA81CC700C7F112 /* CSDataStack+Transaction.swift in Sources */,
|
||||
B56321911BD65216006C9394 /* BaseDataTransaction+Importing.swift in Sources */,
|
||||
B546F95A1C99B17400D5AC55 /* CSCoreStore+Setup.swift in Sources */,
|
||||
|
||||
@@ -42,7 +42,7 @@ final class TransactionTests: BaseTestCase {
|
||||
do {
|
||||
|
||||
let createExpectation = self.expectation(description: "create")
|
||||
let hasChanges: Bool = stack.perform(
|
||||
let hasChanges: Bool = try! stack.perform(
|
||||
synchronous: { (transaction) in
|
||||
|
||||
defer {
|
||||
@@ -84,7 +84,7 @@ final class TransactionTests: BaseTestCase {
|
||||
do {
|
||||
|
||||
let updateExpectation = self.expectation(description: "update")
|
||||
let hasChanges: Bool = stack.perform(
|
||||
let hasChanges: Bool = try! stack.perform(
|
||||
synchronous: { (transaction) in
|
||||
|
||||
defer {
|
||||
@@ -92,9 +92,9 @@ final class TransactionTests: BaseTestCase {
|
||||
updateExpectation.fulfill()
|
||||
}
|
||||
guard let object = transaction.fetchOne(From<TestEntity1>()) else {
|
||||
|
||||
XCTFail()
|
||||
return // TODO: convert fetch methods to throwing methods
|
||||
// TODO: convert fetch methods to throwing methods
|
||||
XCTFail()
|
||||
try transaction.cancel()
|
||||
}
|
||||
object.testString = "string1_edit"
|
||||
object.testNumber = 200
|
||||
|
||||
@@ -55,6 +55,7 @@ extension NSManagedObjectID: QueryableAttributeType {
|
||||
@nonobjc @inline(__always)
|
||||
public class func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Self? {
|
||||
|
||||
@inline(__always)
|
||||
func forceCast<T: NSManagedObjectID>(_ value: Any) -> T? {
|
||||
|
||||
return value as? T
|
||||
@@ -84,6 +85,7 @@ extension NSNumber: QueryableAttributeType {
|
||||
@nonobjc @inline(__always)
|
||||
public class func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Self? {
|
||||
|
||||
@inline(__always)
|
||||
func forceCast<T: NSNumber>(_ value: Any) -> T? {
|
||||
|
||||
return value as? T
|
||||
@@ -121,6 +123,7 @@ extension NSString: QueryableAttributeType {
|
||||
@nonobjc @inline(__always)
|
||||
public class func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Self? {
|
||||
|
||||
@inline(__always)
|
||||
func forceCast<T: NSString>(_ value: Any) -> T? {
|
||||
|
||||
return value as? T
|
||||
@@ -147,6 +150,7 @@ extension NSDate: QueryableAttributeType {
|
||||
@nonobjc @inline(__always)
|
||||
public class func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Self? {
|
||||
|
||||
@inline(__always)
|
||||
func forceCast<T: NSDate>(_ value: Any) -> T? {
|
||||
|
||||
return value as? T
|
||||
@@ -173,6 +177,7 @@ extension NSData: QueryableAttributeType {
|
||||
@nonobjc @inline(__always)
|
||||
public class func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Self? {
|
||||
|
||||
@inline(__always)
|
||||
func forceCast<T: NSData>(_ value: Any) -> T? {
|
||||
|
||||
return value as? T
|
||||
@@ -204,7 +209,7 @@ extension Bool: QueryableAttributeType {
|
||||
case let decimal as NSDecimalNumber:
|
||||
// iOS: NSDecimalNumber(string: "0.5").boolValue // true
|
||||
// OSX: NSDecimalNumber(string: "0.5").boolValue // false
|
||||
return NSNumber(value: decimal.doubleValue).boolValue
|
||||
return decimal != NSDecimalNumber.zero
|
||||
|
||||
default:
|
||||
return value.boolValue
|
||||
|
||||
@@ -59,17 +59,13 @@ extension NSNumber: ImportableAttributeType {
|
||||
@nonobjc @inline(__always)
|
||||
public class func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Self? {
|
||||
|
||||
func forceCast<T: NSNumber>(_ value: Any) -> T? {
|
||||
|
||||
return value as? T
|
||||
}
|
||||
return forceCast(value)
|
||||
return self.cs_fromQueryableNativeType(value)
|
||||
}
|
||||
|
||||
@nonobjc @inline(__always)
|
||||
public func cs_toImportableNativeType() -> ImportableNativeType {
|
||||
|
||||
return self
|
||||
return self.cs_toQueryableNativeType()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,17 +85,13 @@ extension NSString: ImportableAttributeType {
|
||||
@nonobjc @inline(__always)
|
||||
public class func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Self? {
|
||||
|
||||
func forceCast<T: NSString>(_ value: Any) -> T? {
|
||||
|
||||
return value as? T
|
||||
}
|
||||
return forceCast(value)
|
||||
return self.cs_fromQueryableNativeType(value)
|
||||
}
|
||||
|
||||
@nonobjc @inline(__always)
|
||||
public func cs_toImportableNativeType() -> ImportableNativeType {
|
||||
|
||||
return self
|
||||
return self.cs_toQueryableNativeType()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,17 +111,13 @@ extension NSDate: ImportableAttributeType {
|
||||
@nonobjc @inline(__always)
|
||||
public class func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Self? {
|
||||
|
||||
func forceCast<T: NSDate>(_ value: Any) -> T? {
|
||||
|
||||
return value as? T
|
||||
}
|
||||
return forceCast(value)
|
||||
return self.cs_fromQueryableNativeType(value)
|
||||
}
|
||||
|
||||
@nonobjc @inline(__always)
|
||||
public func cs_toImportableNativeType() -> ImportableNativeType {
|
||||
|
||||
return self
|
||||
return self.cs_toQueryableNativeType()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,17 +137,13 @@ extension NSData: ImportableAttributeType {
|
||||
@nonobjc @inline(__always)
|
||||
public class func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Self? {
|
||||
|
||||
func forceCast<T: NSData>(_ value: Any) -> T? {
|
||||
|
||||
return value as? T
|
||||
}
|
||||
return forceCast(value)
|
||||
return self.cs_fromQueryableNativeType(value)
|
||||
}
|
||||
|
||||
@nonobjc @inline(__always)
|
||||
public func cs_toImportableNativeType() -> ImportableNativeType {
|
||||
|
||||
return self
|
||||
return self.cs_toQueryableNativeType()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,22 +163,13 @@ extension Bool: ImportableAttributeType {
|
||||
@inline(__always)
|
||||
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Bool? {
|
||||
|
||||
switch 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
|
||||
}
|
||||
return self.cs_fromQueryableNativeType(value)
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public func cs_toImportableNativeType() -> ImportableNativeType {
|
||||
|
||||
return self as NSNumber
|
||||
return self.cs_toQueryableNativeType()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,13 +189,13 @@ extension Int16: ImportableAttributeType {
|
||||
@inline(__always)
|
||||
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Int16? {
|
||||
|
||||
return value.int16Value
|
||||
return self.cs_fromQueryableNativeType(value)
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public func cs_toImportableNativeType() -> ImportableNativeType {
|
||||
|
||||
return self as NSNumber
|
||||
return self.cs_toQueryableNativeType()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,13 +215,13 @@ extension Int32: ImportableAttributeType {
|
||||
@inline(__always)
|
||||
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Int32? {
|
||||
|
||||
return value.int32Value
|
||||
return self.cs_fromQueryableNativeType(value)
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public func cs_toImportableNativeType() -> ImportableNativeType {
|
||||
|
||||
return self as NSNumber
|
||||
return self.cs_toQueryableNativeType()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -266,13 +241,13 @@ extension Int64: ImportableAttributeType {
|
||||
@inline(__always)
|
||||
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Int64? {
|
||||
|
||||
return value.int64Value
|
||||
return self.cs_fromQueryableNativeType(value)
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public func cs_toImportableNativeType() -> ImportableNativeType {
|
||||
|
||||
return self as NSNumber
|
||||
return self.cs_toQueryableNativeType()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -292,13 +267,13 @@ extension Double: ImportableAttributeType {
|
||||
@inline(__always)
|
||||
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Double? {
|
||||
|
||||
return value.doubleValue
|
||||
return self.cs_fromQueryableNativeType(value)
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public func cs_toImportableNativeType() -> ImportableNativeType {
|
||||
|
||||
return self as NSNumber
|
||||
return self.cs_toQueryableNativeType()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -318,13 +293,13 @@ extension Float: ImportableAttributeType {
|
||||
@inline(__always)
|
||||
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Float? {
|
||||
|
||||
return value.floatValue
|
||||
return self.cs_fromQueryableNativeType(value)
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public func cs_toImportableNativeType() -> ImportableNativeType {
|
||||
|
||||
return self as NSNumber
|
||||
return self.cs_toQueryableNativeType()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -344,13 +319,13 @@ extension Date: ImportableAttributeType {
|
||||
@inline(__always)
|
||||
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Date? {
|
||||
|
||||
return value as Date
|
||||
return self.cs_fromQueryableNativeType(value)
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public func cs_toImportableNativeType() -> ImportableNativeType {
|
||||
|
||||
return self as NSDate
|
||||
return self.cs_toQueryableNativeType()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -370,13 +345,13 @@ extension String: ImportableAttributeType {
|
||||
@inline(__always)
|
||||
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> String? {
|
||||
|
||||
return value as String
|
||||
return self.cs_fromQueryableNativeType(value)
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public func cs_toImportableNativeType() -> ImportableNativeType {
|
||||
|
||||
return self as NSString
|
||||
return self.cs_toQueryableNativeType()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -396,12 +371,12 @@ extension Data: ImportableAttributeType {
|
||||
@inline(__always)
|
||||
public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Data? {
|
||||
|
||||
return value as Data
|
||||
return self.cs_fromQueryableNativeType(value)
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
public func cs_toImportableNativeType() -> ImportableNativeType {
|
||||
|
||||
return self as NSData
|
||||
return self.cs_toQueryableNativeType()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ internal extension CoreStoreFetchRequest {
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
@nonobjc
|
||||
@nonobjc @inline(__always)
|
||||
internal func dynamicCast<U: NSFetchRequestResult>() -> NSFetchRequest<U> {
|
||||
|
||||
return unsafeBitCast(self, to: NSFetchRequest<U>.self)
|
||||
|
||||
@@ -30,7 +30,7 @@ import Foundation
|
||||
|
||||
internal extension DispatchQueue {
|
||||
|
||||
@nonobjc
|
||||
@nonobjc @inline(__always)
|
||||
internal static func serial(_ label: String, qos: DispatchQoS = .default) -> DispatchQueue {
|
||||
|
||||
return DispatchQueue(
|
||||
@@ -42,7 +42,7 @@ internal extension DispatchQueue {
|
||||
)
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
@nonobjc @inline(__always)
|
||||
internal static func concurrent(_ label: String, qos: DispatchQoS = .default) -> DispatchQueue {
|
||||
|
||||
return DispatchQueue(
|
||||
@@ -54,7 +54,7 @@ internal extension DispatchQueue {
|
||||
)
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
@nonobjc @inline(__always)
|
||||
internal func cs_isCurrentExecutionContext() -> Bool {
|
||||
|
||||
let specific = ObjectIdentifier(self)
|
||||
@@ -63,25 +63,25 @@ internal extension DispatchQueue {
|
||||
return DispatchQueue.getSpecific(key: Static.specificKey) == specific
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
@nonobjc @inline(__always)
|
||||
internal func cs_sync<T>(_ closure: () throws -> T) rethrows -> T {
|
||||
|
||||
return try self.sync { try autoreleasepool(invoking: closure) }
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
@nonobjc @inline(__always)
|
||||
internal func cs_async(_ closure: @escaping () -> Void) {
|
||||
|
||||
self.async { autoreleasepool(invoking: closure) }
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
@nonobjc @inline(__always)
|
||||
internal func cs_barrierSync<T>(_ closure: () throws -> T) rethrows -> T {
|
||||
|
||||
return try self.sync(flags: .barrier) { try autoreleasepool(invoking: closure) }
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
@nonobjc @inline(__always)
|
||||
internal func cs_barrierAsync(_ closure: @escaping () -> Void) {
|
||||
|
||||
self.async(flags: .barrier) { autoreleasepool(invoking: closure) }
|
||||
|
||||
@@ -27,6 +27,7 @@ import Foundation
|
||||
|
||||
// MARK: Associated Objects
|
||||
|
||||
@inline(__always)
|
||||
internal func cs_getAssociatedObjectForKey<T: AnyObject>(_ key: UnsafeRawPointer, inObject object: Any) -> T? {
|
||||
|
||||
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) {
|
||||
|
||||
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) {
|
||||
|
||||
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) {
|
||||
|
||||
if let associatedObject = associatedObject {
|
||||
@@ -67,26 +71,31 @@ internal func cs_setAssociatedWeakObject<T: AnyObject>(_ associatedObject: T?, f
|
||||
|
||||
// MARK: Printing Utilities
|
||||
|
||||
@inline(__always)
|
||||
internal func cs_typeName<T>(_ value: T) -> String {
|
||||
|
||||
return "'\(String(reflecting: type(of: value)))'"
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
internal func cs_typeName<T>(_ value: T.Type) -> String {
|
||||
|
||||
return "'\(value)'"
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
internal func cs_typeName(_ value: AnyClass) -> String {
|
||||
|
||||
return "'\(value)'"
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
internal func cs_typeName(_ name: String) -> String {
|
||||
|
||||
return "<\(name)>"
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
internal func cs_typeName(_ name: String?) -> String {
|
||||
|
||||
return "<\(name ?? "unknown")>"
|
||||
|
||||
@@ -34,6 +34,11 @@ import CoreData
|
||||
*/
|
||||
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.
|
||||
|
||||
|
||||
@@ -36,12 +36,6 @@ public /*abstract*/ class BaseDataTransaction {
|
||||
|
||||
// MARK: Object management
|
||||
|
||||
|
||||
public func cancel() throws -> Never {
|
||||
|
||||
throw CoreStoreError.userCancelled
|
||||
}
|
||||
|
||||
/**
|
||||
Indicates if the transaction has pending changes
|
||||
*/
|
||||
|
||||
@@ -31,6 +31,16 @@ import CoreData
|
||||
|
||||
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) {
|
||||
|
||||
let transaction = AsynchronousDataTransaction(
|
||||
@@ -40,28 +50,28 @@ public extension DataStack {
|
||||
)
|
||||
transaction.transactionQueue.cs_async {
|
||||
|
||||
let userInfo: T
|
||||
do {
|
||||
|
||||
let extraInfo = try task(transaction)
|
||||
transaction.commit { (result) in
|
||||
|
||||
switch result {
|
||||
|
||||
case .success:
|
||||
success(extraInfo)
|
||||
|
||||
case .failure(let error):
|
||||
failure(error)
|
||||
}
|
||||
}
|
||||
userInfo = try task(transaction)
|
||||
}
|
||||
catch let error as CoreStoreError {
|
||||
|
||||
DispatchQueue.main.async { failure(error) }
|
||||
return
|
||||
}
|
||||
catch let 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 {
|
||||
|
||||
let extraInfo: T
|
||||
let userInfo: T
|
||||
do {
|
||||
|
||||
extraInfo = try task(transaction)
|
||||
userInfo = try task(transaction)
|
||||
}
|
||||
catch let error as CoreStoreError {
|
||||
|
||||
@@ -88,17 +98,13 @@ public extension DataStack {
|
||||
|
||||
throw CoreStoreError.userError(error: error)
|
||||
}
|
||||
|
||||
let result = waitForObserverNotifications
|
||||
? transaction.commitAndWait()
|
||||
: transaction.commit()
|
||||
switch result {
|
||||
|
||||
case .success:
|
||||
return extraInfo
|
||||
|
||||
case .failure(let error):
|
||||
throw error
|
||||
case .success: return userInfo
|
||||
case .failure(let error): throw error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,11 @@ import CoreData
|
||||
*/
|
||||
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.
|
||||
- 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.
|
||||
|
||||
58
Sources/Transactions/TransactionResult.swift
Normal file
58
Sources/Transactions/TransactionResult.swift
Normal 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)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user