diff --git a/CoreStore.podspec b/CoreStore.podspec index e9bdd8d..646ea17 100644 --- a/CoreStore.podspec +++ b/CoreStore.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "CoreStore" - s.version = "7.3.0" + s.version = "7.3.1" s.swift_version = "5.3" s.license = "MIT" s.homepage = "https://github.com/JohnEstropia/CoreStore" diff --git a/CoreStore.xcodeproj/project.pbxproj b/CoreStore.xcodeproj/project.pbxproj index 91f0791..3906fa5 100644 --- a/CoreStore.xcodeproj/project.pbxproj +++ b/CoreStore.xcodeproj/project.pbxproj @@ -3415,7 +3415,7 @@ DYLIB_INSTALL_NAME_BASE = "@rpath"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MARKETING_VERSION = 7.3.0; + MARKETING_VERSION = 7.3.1; OTHER_LDFLAGS = ( "-weak_framework", Combine, @@ -3438,7 +3438,7 @@ DYLIB_INSTALL_NAME_BASE = "@rpath"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MARKETING_VERSION = 7.3.0; + MARKETING_VERSION = 7.3.1; OTHER_LDFLAGS = ( "-weak_framework", Combine, @@ -3498,7 +3498,7 @@ GCC_NO_COMMON_BLOCKS = YES; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MARKETING_VERSION = 7.3.0; + MARKETING_VERSION = 7.3.1; OTHER_LDFLAGS = ( "-weak_framework", Combine, @@ -3524,7 +3524,7 @@ GCC_NO_COMMON_BLOCKS = YES; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MARKETING_VERSION = 7.3.0; + MARKETING_VERSION = 7.3.1; OTHER_LDFLAGS = ( "-weak_framework", Combine, @@ -3589,7 +3589,7 @@ GCC_NO_COMMON_BLOCKS = YES; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; - MARKETING_VERSION = 7.3.0; + MARKETING_VERSION = 7.3.1; OTHER_LDFLAGS = ( "-weak_framework", Combine, @@ -3618,7 +3618,7 @@ GCC_NO_COMMON_BLOCKS = YES; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; - MARKETING_VERSION = 7.3.0; + MARKETING_VERSION = 7.3.1; OTHER_LDFLAGS = ( "-weak_framework", Combine, @@ -3684,7 +3684,7 @@ GCC_NO_COMMON_BLOCKS = YES; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MARKETING_VERSION = 7.3.0; + MARKETING_VERSION = 7.3.1; OTHER_LDFLAGS = ( "-weak_framework", Combine, @@ -3712,7 +3712,7 @@ GCC_NO_COMMON_BLOCKS = YES; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MARKETING_VERSION = 7.3.0; + MARKETING_VERSION = 7.3.1; OTHER_LDFLAGS = ( "-weak_framework", Combine, diff --git a/CoreStore.xcworkspace/contents.xcworkspacedata b/CoreStore.xcworkspace/contents.xcworkspacedata index a57c826..23b89e6 100644 --- a/CoreStore.xcworkspace/contents.xcworkspacedata +++ b/CoreStore.xcworkspace/contents.xcworkspacedata @@ -8,6 +8,6 @@ location = "group:CoreStore.xcodeproj"> + location = "group:LegacyDemo/LegacyDemo.xcodeproj"> diff --git a/README.md b/README.md index ec5ade7..750be08 100644 --- a/README.md +++ b/README.md @@ -2095,7 +2095,7 @@ This installs CoreStore as a framework. Declare `import CoreStore` in your swift #### Install with Swift Package Manager: ```swift dependencies: [ - .package(url: "https://github.com/JohnEstropia/CoreStore.git", from: "7.3.0")) + .package(url: "https://github.com/JohnEstropia/CoreStore.git", from: "7.3.1")) ] ``` Declare `import CoreStore` in your swift file to use the library. diff --git a/Sources/DynamicObject.swift b/Sources/DynamicObject.swift index 48dd3e7..42a446a 100644 --- a/Sources/DynamicObject.swift +++ b/Sources/DynamicObject.swift @@ -217,7 +217,8 @@ extension CoreStoreObject { guard let object = context.fetchExisting(id) as CoreStoreObject?, - let rawObject = object.rawObject + let rawObject = object.rawObject, + !rawObject.isDeleted else { return nil diff --git a/Sources/Internals.DiffableDataSourceSnapshot.swift b/Sources/Internals.DiffableDataSourceSnapshot.swift index e4388c6..c46bc38 100644 --- a/Sources/Internals.DiffableDataSourceSnapshot.swift +++ b/Sources/Internals.DiffableDataSourceSnapshot.swift @@ -78,7 +78,7 @@ extension Internals { var numberOfItems: Int { - return self.structure.allItemIDs.count + return self.structure.allItemsCount } var numberOfSections: Int { @@ -106,6 +106,59 @@ extension Internals { return self.itemIdentifiers(inSection: identifier).count } + func itemIdentifier(atAllItemsIndex index: Int) -> NSManagedObjectID? { + + guard index >= 0 else { + + return nil + } + var remainingIndex = index + for section in self.structure.sections { + + let elements = section.elements + let sectionCount = elements.count + if remainingIndex < sectionCount { + + return elements[remainingIndex].differenceIdentifier + } + + remainingIndex -= sectionCount + } + return nil + } + + func itemIdentifiers(atAllItemsBounds bounds: Range) -> [NSManagedObjectID] { + + var remainingIndex = bounds.lowerBound + var itemIdentifiers: [NSManagedObjectID] = [] + for section in self.structure.sections { + + let elements = section.elements + let sectionCount = elements.count + if remainingIndex < sectionCount { + + itemIdentifiers.append( + contentsOf: elements[remainingIndex..= bounds.count { + + return itemIdentifiers + } + + remainingIndex -= sectionCount + } + return itemIdentifiers + } + func itemIdentifiers(inSection identifier: String) -> [NSManagedObjectID] { return self.structure.items(in: identifier) @@ -332,6 +385,14 @@ extension Internals { return self.sections.map({ $0.differenceIdentifier }) } + var allItemsCount: Int { + + return self.sections.reduce(into: 0) { (result, section) in + + result += section.elements.count + } + } + var allItemIDs: [NSManagedObjectID] { return self.sections.lazy.flatMap({ $0.elements }).map({ $0.differenceIdentifier }) diff --git a/Sources/KeyPath+Querying.swift b/Sources/KeyPath+Querying.swift index 1fd8ed2..ceaf7ae 100644 --- a/Sources/KeyPath+Querying.swift +++ b/Sources/KeyPath+Querying.swift @@ -267,6 +267,17 @@ public func == (_ keyPath: KeyPath return Where(keyPath._kvcKeyPathString!, isEqualTo: objectID) } +/** + Creates a `Where` clause by comparing if a property is equal to a value + ``` + let dog = dataStack.fetchOne(From().where(\.master == john)) + ``` + */ +public func == (_ keyPath: KeyPath, _ object: O) -> Where where O.ObjectType: NSManagedObject { + + return Where(keyPath._kvcKeyPathString!, isEqualTo: object.cs_id()) +} + /** Creates a `Where` clause by comparing if a property is not equal to a value ``` @@ -278,6 +289,17 @@ public func != (_ keyPath: KeyPath return !Where(keyPath._kvcKeyPathString!, isEqualTo: objectID) } +/** + Creates a `Where` clause by comparing if a property is not equal to a value + ``` + let dog = dataStack.fetchOne(From().where(\.master != john)) + ``` + */ +public func != (_ keyPath: KeyPath, _ object: O) -> Where where O.ObjectType: NSManagedObject { + + return !Where(keyPath._kvcKeyPathString!, isEqualTo: object.cs_id()) +} + /** Creates a `Where` clause by checking if a sequence contains a value of a property ``` @@ -303,6 +325,17 @@ public func == (_ keyPath: KeyPath(keyPath._kvcKeyPathString!, isEqualTo: object) } +/** + Creates a `Where` clause by comparing if a property is equal to a value + ``` + let dog = dataStack.fetchOne(From().where(\.master == john)) + ``` + */ +public func == (_ keyPath: KeyPath>, _ object: O?) -> Where where O.ObjectType: NSManagedObject { + + return Where(keyPath._kvcKeyPathString!, isEqualTo: object?.cs_toRaw()) +} + /** Creates a `Where` clause by comparing if a property is not equal to a value ``` @@ -314,6 +347,17 @@ public func != (_ keyPath: KeyPath(keyPath._kvcKeyPathString!, isEqualTo: object) } +/** + Creates a `Where` clause by comparing if a property is not equal to a value + ``` + let dog = dataStack.fetchOne(From().where(\.master != john)) + ``` + */ +public func != (_ keyPath: KeyPath>, _ object: O?) -> Where where O.ObjectType: NSManagedObject { + + return !Where(keyPath._kvcKeyPathString!, isEqualTo: object?.cs_toRaw()) +} + /** Creates a `Where` clause by checking if a sequence contains a value of a property ``` @@ -690,6 +734,17 @@ public func == (_ keyPath: KeyPath(O.meta[keyPath: keyPath].keyPath, isEqualTo: object) } +/** + Creates a `Where` clause by comparing if a property is equal to a value + ``` + let dog = dataStack.fetchOne(From().where(\.master == john)) + ``` + */ +public func == (_ keyPath: KeyPath.Relationship>, _ object: R?) -> Where where D.DestinationObjectType == R.ObjectType { + + return Where(O.meta[keyPath: keyPath].keyPath, isEqualTo: object?.objectID()) +} + /** Creates a `Where` clause by comparing if a property is equal to a value ``` @@ -723,6 +778,17 @@ public func != (_ keyPath: KeyPath(O.meta[keyPath: keyPath].keyPath, isEqualTo: object) } +/** + Creates a `Where` clause by comparing if a property is not equal to a value + ``` + let dog = dataStack.fetchOne(From().where(\.master != john)) + ``` + */ +public func != (_ keyPath: KeyPath.Relationship>, _ object: R?) -> Where where D.DestinationObjectType == R.ObjectType { + + return !Where(O.meta[keyPath: keyPath].keyPath, isEqualTo: object?.objectID()) +} + /** Creates a `Where` clause by comparing if a property is not equal to a value ``` diff --git a/Sources/ListSnapshot.swift b/Sources/ListSnapshot.swift index 182fe63..4510f69 100644 --- a/Sources/ListSnapshot.swift +++ b/Sources/ListSnapshot.swift @@ -71,7 +71,7 @@ public struct ListSnapshot: RandomAccessCollection, Hashable { public subscript(index: Index) -> ObjectPublisher { let context = self.context! - let itemID = self.diffableSnapshot.itemIdentifiers[index] + let itemID = self.diffableSnapshot.itemIdentifier(atAllItemsIndex: index)! return context.objectPublisher(objectID: itemID) } @@ -83,16 +83,13 @@ public struct ListSnapshot: RandomAccessCollection, Hashable { */ public subscript(safeIndex index: Index) -> ObjectPublisher? { - guard let context = self.context else { + guard + let context = self.context, + let itemID = self.diffableSnapshot.itemIdentifier(atAllItemsIndex: index) + else { return nil } - let itemIDs = self.diffableSnapshot.itemIdentifiers - guard itemIDs.indices.contains(index) else { - - return nil - } - let itemID = itemIDs[index] return context.objectPublisher(objectID: itemID) } @@ -610,19 +607,61 @@ public struct ListSnapshot: RandomAccessCollection, Hashable { return self.diffableSnapshot.numberOfItems } + public func index(after i: Index) -> Index { + + return i + 1 + } + + public func formIndex(after i: inout Index) { + + return i += 1 + } + + public func index(before i: Index) -> Index { + + return i - 1 + } + + public func formIndex(before i: inout Index) { + + return i -= 1 + } + // MARK: BidirectionalCollection - public func index(_ i: Int, offsetBy distance: Int) -> Int { + public func index(_ i: Index, offsetBy distance: Int) -> Index { return i + distance } - public func distance(from start: Int, to end: Int) -> Int { + public func index(_ i: Index, offsetBy distance: Int, limitedBy limit: Int) -> Index? { + + let length = limit - i + if distance > 0 + ? length >= 0 && length < distance + : length <= 0 && length > distance { + + return nil + } + return i + distance + } + + public func distance(from start: Index, to end: Index) -> Int { return end - start } + public subscript(bounds: Range) -> ArraySlice { + + guard let context = self.context else { + + return .init() + } + let itemIDs = self.diffableSnapshot.itemIdentifiers(atAllItemsBounds: bounds) + return ArraySlice(itemIDs.map(context.objectPublisher(objectID:))) + } + // MARK: Sequence