Compare commits

...

18 Commits

Author SHA1 Message Date
John Estropia
edd8ba55d8 fix rare duplication of uniqueID values during import when an import candidate is added by a previous insertion block 2021-01-23 16:51:45 +09:00
John Estropia
18aac84335 fix compiler error 2021-01-02 10:36:33 +09:00
John Estropia
c6be892cb0 added .where(combinedByAnd:) and .where(combinedByOr:) to help compiler with long && and || chains 2021-01-02 10:00:23 +09:00
John Estropia
2cd8101987 Implement ObjectRepresentation on ObjectMonitor, ObjectPublisher, and ObjectSnapshot for future APIs 2021-01-02 09:59:15 +09:00
John Estropia
e1aed37da0 avoid using default queue qos 2020-12-26 23:45:11 +09:00
John Estropia
5de5ecee06 give opportunity for faster equating of ObjectSnapshot 2020-12-26 23:44:35 +09:00
John Estropia
9406901b28 WIP: SwiftUI utils 2020-12-26 19:21:46 +09:00
John Estropia
477f478d85 Add missing Where operators (fixes #410) 2020-12-26 14:02:20 +09:00
John Estropia
668b5ad606 Update playground samples to use Field properties instead of old syntax 2020-12-07 14:08:05 +09:00
John Estropia
f985828f3b cleanup 2020-11-17 18:14:23 +09:00
John Estropia
bb3bc940c2 Remove the dataStack SwiftUI environment key since it's prone to initialization issues 2020-11-11 16:56:20 +09:00
John Estropia
2d5bc77219 Merge branch 'master' into minIOS11
# Conflicts:
#	Sources/ListSnapshot.swift
2020-11-11 13:44:58 +09:00
John Estropia
a40df37192 version bump 2020-11-11 13:29:02 +09:00
John Estropia
63b3d25d78 clear warnings 2020-11-11 13:18:11 +09:00
John Estropia
74721b5c12 allow ObjectSnapshot and ObjectPublisher as parameter to Where clauses 2020-10-10 16:55:35 +09:00
John Estropia
f136549b46 prevent creation of ObjectSnapshot if object is already deleted 2020-10-09 20:14:04 +09:00
John Estropia
4ec2b2e311 Optimize ListSnapshot collection implementation 2020-10-05 23:12:17 +09:00
John Estropia
3d82ee18c7 reinclude LegacyDemo in workspace 2020-10-03 14:36:57 +09:00
40 changed files with 878 additions and 276 deletions

View File

@@ -1,6 +1,6 @@
Pod::Spec.new do |s| Pod::Spec.new do |s|
s.name = "CoreStore" s.name = "CoreStore"
s.version = "7.3.0" s.version = "7.3.1"
s.swift_version = "5.3" s.swift_version = "5.3"
s.license = "MIT" s.license = "MIT"
s.homepage = "https://github.com/JohnEstropia/CoreStore" s.homepage = "https://github.com/JohnEstropia/CoreStore"

View File

@@ -362,6 +362,10 @@
B52FD3AB1E3B3EF10001D919 /* NSManagedObject+Logging.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52FD3A91E3B3EF10001D919 /* NSManagedObject+Logging.swift */; }; B52FD3AB1E3B3EF10001D919 /* NSManagedObject+Logging.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52FD3A91E3B3EF10001D919 /* NSManagedObject+Logging.swift */; };
B52FD3AC1E3B3EF10001D919 /* NSManagedObject+Logging.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52FD3A91E3B3EF10001D919 /* NSManagedObject+Logging.swift */; }; B52FD3AC1E3B3EF10001D919 /* NSManagedObject+Logging.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52FD3A91E3B3EF10001D919 /* NSManagedObject+Logging.swift */; };
B52FD3AD1E3B3EF10001D919 /* NSManagedObject+Logging.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52FD3A91E3B3EF10001D919 /* NSManagedObject+Logging.swift */; }; B52FD3AD1E3B3EF10001D919 /* NSManagedObject+Logging.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52FD3A91E3B3EF10001D919 /* NSManagedObject+Logging.swift */; };
B52FEC742596DBE100368BFB /* ObjectReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52FEC732596DBE000368BFB /* ObjectReader.swift */; };
B52FEC752596DBE100368BFB /* ObjectReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52FEC732596DBE000368BFB /* ObjectReader.swift */; };
B52FEC762596DBE100368BFB /* ObjectReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52FEC732596DBE000368BFB /* ObjectReader.swift */; };
B52FEC772596DBE100368BFB /* ObjectReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52FEC732596DBE000368BFB /* ObjectReader.swift */; };
B533C4DB1D7D4BFA001383CB /* DispatchQueue+CoreStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B533C4DA1D7D4BFA001383CB /* DispatchQueue+CoreStore.swift */; }; B533C4DB1D7D4BFA001383CB /* DispatchQueue+CoreStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B533C4DA1D7D4BFA001383CB /* DispatchQueue+CoreStore.swift */; };
B533C4DC1D7D4BFA001383CB /* DispatchQueue+CoreStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B533C4DA1D7D4BFA001383CB /* DispatchQueue+CoreStore.swift */; }; B533C4DC1D7D4BFA001383CB /* DispatchQueue+CoreStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B533C4DA1D7D4BFA001383CB /* DispatchQueue+CoreStore.swift */; };
B533C4DD1D7D4BFA001383CB /* DispatchQueue+CoreStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B533C4DA1D7D4BFA001383CB /* DispatchQueue+CoreStore.swift */; }; B533C4DD1D7D4BFA001383CB /* DispatchQueue+CoreStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B533C4DA1D7D4BFA001383CB /* DispatchQueue+CoreStore.swift */; };
@@ -1064,6 +1068,7 @@
B52F743C1E9B8724005F3DAC /* XcodeDataModelSchema.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XcodeDataModelSchema.swift; sourceTree = "<group>"; }; B52F743C1E9B8724005F3DAC /* XcodeDataModelSchema.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XcodeDataModelSchema.swift; sourceTree = "<group>"; };
B52F74491E9B8740005F3DAC /* CoreStoreSchema.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreStoreSchema.swift; sourceTree = "<group>"; }; B52F74491E9B8740005F3DAC /* CoreStoreSchema.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreStoreSchema.swift; sourceTree = "<group>"; };
B52FD3A91E3B3EF10001D919 /* NSManagedObject+Logging.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSManagedObject+Logging.swift"; sourceTree = "<group>"; }; B52FD3A91E3B3EF10001D919 /* NSManagedObject+Logging.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSManagedObject+Logging.swift"; sourceTree = "<group>"; };
B52FEC732596DBE000368BFB /* ObjectReader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ObjectReader.swift; sourceTree = "<group>"; };
B533C4DA1D7D4BFA001383CB /* DispatchQueue+CoreStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "DispatchQueue+CoreStore.swift"; sourceTree = "<group>"; }; B533C4DA1D7D4BFA001383CB /* DispatchQueue+CoreStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "DispatchQueue+CoreStore.swift"; sourceTree = "<group>"; };
B538BA701D15B3E30003A766 /* CoreStoreBridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CoreStoreBridge.m; sourceTree = "<group>"; }; B538BA701D15B3E30003A766 /* CoreStoreBridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CoreStoreBridge.m; sourceTree = "<group>"; };
B53B275E1EE3B92E00E9B352 /* CoreStoreManagedObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreStoreManagedObject.swift; sourceTree = "<group>"; }; B53B275E1EE3B92E00E9B352 /* CoreStoreManagedObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreStoreManagedObject.swift; sourceTree = "<group>"; };
@@ -1535,6 +1540,14 @@
name = "Dynamic Schema"; name = "Dynamic Schema";
sourceTree = "<group>"; sourceTree = "<group>";
}; };
B52FEC722596DB6400368BFB /* SwiftUI */ = {
isa = PBXGroup;
children = (
B52FEC732596DBE000368BFB /* ObjectReader.swift */,
);
name = SwiftUI;
sourceTree = "<group>";
};
B53FBA101CAB607000F0D40A /* Convenience */ = { B53FBA101CAB607000F0D40A /* Convenience */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@@ -1697,6 +1710,7 @@
B5D1E22B19FA9FBC003B2874 /* CoreStoreError.swift */, B5D1E22B19FA9FBC003B2874 /* CoreStoreError.swift */,
B549F6721E56A92800FBAB2D /* CoreDataNativeType.swift */, B549F6721E56A92800FBAB2D /* CoreDataNativeType.swift */,
B5D339F01E94AF5800C880DE /* CoreStoreStrings.swift */, B5D339F01E94AF5800C880DE /* CoreStoreStrings.swift */,
B52FEC722596DB6400368BFB /* SwiftUI */,
B5E84EDA1AFF84500064E85B /* Setup */, B5E84EDA1AFF84500064E85B /* Setup */,
B51B5C2922D43854009FA3BA /* KeyPaths */, B51B5C2922D43854009FA3BA /* KeyPaths */,
B5E84EE21AFF84610064E85B /* Logging */, B5E84EE21AFF84610064E85B /* Logging */,
@@ -2165,7 +2179,7 @@
isa = PBXProject; isa = PBXProject;
attributes = { attributes = {
LastSwiftUpdateCheck = 0730; LastSwiftUpdateCheck = 0730;
LastUpgradeCheck = 1020; LastUpgradeCheck = 1200;
ORGANIZATIONNAME = "John Rommel Estropia"; ORGANIZATIONNAME = "John Rommel Estropia";
TargetAttributes = { TargetAttributes = {
2F03A52F19C5C6DA005002A5 = { 2F03A52F19C5C6DA005002A5 = {
@@ -2441,6 +2455,7 @@
B559CD491CAA8C6D00E4D58B /* CSStorageInterface.swift in Sources */, B559CD491CAA8C6D00E4D58B /* CSStorageInterface.swift in Sources */,
B5ECDC2F1CA81CDC00C7F112 /* CSCoreStore+Transaction.swift in Sources */, B5ECDC2F1CA81CDC00C7F112 /* CSCoreStore+Transaction.swift in Sources */,
B5E84F311AFF849C0064E85B /* Internals.WeakObject.swift in Sources */, B5E84F311AFF849C0064E85B /* Internals.WeakObject.swift in Sources */,
B52FEC742596DBE100368BFB /* ObjectReader.swift in Sources */,
B5E84F101AFF847B0064E85B /* GroupBy.swift in Sources */, B5E84F101AFF847B0064E85B /* GroupBy.swift in Sources */,
B5E84F201AFF84860064E85B /* DataStack+Observing.swift in Sources */, B5E84F201AFF84860064E85B /* DataStack+Observing.swift in Sources */,
B501FDDD1CA8D05000BE22EF /* CSSectionBy.swift in Sources */, B501FDDD1CA8D05000BE22EF /* CSSectionBy.swift in Sources */,
@@ -2693,6 +2708,7 @@
B501FDDF1CA8D05000BE22EF /* CSSectionBy.swift in Sources */, B501FDDF1CA8D05000BE22EF /* CSSectionBy.swift in Sources */,
B5BF7FAE234C41E90070E741 /* Internals.DiffableDataSourceSnapshot.swift in Sources */, B5BF7FAE234C41E90070E741 /* Internals.DiffableDataSourceSnapshot.swift in Sources */,
B538BA781D15B3E30003A766 /* CoreStoreBridge.m in Sources */, B538BA781D15B3E30003A766 /* CoreStoreBridge.m in Sources */,
B52FEC752596DBE100368BFB /* ObjectReader.swift in Sources */,
B51260801E97A18000402229 /* CoreStoreObject+Convenience.swift in Sources */, B51260801E97A18000402229 /* CoreStoreObject+Convenience.swift in Sources */,
82BA18D31C4BBD7100A0916E /* NSManagedObjectContext+CoreStore.swift in Sources */, 82BA18D31C4BBD7100A0916E /* NSManagedObjectContext+CoreStore.swift in Sources */,
82BA18AD1C4BBD3100A0916E /* UnsafeDataTransaction.swift in Sources */, 82BA18AD1C4BBD3100A0916E /* UnsafeDataTransaction.swift in Sources */,
@@ -2945,6 +2961,7 @@
B5220E181D130711009BC71E /* ObjectObserver.swift in Sources */, B5220E181D130711009BC71E /* ObjectObserver.swift in Sources */,
B5220E251D13088E009BC71E /* ListObserver.swift in Sources */, B5220E251D13088E009BC71E /* ListObserver.swift in Sources */,
B538BA7A1D15B3E30003A766 /* CoreStoreBridge.m in Sources */, B538BA7A1D15B3E30003A766 /* CoreStoreBridge.m in Sources */,
B52FEC772596DBE100368BFB /* ObjectReader.swift in Sources */,
B5BF7FB0234C41E90070E741 /* Internals.DiffableDataSourceSnapshot.swift in Sources */, B5BF7FB0234C41E90070E741 /* Internals.DiffableDataSourceSnapshot.swift in Sources */,
B51260821E97A18000402229 /* CoreStoreObject+Convenience.swift in Sources */, B51260821E97A18000402229 /* CoreStoreObject+Convenience.swift in Sources */,
B52DD1A01BE1F92C00949AFE /* UnsafeDataTransaction.swift in Sources */, B52DD1A01BE1F92C00949AFE /* UnsafeDataTransaction.swift in Sources */,
@@ -3197,6 +3214,7 @@
B501FDE01CA8D05000BE22EF /* CSSectionBy.swift in Sources */, B501FDE01CA8D05000BE22EF /* CSSectionBy.swift in Sources */,
B5BF7FAF234C41E90070E741 /* Internals.DiffableDataSourceSnapshot.swift in Sources */, B5BF7FAF234C41E90070E741 /* Internals.DiffableDataSourceSnapshot.swift in Sources */,
B538BA791D15B3E30003A766 /* CoreStoreBridge.m in Sources */, B538BA791D15B3E30003A766 /* CoreStoreBridge.m in Sources */,
B52FEC762596DBE100368BFB /* ObjectReader.swift in Sources */,
B51260811E97A18000402229 /* CoreStoreObject+Convenience.swift in Sources */, B51260811E97A18000402229 /* CoreStoreObject+Convenience.swift in Sources */,
B56321B11BD6521C006C9394 /* NSManagedObjectContext+CoreStore.swift in Sources */, B56321B11BD6521C006C9394 /* NSManagedObjectContext+CoreStore.swift in Sources */,
B563218D1BD65216006C9394 /* CoreStore+Transaction.swift in Sources */, B563218D1BD65216006C9394 /* CoreStore+Transaction.swift in Sources */,
@@ -3292,6 +3310,7 @@
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES;
@@ -3363,6 +3382,7 @@
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES;
@@ -3413,7 +3433,7 @@
DYLIB_INSTALL_NAME_BASE = "@rpath"; DYLIB_INSTALL_NAME_BASE = "@rpath";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MARKETING_VERSION = 7.3.0; MARKETING_VERSION = 7.3.1;
OTHER_LDFLAGS = ( OTHER_LDFLAGS = (
"-weak_framework", "-weak_framework",
Combine, Combine,
@@ -3436,7 +3456,7 @@
DYLIB_INSTALL_NAME_BASE = "@rpath"; DYLIB_INSTALL_NAME_BASE = "@rpath";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MARKETING_VERSION = 7.3.0; MARKETING_VERSION = 7.3.1;
OTHER_LDFLAGS = ( OTHER_LDFLAGS = (
"-weak_framework", "-weak_framework",
Combine, Combine,
@@ -3496,7 +3516,7 @@
GCC_NO_COMMON_BLOCKS = YES; GCC_NO_COMMON_BLOCKS = YES;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MARKETING_VERSION = 7.3.0; MARKETING_VERSION = 7.3.1;
OTHER_LDFLAGS = ( OTHER_LDFLAGS = (
"-weak_framework", "-weak_framework",
Combine, Combine,
@@ -3522,7 +3542,7 @@
GCC_NO_COMMON_BLOCKS = YES; GCC_NO_COMMON_BLOCKS = YES;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MARKETING_VERSION = 7.3.0; MARKETING_VERSION = 7.3.1;
OTHER_LDFLAGS = ( OTHER_LDFLAGS = (
"-weak_framework", "-weak_framework",
Combine, Combine,
@@ -3587,7 +3607,7 @@
GCC_NO_COMMON_BLOCKS = YES; GCC_NO_COMMON_BLOCKS = YES;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
MARKETING_VERSION = 7.3.0; MARKETING_VERSION = 7.3.1;
OTHER_LDFLAGS = ( OTHER_LDFLAGS = (
"-weak_framework", "-weak_framework",
Combine, Combine,
@@ -3616,7 +3636,7 @@
GCC_NO_COMMON_BLOCKS = YES; GCC_NO_COMMON_BLOCKS = YES;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
MARKETING_VERSION = 7.3.0; MARKETING_VERSION = 7.3.1;
OTHER_LDFLAGS = ( OTHER_LDFLAGS = (
"-weak_framework", "-weak_framework",
Combine, Combine,
@@ -3682,7 +3702,7 @@
GCC_NO_COMMON_BLOCKS = YES; GCC_NO_COMMON_BLOCKS = YES;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MARKETING_VERSION = 7.3.0; MARKETING_VERSION = 7.3.1;
OTHER_LDFLAGS = ( OTHER_LDFLAGS = (
"-weak_framework", "-weak_framework",
Combine, Combine,
@@ -3710,7 +3730,7 @@
GCC_NO_COMMON_BLOCKS = YES; GCC_NO_COMMON_BLOCKS = YES;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MARKETING_VERSION = 7.3.0; MARKETING_VERSION = 7.3.1;
OTHER_LDFLAGS = ( OTHER_LDFLAGS = (
"-weak_framework", "-weak_framework",
Combine, Combine,

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1020" LastUpgradeVersion = "1200"
version = "1.3"> version = "1.3">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1020" LastUpgradeVersion = "1200"
version = "1.3"> version = "1.3">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1020" LastUpgradeVersion = "1200"
version = "1.3"> version = "1.3">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1020" LastUpgradeVersion = "1200"
version = "1.3"> version = "1.3">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"

View File

@@ -8,6 +8,6 @@
location = "group:CoreStore.xcodeproj"> location = "group:CoreStore.xcodeproj">
</FileRef> </FileRef>
<FileRef <FileRef
location = "group:/Users/JohnEstropia/Documents/XCodeProjects/CoreStore/LegacyDemo/LegacyDemo.xcodeproj"> location = "group:LegacyDemo/LegacyDemo.xcodeproj">
</FileRef> </FileRef>
</Workspace> </Workspace>

View File

@@ -290,19 +290,6 @@ class DynamicModelTests: BaseTestDataTestCase {
} }
} }
// #if swift(>=5.1)
//
// let dogKeyPathBuilder = Dog.keyPathBuilder()
// XCTAssertEqual(dogKeyPathBuilder.species.keyPathString, "SELF.species")
// XCTAssertEqual(dogKeyPathBuilder.master.title.keyPathString, "SELF.master.title")
// let a = dogKeyPathBuilder.master
// let b = dogKeyPathBuilder.master.spouse
// let c = dogKeyPathBuilder.master.spouse.pets
// let d = dogKeyPathBuilder.master.spouse.pets.color
// XCTAssertEqual(dogKeyPathBuilder.master.spouse.pets.color.keyPathString, "SELF.master.spouse.pets.color")
//
// #endif
let didSetObserver = dog.observe(\.$species, options: [.new, .old]) { (object, change) in let didSetObserver = dog.observe(\.$species, options: [.new, .old]) { (object, change) in
XCTAssertEqual(object, dog) XCTAssertEqual(object, dog)

View File

@@ -77,17 +77,10 @@ final class WhereTests: XCTestCase {
do { do {
// let keyPathBuilder = TestEntity1.keyPathBuilder()
// let kp = \TestEntity1.testToOne
// print(keyPathBuilder.testString)
// print(keyPathBuilder.testToOne)
// print(keyPathBuilder.testToOne.testEntityID)
XCTAssertAllEqual( XCTAssertAllEqual(
#keyPath(TestEntity1.testToOne.testEntityID), #keyPath(TestEntity1.testToOne.testEntityID),
(\TestEntity1.testToOne ~ \.testEntityID).description, (\TestEntity1.testToOne ~ \.testEntityID).description,
String(keyPath: \TestEntity1.testToOne ~ \.testEntityID) String(keyPath: \TestEntity1.testToOne ~ \.testEntityID)
// keyPathBuilder.testToOne.testEntityID.keyPathString
) )
XCTAssertAllEqual( XCTAssertAllEqual(
#keyPath(TestEntity1.testToOne.testToOne.testToManyUnordered), #keyPath(TestEntity1.testToOne.testToOne.testToManyUnordered),

View File

@@ -622,7 +622,7 @@
isa = PBXProject; isa = PBXProject;
attributes = { attributes = {
LastSwiftUpdateCheck = 1160; LastSwiftUpdateCheck = 1160;
LastUpgradeCheck = 1160; LastUpgradeCheck = 1200;
TargetAttributes = { TargetAttributes = {
B5A3911824E5429200E7E8BD = { B5A3911824E5429200E7E8BD = {
CreatedOnToolsVersion = 11.6; CreatedOnToolsVersion = 11.6;
@@ -769,6 +769,33 @@
B5A3911324E5424E00E7E8BD /* Debug */ = { B5A3911324E5424E00E7E8BD /* Debug */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 13.0; IPHONEOS_DEPLOYMENT_TARGET = 13.0;
}; };
name = Debug; name = Debug;
@@ -776,6 +803,32 @@
B5A3911424E5424E00E7E8BD /* Release */ = { B5A3911424E5424E00E7E8BD /* Release */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 13.0; IPHONEOS_DEPLOYMENT_TARGET = 13.0;
}; };
name = Release; name = Release;

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1160" LastUpgradeVersion = "1200"
version = "1.3"> version = "1.3">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"

View File

@@ -5,6 +5,7 @@
import CoreStore import CoreStore
import SwiftUI import SwiftUI
// MARK: - Modern.ColorsDemo.SwiftUI // MARK: - Modern.ColorsDemo.SwiftUI
extension Modern.ColorsDemo.SwiftUI { extension Modern.ColorsDemo.SwiftUI {
@@ -39,7 +40,7 @@ extension Modern.ColorsDemo.SwiftUI {
.listRowInsets(.init()) .listRowInsets(.init())
} }
.onDelete { itemIndices in .onDelete { itemIndices in
self.deleteColors(at: itemIndices, in: sectionID) self.deleteColors(at: itemIndices, in: sectionID)
} }
} }

View File

@@ -295,7 +295,7 @@
isa = PBXProject; isa = PBXProject;
attributes = { attributes = {
LastSwiftUpdateCheck = 0700; LastSwiftUpdateCheck = 0700;
LastUpgradeCheck = 0930; LastUpgradeCheck = 1200;
ORGANIZATIONNAME = "John Rommel Estropia"; ORGANIZATIONNAME = "John Rommel Estropia";
TargetAttributes = { TargetAttributes = {
B54AAD481AF4D26E00848AE0 = { B54AAD481AF4D26E00848AE0 = {
@@ -422,6 +422,7 @@
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES;
@@ -479,6 +480,7 @@
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES;

View File

@@ -6,14 +6,24 @@ PlaygroundPage.current.needsIndefiniteExecution = true
/// Model Declaration ===== /// Model Declaration =====
class Animal: CoreStoreObject { class Animal: CoreStoreObject {
let species = Value.Required<String>("species", initial: "Swift")
let master = Relationship.ToOne<Person>("master") @Field.Stored("species")
let color = Transformable.Optional<UIColor>("color", initial: .orange) var species: String = "Swift"
@Field.Coded("color", coder: FieldCoders.NSCoding.self)
var color: UIColor = .orange
@Field.Relationship("master")
var master: Person?
} }
class Person: CoreStoreObject { class Person: CoreStoreObject {
let name = Value.Optional<String>("name")
let pets = Relationship.ToManyUnordered<Animal>("pets", inverse: { $0.master }) @Field.Stored("name")
var name: String?
@Field.Relationship("pets", inverse: \.$master)
var pets: Set<Animal>
} }
/// ======================= /// =======================
@@ -24,6 +34,10 @@ let dataStack = DataStack(
entities: [ entities: [
Entity<Animal>("Animal"), Entity<Animal>("Animal"),
Entity<Person>("Person") Entity<Person>("Person")
],
versionLock: [
"Animal": [0x4a201cc685d53c0a, 0x16e6c3b561577875, 0xb032e2da61c792a0, 0xa133b801051acee4],
"Person": [0xca938eea1af4bd56, 0xbca30994506356ad, 0x7a7cc655898816ef, 0x1a4551ffedc9b214]
] ]
) )
) )
@@ -42,12 +56,12 @@ dataStack.addStorage(
asynchronous: { transaction in asynchronous: { transaction in
let animal = transaction.create(Into<Animal>()) let animal = transaction.create(Into<Animal>())
animal.species .= "Sparrow" animal.species = "Sparrow"
animal.color .= .yellow animal.color = .yellow
let person = transaction.create(Into<Person>()) let person = transaction.create(Into<Person>())
person.name .= "John" person.name = "John"
person.pets.value.insert(animal) person.pets.insert(animal)
}, },
completion: { result in completion: { result in
@@ -58,13 +72,16 @@ dataStack.addStorage(
case .success: case .success:
/// Accessing Objects ===== /// Accessing Objects =====
let bird = try! dataStack.fetchOne(From<Animal>().where(\.species == "Sparrow"))! let bird = try! dataStack.fetchOne(
print(bird.species.value) From<Animal>()
print(bird.color.value as Any) .where(\.$species == "Sparrow")
)!
print(bird.species)
print(bird.color as Any)
print(bird) print(bird)
let owner = bird.master.value! let owner = bird.master!
print(owner.name.value as Any) print(owner.name as Any)
print(owner.pets.count) print(owner.pets.count)
print(owner) print(owner)
/// ======================= /// =======================

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<playground version='5.0' target-platform='ios' executeOnSourceChanges='false'> <playground version='5.0' target-platform='ios' buildActiveScheme='true'>
<timeline fileName='timeline.xctimeline'/> <timeline fileName='timeline.xctimeline'/>
</playground> </playground>

View File

@@ -6,14 +6,24 @@ PlaygroundPage.current.needsIndefiniteExecution = true
/// Model Declaration ===== /// Model Declaration =====
class Animal: CoreStoreObject { class Animal: CoreStoreObject {
let species = Value.Required<String>("species", initial: "Swift")
let master = Relationship.ToOne<Person>("master") @Field.Stored("species")
let color = Transformable.Optional<NSColor>("color", initial: .orange) var species: String = "Swift"
@Field.Coded("color", coder: FieldCoders.NSCoding.self)
var color: NSColor = .orange
@Field.Relationship("master")
var master: Person?
} }
class Person: CoreStoreObject { class Person: CoreStoreObject {
let name = Value.Optional<String>("name")
let pets = Relationship.ToManyUnordered<Animal>("pets", inverse: { $0.master }) @Field.Stored("name")
var name: String?
@Field.Relationship("pets", inverse: \.$master)
var pets: Set<Animal>
} }
/// ======================= /// =======================
@@ -24,6 +34,10 @@ let dataStack = DataStack(
entities: [ entities: [
Entity<Animal>("Animal"), Entity<Animal>("Animal"),
Entity<Person>("Person") Entity<Person>("Person")
],
versionLock: [
"Animal": [0x4a201cc685d53c0a, 0x16e6c3b561577875, 0xb032e2da61c792a0, 0xa133b801051acee4],
"Person": [0xca938eea1af4bd56, 0xbca30994506356ad, 0x7a7cc655898816ef, 0x1a4551ffedc9b214]
] ]
) )
) )
@@ -42,12 +56,12 @@ dataStack.addStorage(
asynchronous: { transaction in asynchronous: { transaction in
let animal = transaction.create(Into<Animal>()) let animal = transaction.create(Into<Animal>())
animal.species .= "Sparrow" animal.species = "Sparrow"
animal.color .= .yellow animal.color = .yellow
let person = transaction.create(Into<Person>()) let person = transaction.create(Into<Person>())
person.name .= "John" person.name = "John"
person.pets.value.insert(animal) person.pets.insert(animal)
}, },
completion: { result in completion: { result in
@@ -58,13 +72,16 @@ dataStack.addStorage(
case .success: case .success:
/// Accessing Objects ===== /// Accessing Objects =====
let bird = try! dataStack.fetchOne(From<Animal>().where(\.species == "Sparrow"))! let bird = try! dataStack.fetchOne(
print(bird.species.value) From<Animal>()
print(bird.color.value as Any) .where(\.$species == "Sparrow")
)!
print(bird.species)
print(bird.color as Any)
print(bird) print(bird)
let owner = bird.master.value! let owner = bird.master!
print(owner.name.value as Any) print(owner.name as Any)
print(owner.pets.count) print(owner.pets.count)
print(owner) print(owner)
/// ======================= /// =======================

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<playground version='5.0' target-platform='macos' executeOnSourceChanges='false'> <playground version='5.0' target-platform='macos' buildActiveScheme='true'>
<timeline fileName='timeline.xctimeline'/> <timeline fileName='timeline.xctimeline'/>
</playground> </playground>

View File

@@ -2095,7 +2095,7 @@ This installs CoreStore as a framework. Declare `import CoreStore` in your swift
#### Install with Swift Package Manager: #### Install with Swift Package Manager:
```swift ```swift
dependencies: [ 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. Declare `import CoreStore` in your swift file to use the library.

View File

@@ -230,7 +230,10 @@ extension BaseDataTransaction {
} }
try autoreleasepool { try autoreleasepool {
if let object = existingObjectsByID[objectID] { if let object = existingObjectsByID[objectID]
?? self.context.insertedObjects
.compactMap({ O.cs_matches(object: $0) ? O.cs_fromRaw(object: $0) : nil })
.first(where: { $0.uniqueIDValue == objectID }) {
guard entityType.shouldUpdate(from: source, in: self) else { guard entityType.shouldUpdate(from: source, in: self) else {

View File

@@ -429,7 +429,7 @@ public /*abstract*/ class BaseDataTransaction {
internal let context: NSManagedObjectContext internal let context: NSManagedObjectContext
internal let transactionQueue: DispatchQueue internal let transactionQueue: DispatchQueue
internal let childTransactionQueue = DispatchQueue.serial("com.corestore.datastack.childTransactionQueue") internal let childTransactionQueue = DispatchQueue.serial("com.corestore.datastack.childTransactionQueue", qos: .utility)
internal let supportsUndo: Bool internal let supportsUndo: Bool
internal let bypassesQueueing: Bool internal let bypassesQueueing: Bool
internal var isCommitted = false internal var isCommitted = false

View File

@@ -1189,7 +1189,6 @@ extension NSAttributeDescription: CoreStoreDebugStringConvertible {
("versionHash", self.versionHash), ("versionHash", self.versionHash),
("versionHashModifier", self.versionHashModifier as Any), ("versionHashModifier", self.versionHashModifier as Any),
("isIndexedBySpotlight", self.isIndexedBySpotlight), ("isIndexedBySpotlight", self.isIndexedBySpotlight),
("isStoredInExternalRecord", self.isStoredInExternalRecord),
("renamingIdentifier", self.renamingIdentifier as Any) ("renamingIdentifier", self.renamingIdentifier as Any)
) )
} }
@@ -1363,11 +1362,9 @@ extension NSRelationshipDescription: CoreStoreDebugStringConvertible {
("isOptional", self.isOptional), ("isOptional", self.isOptional),
("isTransient", self.isTransient), ("isTransient", self.isTransient),
("userInfo", self.userInfo as Any), ("userInfo", self.userInfo as Any),
("isIndexed", self.isIndexed),
("versionHash", self.versionHash), ("versionHash", self.versionHash),
("versionHashModifier", self.versionHashModifier as Any), ("versionHashModifier", self.versionHashModifier as Any),
("isIndexedBySpotlight", self.isIndexedBySpotlight), ("isIndexedBySpotlight", self.isIndexedBySpotlight),
("isStoredInExternalRecord", self.isStoredInExternalRecord),
("renamingIdentifier", self.renamingIdentifier as Any) ("renamingIdentifier", self.renamingIdentifier as Any)
) )
} }

View File

@@ -29,4 +29,4 @@
FOUNDATION_EXPORT double CoreStoreVersionNumber; FOUNDATION_EXPORT double CoreStoreVersionNumber;
FOUNDATION_EXPORT const unsigned char CoreStoreVersionString[]; FOUNDATION_EXPORT const unsigned char CoreStoreVersionString[];
#import "CoreStoreBridge.h" #import <CoreStore/CoreStoreBridge.h>

View File

@@ -69,7 +69,7 @@ public enum CoreStoreDefaults {
// MARK: Private // MARK: Private
private static let defaultStackBarrierQueue = DispatchQueue.concurrent("com.coreStore.defaultStackBarrierQueue") private static let defaultStackBarrierQueue = DispatchQueue.concurrent("com.coreStore.defaultStackBarrierQueue", qos: .userInteractive)
private static var defaultStackInstance: DataStack? private static var defaultStackInstance: DataStack?
} }

View File

@@ -48,6 +48,6 @@ import Foundation
private enum Static { private enum Static {
static let queue = DispatchQueue.concurrent("com.coreStore.coreStoreManagerObjectBarrierQueue") static let queue = DispatchQueue.concurrent("com.coreStore.coreStoreManagerObjectBarrierQueue", qos: .userInteractive)
static var cache: [ObjectIdentifier: [KeyPathString: Set<KeyPathString>]] = [:] static var cache: [ObjectIdentifier: [KeyPathString: Set<KeyPathString>]] = [:]
} }

View File

@@ -254,7 +254,7 @@ public final class CoreStoreSchema: DynamicSchema {
// MARK: Private // MARK: Private
private static let barrierQueue = DispatchQueue.concurrent("com.coreStore.coreStoreDataModelBarrierQueue") private static let barrierQueue = DispatchQueue.concurrent("com.coreStore.coreStoreDataModelBarrierQueue", qos: .userInteractive)
private let allEntities: Set<DynamicEntity> private let allEntities: Set<DynamicEntity>

View File

@@ -440,8 +440,8 @@ public final class DataStack: Equatable {
internal let rootSavingContext: NSManagedObjectContext internal let rootSavingContext: NSManagedObjectContext
internal let mainContext: NSManagedObjectContext internal let mainContext: NSManagedObjectContext
internal let schemaHistory: SchemaHistory internal let schemaHistory: SchemaHistory
internal let childTransactionQueue = DispatchQueue.serial("com.coreStore.dataStack.childTransactionQueue") internal let childTransactionQueue = DispatchQueue.serial("com.coreStore.dataStack.childTransactionQueue", qos: .utility)
internal let storeMetadataUpdateQueue = DispatchQueue.concurrent("com.coreStore.persistentStoreBarrierQueue") internal let storeMetadataUpdateQueue = DispatchQueue.concurrent("com.coreStore.persistentStoreBarrierQueue", qos: .userInteractive)
internal let migrationQueue: OperationQueue = Internals.with { internal let migrationQueue: OperationQueue = Internals.with {
let migrationQueue = OperationQueue() let migrationQueue = OperationQueue()

View File

@@ -63,7 +63,7 @@ extension DiffableDataSource {
*/ */
open class TableViewAdapter<O: DynamicObject>: BaseAdapter<O, DefaultTableViewTarget<UITableView>>, UITableViewDataSource { open class TableViewAdapter<O: DynamicObject>: BaseAdapter<O, DefaultTableViewTarget<UITableView>>, UITableViewDataSource {
// MARK: Publi // MARK: Public
/** /**
Initializes the `DiffableDataSource.TableViewAdapter`. This instance needs to be held on (retained) for as long as the `UITableView`'s lifecycle. Initializes the `DiffableDataSource.TableViewAdapter`. This instance needs to be held on (retained) for as long as the `UITableView`'s lifecycle.

View File

@@ -31,7 +31,7 @@ import Foundation
extension DispatchQueue { extension DispatchQueue {
@nonobjc @inline(__always) @nonobjc @inline(__always)
internal static func serial(_ label: String, qos: DispatchQoS = .default) -> DispatchQueue { internal static func serial(_ label: String, qos: DispatchQoS) -> DispatchQueue {
return DispatchQueue( return DispatchQueue(
label: label, label: label,
@@ -43,7 +43,7 @@ extension DispatchQueue {
} }
@nonobjc @inline(__always) @nonobjc @inline(__always)
internal static func concurrent(_ label: String, qos: DispatchQoS = .default) -> DispatchQueue { internal static func concurrent(_ label: String, qos: DispatchQoS) -> DispatchQueue {
return DispatchQueue( return DispatchQueue(
label: label, label: label,

View File

@@ -217,7 +217,8 @@ extension CoreStoreObject {
guard guard
let object = context.fetchExisting(id) as CoreStoreObject?, let object = context.fetchExisting(id) as CoreStoreObject?,
let rawObject = object.rawObject let rawObject = object.rawObject,
!rawObject.isDeleted
else { else {
return nil return nil

View File

@@ -42,6 +42,28 @@ extension From {
return self.fetchChain(appending: clause) return self.fetchChain(appending: clause)
} }
/**
Creates a `FetchChainBuilder` that `AND`s the specified `Where` clauses. Use this overload if the compiler cannot infer the types when chaining multiple `&&` operators.
- parameter clauses: the `Where` clauses to create a `FetchChainBuilder` with
- returns: a `FetchChainBuilder` that `AND`s the specified `Where` clauses
*/
public func `where`(combineByAnd clauses: Where<O>...) -> FetchChainBuilder<O> {
return self.fetchChain(appending: clauses.combinedByAnd())
}
/**
Creates a `FetchChainBuilder` that `OR`s the specified `Where` clauses. Use this overload if the compiler cannot infer the types when chaining multiple `||` operators.
- parameter clauses: the `Where` clauses to create a `FetchChainBuilder` with
- returns: a `FetchChainBuilder` that `OR`s the specified `Where` clauses
*/
public func `where`(combineByOr clauses: Where<O>...) -> FetchChainBuilder<O> {
return self.fetchChain(appending: clauses.combinedByOr())
}
/** /**
Creates a `FetchChainBuilder` with a predicate using the specified string format and arguments Creates a `FetchChainBuilder` with a predicate using the specified string format and arguments
@@ -295,11 +317,6 @@ extension From where O: CoreStoreObject {
return self.fetchChain(appending: clause(O.meta)) return self.fetchChain(appending: clause(O.meta))
} }
public func `where`(combinedByAnd clause: Where<O>, _ others: Where<O>...) -> FetchChainBuilder<O> {
return self.fetchChain(appending: ([clause] + others).combinedByAnd())
}
/** /**
Creates a `QueryChainBuilder` that starts with a `Select` clause created from the specified key path Creates a `QueryChainBuilder` that starts with a `Select` clause created from the specified key path
@@ -544,6 +561,28 @@ extension FetchChainBuilder {
return self.fetchChain(appending: clause) return self.fetchChain(appending: clause)
} }
/**
Creates a `FetchChainBuilder` that `AND`s the specified `Where` clauses. Use this overload if the compiler cannot infer the types when chaining multiple `&&` operators.
- parameter clauses: the `Where` clauses to create a `FetchChainBuilder` with
- returns: a `FetchChainBuilder` that `AND`s the specified `Where` clauses
*/
public func `where`(combineByAnd clauses: Where<O>...) -> FetchChainBuilder<O> {
return self.fetchChain(appending: clauses.combinedByAnd())
}
/**
Creates a `FetchChainBuilder` that `OR`s the specified `Where` clauses. Use this overload if the compiler cannot infer the types when chaining multiple `||` operators.
- parameter clauses: the `Where` clauses to create a `FetchChainBuilder` with
- returns: a `FetchChainBuilder` that `OR`s the specified `Where` clauses
*/
public func `where`(combineByOr clauses: Where<O>...) -> FetchChainBuilder<O> {
return self.fetchChain(appending: clauses.combinedByOr())
}
/** /**
Adds a `Where` clause to the `FetchChainBuilder` Adds a `Where` clause to the `FetchChainBuilder`
@@ -682,6 +721,28 @@ extension QueryChainBuilder {
return self.queryChain(appending: clause) return self.queryChain(appending: clause)
} }
/**
Creates a `FetchChainBuilder` that `AND`s the specified `Where` clauses. Use this overload if the compiler cannot infer the types when chaining multiple `&&` operators.
- parameter clauses: the `Where` clauses to create a `FetchChainBuilder` with
- returns: a `FetchChainBuilder` that `AND`s the specified `Where` clauses
*/
public func `where`(combineByAnd clauses: Where<O>...) -> QueryChainBuilder<O, R> {
return self.queryChain(appending: clauses.combinedByAnd())
}
/**
Creates a `FetchChainBuilder` that `OR`s the specified `Where` clauses. Use this overload if the compiler cannot infer the types when chaining multiple `||` operators.
- parameter clauses: the `Where` clauses to create a `FetchChainBuilder` with
- returns: a `FetchChainBuilder` that `OR`s the specified `Where` clauses
*/
public func `where`(combineByOr clauses: Where<O>...) -> QueryChainBuilder<O, R> {
return self.queryChain(appending: clauses.combinedByOr())
}
/** /**
Adds a `Where` clause to the `QueryChainBuilder` Adds a `Where` clause to the `QueryChainBuilder`
@@ -957,6 +1018,28 @@ extension SectionMonitorChainBuilder {
return self.sectionMonitorChain(appending: clause) return self.sectionMonitorChain(appending: clause)
} }
/**
Creates a `FetchChainBuilder` that `AND`s the specified `Where` clauses. Use this overload if the compiler cannot infer the types when chaining multiple `&&` operators.
- parameter clauses: the `Where` clauses to create a `FetchChainBuilder` with
- returns: a `FetchChainBuilder` that `AND`s the specified `Where` clauses
*/
public func `where`(combineByAnd clauses: Where<O>...) -> SectionMonitorChainBuilder<O> {
return self.sectionMonitorChain(appending: clauses.combinedByAnd())
}
/**
Creates a `FetchChainBuilder` that `OR`s the specified `Where` clauses. Use this overload if the compiler cannot infer the types when chaining multiple `||` operators.
- parameter clauses: the `Where` clauses to create a `FetchChainBuilder` with
- returns: a `FetchChainBuilder` that `OR`s the specified `Where` clauses
*/
public func `where`(combineByOr clauses: Where<O>...) -> SectionMonitorChainBuilder<O> {
return self.sectionMonitorChain(appending: clauses.combinedByOr())
}
/** /**
Adds a `Where` clause to the `SectionMonitorChainBuilder` Adds a `Where` clause to the `SectionMonitorChainBuilder`

View File

@@ -53,7 +53,7 @@ import CoreData
) )
``` ```
*/ */
public protocol ImportableUniqueObject: ImportableObject { public protocol ImportableUniqueObject: ImportableObject, Hashable {
/** /**
The data type for the entity's unique ID attribute The data type for the entity's unique ID attribute

View File

@@ -78,7 +78,7 @@ extension Internals {
var numberOfItems: Int { var numberOfItems: Int {
return self.structure.allItemIDs.count return self.structure.allItemsCount
} }
var numberOfSections: Int { var numberOfSections: Int {
@@ -106,6 +106,59 @@ extension Internals {
return self.itemIdentifiers(inSection: identifier).count 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<Int>) -> [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..<min(sectionCount, bounds.count)]
.map({ $0.differenceIdentifier })
)
}
else if !itemIdentifiers.isEmpty {
itemIdentifiers.append(
contentsOf: elements.prefix(bounds.count - itemIdentifiers.count)
.map({ $0.differenceIdentifier })
)
}
if itemIdentifiers.count >= bounds.count {
return itemIdentifiers
}
remainingIndex -= sectionCount
}
return itemIdentifiers
}
func itemIdentifiers(inSection identifier: String) -> [NSManagedObjectID] { func itemIdentifiers(inSection identifier: String) -> [NSManagedObjectID] {
return self.structure.items(in: identifier) return self.structure.items(in: identifier)
@@ -332,6 +385,14 @@ extension Internals {
return self.sections.map({ $0.differenceIdentifier }) 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] { var allItemIDs: [NSManagedObjectID] {
return self.sections.lazy.flatMap({ $0.elements }).map({ $0.differenceIdentifier }) return self.sections.lazy.flatMap({ $0.elements }).map({ $0.differenceIdentifier })

View File

@@ -267,6 +267,17 @@ public func == <O: NSManagedObject, D: NSManagedObject>(_ keyPath: KeyPath<O, D>
return Where<O>(keyPath._kvcKeyPathString!, isEqualTo: objectID) return Where<O>(keyPath._kvcKeyPathString!, isEqualTo: objectID)
} }
/**
Creates a `Where` clause by comparing if a property is equal to a value
```
let dog = dataStack.fetchOne(From<Dog>().where(\.master == john))
```
*/
public func == <O: ObjectRepresentation, D: NSManagedObject>(_ keyPath: KeyPath<O, D>, _ object: O) -> Where<O> where O.ObjectType: NSManagedObject {
return Where<O>(keyPath._kvcKeyPathString!, isEqualTo: object.cs_id())
}
/** /**
Creates a `Where` clause by comparing if a property is not equal to a value Creates a `Where` clause by comparing if a property is not equal to a value
``` ```
@@ -278,6 +289,17 @@ public func != <O: NSManagedObject, D: NSManagedObject>(_ keyPath: KeyPath<O, D>
return !Where<O>(keyPath._kvcKeyPathString!, isEqualTo: objectID) return !Where<O>(keyPath._kvcKeyPathString!, isEqualTo: objectID)
} }
/**
Creates a `Where` clause by comparing if a property is not equal to a value
```
let dog = dataStack.fetchOne(From<Dog>().where(\.master != john))
```
*/
public func != <O: ObjectRepresentation, D: NSManagedObject>(_ keyPath: KeyPath<O, D>, _ object: O) -> Where<O> where O.ObjectType: NSManagedObject {
return !Where<O>(keyPath._kvcKeyPathString!, isEqualTo: object.cs_id())
}
/** /**
Creates a `Where` clause by checking if a sequence contains a value of a property Creates a `Where` clause by checking if a sequence contains a value of a property
``` ```
@@ -303,6 +325,17 @@ public func == <O: NSManagedObject, D: NSManagedObject>(_ keyPath: KeyPath<O, Op
return Where<O>(keyPath._kvcKeyPathString!, isEqualTo: object) return Where<O>(keyPath._kvcKeyPathString!, isEqualTo: object)
} }
/**
Creates a `Where` clause by comparing if a property is equal to a value
```
let dog = dataStack.fetchOne(From<Dog>().where(\.master == john))
```
*/
public func == <O: ObjectRepresentation, D: NSManagedObject>(_ keyPath: KeyPath<O, Optional<D>>, _ object: O?) -> Where<O> where O.ObjectType: NSManagedObject {
return Where<O>(keyPath._kvcKeyPathString!, isEqualTo: object?.cs_toRaw())
}
/** /**
Creates a `Where` clause by comparing if a property is not equal to a value Creates a `Where` clause by comparing if a property is not equal to a value
``` ```
@@ -314,6 +347,17 @@ public func != <O: NSManagedObject, D: NSManagedObject>(_ keyPath: KeyPath<O, Op
return !Where<O>(keyPath._kvcKeyPathString!, isEqualTo: object) return !Where<O>(keyPath._kvcKeyPathString!, isEqualTo: object)
} }
/**
Creates a `Where` clause by comparing if a property is not equal to a value
```
let dog = dataStack.fetchOne(From<Dog>().where(\.master != john))
```
*/
public func != <O: ObjectRepresentation, D: NSManagedObject>(_ keyPath: KeyPath<O, Optional<D>>, _ object: O?) -> Where<O> where O.ObjectType: NSManagedObject {
return !Where<O>(keyPath._kvcKeyPathString!, isEqualTo: object?.cs_toRaw())
}
/** /**
Creates a `Where` clause by checking if a sequence contains a value of a property Creates a `Where` clause by checking if a sequence contains a value of a property
``` ```
@@ -395,6 +439,155 @@ public func ~= <O, V, S: Sequence>(_ sequence: S, _ keyPath: KeyPath<O, FieldCon
} }
// MARK: - KeyPath where Root: CoreStoreObject, Value: FieldContainer<Root>.Stored<QueryableAttributeType & Comparable>
/**
Creates a `Where` clause by comparing if a property is less than a value
```
let person = dataStack.fetchOne(From<Person>().where(\.$age < 20))
```
*/
public func < <O, V: Comparable>(_ keyPath: KeyPath<O, FieldContainer<O>.Stored<V>>, _ value: V) -> Where<O> {
return Where<O>("%K < %@", O.meta[keyPath: keyPath].keyPath, value.cs_toFieldStoredNativeType() as! V.FieldStoredNativeType)
}
/**
Creates a `Where` clause by comparing if a property is less than a value
```
let person = dataStack.fetchOne(From<Person>().where(\.$age < 20))
```
*/
public func < <O, V: FieldOptionalType>(_ keyPath: KeyPath<O, FieldContainer<O>.Stored<V>>, _ value: V) -> Where<O> where V.Wrapped: Comparable {
return Where<O>("%K < %@", O.meta[keyPath: keyPath].keyPath, value.cs_toFieldStoredNativeType() as! V.FieldStoredNativeType)
}
/**
Creates a `Where` clause by comparing if a property is greater than a value
```
let person = dataStack.fetchOne(From<Person>().where(\.$age > 20))
```
*/
public func > <O, V: Comparable>(_ keyPath: KeyPath<O, FieldContainer<O>.Stored<V>>, _ value: V) -> Where<O> {
return Where<O>("%K > %@", O.meta[keyPath: keyPath].keyPath, value.cs_toFieldStoredNativeType() as! V.FieldStoredNativeType)
}
/**
Creates a `Where` clause by comparing if a property is greater than a value
```
let person = dataStack.fetchOne(From<Person>().where(\.$age > 20))
```
*/
public func > <O, V: FieldOptionalType>(_ keyPath: KeyPath<O, FieldContainer<O>.Stored<V>>, _ value: V) -> Where<O> where V.Wrapped: Comparable {
return Where<O>("%K > %@", O.meta[keyPath: keyPath].keyPath, value.cs_toFieldStoredNativeType() as! V.FieldStoredNativeType)
}
/**
Creates a `Where` clause by comparing if a property is less than or equal to a value
```
let person = dataStack.fetchOne(From<Person>().where(\.$age <= 20))
```
*/
public func <= <O, V: Comparable>(_ keyPath: KeyPath<O, FieldContainer<O>.Stored<V>>, _ value: V) -> Where<O> {
return Where<O>("%K <= %@", O.meta[keyPath: keyPath].keyPath, value.cs_toFieldStoredNativeType() as! V.FieldStoredNativeType)
}
/**
Creates a `Where` clause by comparing if a property is less than or equal to a value
```
let person = dataStack.fetchOne(From<Person>().where(\.$age <= 20))
```
*/
public func <= <O, V: FieldOptionalType>(_ keyPath: KeyPath<O, FieldContainer<O>.Stored<V>>, _ value: V) -> Where<O> where V.Wrapped: Comparable {
return Where<O>("%K <= %@", O.meta[keyPath: keyPath].keyPath, value.cs_toFieldStoredNativeType() as! V.FieldStoredNativeType)
}
/**
Creates a `Where` clause by comparing if a property is greater than or equal to a value
```
let person = dataStack.fetchOne(From<Person>().where(\.$age >= 20))
```
*/
public func >= <O, V: Comparable>(_ keyPath: KeyPath<O, FieldContainer<O>.Stored<V>>, _ value: V) -> Where<O> {
return Where<O>("%K >= %@", O.meta[keyPath: keyPath].keyPath, value.cs_toFieldStoredNativeType() as! V.FieldStoredNativeType)
}
/**
Creates a `Where` clause by comparing if a property is greater than or equal to a value
```
let person = dataStack.fetchOne(From<Person>().where(\.$age >= 20))
```
*/
public func >= <O, V: FieldOptionalType>(_ keyPath: KeyPath<O, FieldContainer<O>.Stored<V>>, _ value: V) -> Where<O> where V.Wrapped: Comparable {
return Where<O>("%K >= %@", O.meta[keyPath: keyPath].keyPath, value.cs_toFieldStoredNativeType() as! V.FieldStoredNativeType)
}
// MARK: - KeyPath where Root: CoreStoreObject, Value: FieldContainer<Root>.Relationship<CoreStoreObject>
/**
Creates a `Where` clause by comparing if a property is equal to a value
```
let dog = dataStack.fetchOne(From<Dog>().where(\.$master == john))
```
*/
public func == <O, D: FieldRelationshipToOneType>(_ keyPath: KeyPath<O, FieldContainer<O>.Relationship<D>>, _ object: D.DestinationObjectType?) -> Where<O> {
return Where<O>(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<Dog>().where(\.master == john))
```
*/
public func == <O, D: FieldRelationshipToOneType, R: ObjectRepresentation>(_ keyPath: KeyPath<O, FieldContainer<O>.Relationship<D>>, _ object: R?) -> Where<O> where D.DestinationObjectType == R.ObjectType {
return Where<O>(O.meta[keyPath: keyPath].keyPath, isEqualTo: object?.objectID())
}
/**
Creates a `Where` clause by comparing if a property is not equal to a value
```
let dog = dataStack.fetchOne(From<Dog>().where(\.$master != john))
```
*/
public func != <O, D: FieldRelationshipToOneType>(_ keyPath: KeyPath<O, FieldContainer<O>.Relationship<D>>, _ object: D.DestinationObjectType?) -> Where<O> {
return !Where<O>(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<Dog>().where(\.master != john))
```
*/
public func != <O, D: FieldRelationshipToOneType, R: ObjectRepresentation>(_ keyPath: KeyPath<O, FieldContainer<O>.Relationship<D>>, _ object: R?) -> Where<O> where D.DestinationObjectType == R.ObjectType {
return !Where<O>(O.meta[keyPath: keyPath].keyPath, isEqualTo: object?.objectID())
}
/**
Creates a `Where` clause by checking if a sequence contains a value of a property
```
let dog = dataStack.fetchOne(From<Dog>().where([john, bob, joe] ~= \.$master))
```
*/
public func ~= <O, D: FieldRelationshipToOneType, S: Sequence>(_ sequence: S, _ keyPath: KeyPath<O, FieldContainer<O>.Relationship<D>>) -> Where<O> where S.Iterator.Element == D.DestinationObjectType {
return Where<O>(O.meta[keyPath: keyPath].keyPath, isMemberOf: sequence)
}
// MARK: - KeyPath where Root: CoreStoreObject, Value: ValueContainer<Root>.Required<QueryableAttributeType & Equatable> // MARK: - KeyPath where Root: CoreStoreObject, Value: ValueContainer<Root>.Required<QueryableAttributeType & Equatable>
/** /**
@@ -469,17 +662,6 @@ public func ~= <O, V, S: Sequence>(_ sequence: S, _ keyPath: KeyPath<O, ValueCon
// MARK: - KeyPath where Root: CoreStoreObject, Value: ValueContainer<Root>.Required<QueryableAttributeType & Comparable> // MARK: - KeyPath where Root: CoreStoreObject, Value: ValueContainer<Root>.Required<QueryableAttributeType & Comparable>
/**
Creates a `Where` clause by comparing if a property is less than a value
```
let person = dataStack.fetchOne(From<Person>().where(\.$age < 20))
```
*/
public func < <O, V: Comparable>(_ keyPath: KeyPath<O, FieldContainer<O>.Stored<V>>, _ value: V) -> Where<O> {
return Where<O>("%K < %@", O.meta[keyPath: keyPath].keyPath, value.cs_toFieldStoredNativeType() as! V.FieldStoredNativeType)
}
/** /**
Creates a `Where` clause by comparing if a property is less than a value Creates a `Where` clause by comparing if a property is less than a value
``` ```
@@ -491,17 +673,6 @@ public func < <O, V: Comparable>(_ keyPath: KeyPath<O, ValueContainer<O>.Require
return Where<O>("%K < %@", O.meta[keyPath: keyPath].keyPath, value.cs_toQueryableNativeType()) return Where<O>("%K < %@", O.meta[keyPath: keyPath].keyPath, value.cs_toQueryableNativeType())
} }
/**
Creates a `Where` clause by comparing if a property is greater than a value
```
let person = dataStack.fetchOne(From<Person>().where(\.$age > 20))
```
*/
public func > <O, V: Comparable>(_ keyPath: KeyPath<O, FieldContainer<O>.Stored<V>>, _ value: V) -> Where<O> {
return Where<O>("%K > %@", O.meta[keyPath: keyPath].keyPath, value.cs_toFieldStoredNativeType() as! V.FieldStoredNativeType)
}
/** /**
Creates a `Where` clause by comparing if a property is greater than a value Creates a `Where` clause by comparing if a property is greater than a value
``` ```
@@ -513,17 +684,6 @@ public func > <O, V: Comparable>(_ keyPath: KeyPath<O, ValueContainer<O>.Require
return Where<O>("%K > %@", O.meta[keyPath: keyPath].keyPath, value.cs_toQueryableNativeType()) return Where<O>("%K > %@", O.meta[keyPath: keyPath].keyPath, value.cs_toQueryableNativeType())
} }
/**
Creates a `Where` clause by comparing if a property is less than or equal to a value
```
let person = dataStack.fetchOne(From<Person>().where(\.$age <= 20))
```
*/
public func <= <O, V: Comparable>(_ keyPath: KeyPath<O, FieldContainer<O>.Stored<V>>, _ value: V) -> Where<O> {
return Where<O>("%K <= %@", O.meta[keyPath: keyPath].keyPath, value.cs_toFieldStoredNativeType() as! V.FieldStoredNativeType)
}
/** /**
Creates a `Where` clause by comparing if a property is less than or equal to a value Creates a `Where` clause by comparing if a property is less than or equal to a value
``` ```
@@ -535,17 +695,6 @@ public func <= <O, V: Comparable>(_ keyPath: KeyPath<O, ValueContainer<O>.Requir
return Where<O>("%K <= %@", O.meta[keyPath: keyPath].keyPath, value.cs_toQueryableNativeType()) return Where<O>("%K <= %@", O.meta[keyPath: keyPath].keyPath, value.cs_toQueryableNativeType())
} }
/**
Creates a `Where` clause by comparing if a property is greater than or equal to a value
```
let person = dataStack.fetchOne(From<Person>().where(\.$age >= 20))
```
*/
public func >= <O, V: Comparable>(_ keyPath: KeyPath<O, FieldContainer<O>.Stored<V>>, _ value: V) -> Where<O> {
return Where<O>("%K >= %@", O.meta[keyPath: keyPath].keyPath, value.cs_toFieldStoredNativeType() as! V.FieldStoredNativeType)
}
/** /**
Creates a `Where` clause by comparing if a property is greater than or equal to a value Creates a `Where` clause by comparing if a property is greater than or equal to a value
``` ```
@@ -560,17 +709,6 @@ public func >= <O, V: Comparable>(_ keyPath: KeyPath<O, ValueContainer<O>.Requir
// MARK: - KeyPath where Root: CoreStoreObject, Value: ValueContainer<Root>.Optional<QueryableAttributeType & Comparable> // MARK: - KeyPath where Root: CoreStoreObject, Value: ValueContainer<Root>.Optional<QueryableAttributeType & Comparable>
/**
Creates a `Where` clause by comparing if a property is less than a value
```
let person = dataStack.fetchOne(From<Person>().where(\.$age < 20))
```
*/
public func < <O, V: FieldOptionalType>(_ keyPath: KeyPath<O, FieldContainer<O>.Stored<V>>, _ value: V) -> Where<O> where V.Wrapped: Comparable {
return Where<O>("%K < %@", O.meta[keyPath: keyPath].keyPath, value.cs_toFieldStoredNativeType() as! V.FieldStoredNativeType)
}
/** /**
Creates a `Where` clause by comparing if a property is less than a value Creates a `Where` clause by comparing if a property is less than a value
``` ```
@@ -589,17 +727,6 @@ public func < <O, V>(_ keyPath: KeyPath<O, ValueContainer<O>.Optional<V>>, _ val
} }
} }
/**
Creates a `Where` clause by comparing if a property is greater than a value
```
let person = dataStack.fetchOne(From<Person>().where(\.$age > 20))
```
*/
public func > <O, V: FieldOptionalType>(_ keyPath: KeyPath<O, FieldContainer<O>.Stored<V>>, _ value: V) -> Where<O> where V.Wrapped: Comparable {
return Where<O>("%K > %@", O.meta[keyPath: keyPath].keyPath, value.cs_toFieldStoredNativeType() as! V.FieldStoredNativeType)
}
/** /**
Creates a `Where` clause by comparing if a property is greater than a value Creates a `Where` clause by comparing if a property is greater than a value
``` ```
@@ -618,17 +745,6 @@ public func > <O, V>(_ keyPath: KeyPath<O, ValueContainer<O>.Optional<V>>, _ val
} }
} }
/**
Creates a `Where` clause by comparing if a property is less than or equal to a value
```
let person = dataStack.fetchOne(From<Person>().where(\.$age <= 20))
```
*/
public func <= <O, V: FieldOptionalType>(_ keyPath: KeyPath<O, FieldContainer<O>.Stored<V>>, _ value: V) -> Where<O> where V.Wrapped: Comparable {
return Where<O>("%K <= %@", O.meta[keyPath: keyPath].keyPath, value.cs_toFieldStoredNativeType() as! V.FieldStoredNativeType)
}
/** /**
Creates a `Where` clause by comparing if a property is less than or equal to a value Creates a `Where` clause by comparing if a property is less than or equal to a value
``` ```
@@ -647,17 +763,6 @@ public func <= <O, V>(_ keyPath: KeyPath<O, ValueContainer<O>.Optional<V>>, _ va
} }
} }
/**
Creates a `Where` clause by comparing if a property is greater than or equal to a value
```
let person = dataStack.fetchOne(From<Person>().where(\.$age >= 20))
```
*/
public func >= <O, V: FieldOptionalType>(_ keyPath: KeyPath<O, FieldContainer<O>.Stored<V>>, _ value: V) -> Where<O> where V.Wrapped: Comparable {
return Where<O>("%K >= %@", O.meta[keyPath: keyPath].keyPath, value.cs_toFieldStoredNativeType() as! V.FieldStoredNativeType)
}
/** /**
Creates a `Where` clause by comparing if a property is greater than or equal to a value Creates a `Where` clause by comparing if a property is greater than or equal to a value
``` ```
@@ -679,17 +784,6 @@ public func >= <O, V>(_ keyPath: KeyPath<O, ValueContainer<O>.Optional<V>>, _ va
// MARK: - KeyPath where Root: CoreStoreObject, Value: RelationshipContainer<Root>.ToOne<CoreStoreObject> // MARK: - KeyPath where Root: CoreStoreObject, Value: RelationshipContainer<Root>.ToOne<CoreStoreObject>
/**
Creates a `Where` clause by comparing if a property is equal to a value
```
let dog = dataStack.fetchOne(From<Dog>().where(\.$master == john))
```
*/
public func == <O, D: FieldRelationshipToOneType>(_ keyPath: KeyPath<O, FieldContainer<O>.Relationship<D>>, _ object: D.DestinationObjectType?) -> Where<O> {
return Where<O>(O.meta[keyPath: keyPath].keyPath, isEqualTo: object)
}
/** /**
Creates a `Where` clause by comparing if a property is equal to a value Creates a `Where` clause by comparing if a property is equal to a value
``` ```
@@ -712,17 +806,6 @@ public func == <O, D>(_ keyPath: KeyPath<O, RelationshipContainer<O>.ToOne<D>>,
return Where<O>(O.meta[keyPath: keyPath].keyPath, isEqualTo: object) return Where<O>(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<Dog>().where(\.$master != john))
```
*/
public func != <O, D: FieldRelationshipToOneType>(_ keyPath: KeyPath<O, FieldContainer<O>.Relationship<D>>, _ object: D.DestinationObjectType?) -> Where<O> {
return !Where<O>(O.meta[keyPath: keyPath].keyPath, isEqualTo: object)
}
/** /**
Creates a `Where` clause by comparing if a property is not equal to a value Creates a `Where` clause by comparing if a property is not equal to a value
``` ```
@@ -745,17 +828,6 @@ public func != <O, D>(_ keyPath: KeyPath<O, RelationshipContainer<O>.ToOne<D>>,
return !Where<O>(O.meta[keyPath: keyPath].keyPath, isEqualTo: object) return !Where<O>(O.meta[keyPath: keyPath].keyPath, isEqualTo: object)
} }
/**
Creates a `Where` clause by checking if a sequence contains a value of a property
```
let dog = dataStack.fetchOne(From<Dog>().where([john, bob, joe] ~= \.$master))
```
*/
public func ~= <O, D: FieldRelationshipToOneType, S: Sequence>(_ sequence: S, _ keyPath: KeyPath<O, FieldContainer<O>.Relationship<D>>) -> Where<O> where S.Iterator.Element == D.DestinationObjectType {
return Where<O>(O.meta[keyPath: keyPath].keyPath, isMemberOf: sequence)
}
/** /**
Creates a `Where` clause by checking if a sequence contains a value of a property Creates a `Where` clause by checking if a sequence contains a value of a property
``` ```

View File

@@ -71,7 +71,7 @@ public struct ListSnapshot<O: DynamicObject>: RandomAccessCollection, Hashable {
public subscript(index: Index) -> ObjectPublisher<O> { public subscript(index: Index) -> ObjectPublisher<O> {
let context = self.context! let context = self.context!
let itemID = self.diffableSnapshot.itemIdentifiers[index] let itemID = self.diffableSnapshot.itemIdentifier(atAllItemsIndex: index)!
return context.objectPublisher(objectID: itemID) return context.objectPublisher(objectID: itemID)
} }
@@ -83,16 +83,13 @@ public struct ListSnapshot<O: DynamicObject>: RandomAccessCollection, Hashable {
*/ */
public subscript(safeIndex index: Index) -> ObjectPublisher<O>? { public subscript(safeIndex index: Index) -> ObjectPublisher<O>? {
guard let context = self.context else { guard
let context = self.context,
let itemID = self.diffableSnapshot.itemIdentifier(atAllItemsIndex: index)
else {
return nil return nil
} }
let itemIDs = self.diffableSnapshot.itemIdentifiers
guard itemIDs.indices.contains(index) else {
return nil
}
let itemID = itemIDs[index]
return context.objectPublisher(objectID: itemID) return context.objectPublisher(objectID: itemID)
} }
@@ -597,20 +594,74 @@ public struct ListSnapshot<O: DynamicObject>: RandomAccessCollection, Hashable {
self.diffableSnapshot.reloadSections(sectionIDs) self.diffableSnapshot.reloadSections(sectionIDs)
} }
// MARK: RandomAccessCollection // MARK: RandomAccessCollection
public var startIndex: Index { public var startIndex: Index {
return self.diffableSnapshot.itemIdentifiers.startIndex return 0
} }
public var endIndex: Index { public var endIndex: Index {
return self.diffableSnapshot.itemIdentifiers.endIndex 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: Index, offsetBy distance: Int) -> Index {
return i + distance
}
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<Index>) -> ArraySlice<Element> {
guard let context = self.context else {
return .init()
}
let itemIDs = self.diffableSnapshot.itemIdentifiers(atAllItemsBounds: bounds)
return ArraySlice(itemIDs.map(context.objectPublisher(objectID:)))
}
// MARK: Sequence // MARK: Sequence

View File

@@ -40,12 +40,7 @@ import CoreData
Observers registered via `addObserver(_:)` are not retained. `ObjectMonitor` only keeps a `weak` reference to all observers, thus keeping itself free from retain-cycles. Observers registered via `addObserver(_:)` are not retained. `ObjectMonitor` only keeps a `weak` reference to all observers, thus keeping itself free from retain-cycles.
*/ */
@available(macOS 10.12, *) @available(macOS 10.12, *)
public final class ObjectMonitor<O: DynamicObject>: Equatable { public final class ObjectMonitor<O: DynamicObject>: Hashable, ObjectRepresentation {
/**
The object type represented by this `ObjectMonitor`
*/
public typealias ObjectType = O
/** /**
Returns the `DynamicObject` instance being observed, or `nil` if the object was already deleted. Returns the `DynamicObject` instance being observed, or `nil` if the object was already deleted.
@@ -156,6 +151,51 @@ public final class ObjectMonitor<O: DynamicObject>: Equatable {
} }
// MARK: AnyObjectRepresentation
public func objectID() -> O.ObjectID {
return self.id
}
public func cs_dataStack() -> DataStack? {
return self.context.parentStack
}
// MARK: ObjectRepresentation
public typealias ObjectType = O
public func asPublisher(in dataStack: DataStack) -> ObjectPublisher<O> {
return dataStack.unsafeContext().objectPublisher(objectID: self.id)
}
public func asReadOnly(in dataStack: DataStack) -> O? {
return dataStack.unsafeContext().fetchExisting(self.id)
}
public func asEditable(in transaction: BaseDataTransaction) -> O? {
return transaction.unsafeContext().fetchExisting(self.id)
}
public func asSnapshot(in dataStack: DataStack) -> ObjectSnapshot<O>? {
let context = dataStack.unsafeContext()
return ObjectSnapshot<O>(objectID: self.id, context: context)
}
public func asSnapshot(in transaction: BaseDataTransaction) -> ObjectSnapshot<O>? {
let context = transaction.unsafeContext()
return ObjectSnapshot<O>(objectID: self.id, context: context)
}
// MARK: Internal // MARK: Internal
internal init(objectID: O.ObjectID, context: NSManagedObjectContext) { internal init(objectID: O.ObjectID, context: NSManagedObjectContext) {

View File

@@ -125,15 +125,23 @@ public final class ObjectPublisher<O: DynamicObject>: ObjectRepresentation, Hash
} }
// MARK: ObjectRepresentation // MARK: AnyObjectRepresentation
public typealias ObjectType = O
public func objectID() -> O.ObjectID { public func objectID() -> O.ObjectID {
return self.id return self.id
} }
public func cs_dataStack() -> DataStack? {
return self.context.parentStack
}
// MARK: ObjectRepresentation
public typealias ObjectType = O
public func asPublisher(in dataStack: DataStack) -> ObjectPublisher<O> { public func asPublisher(in dataStack: DataStack) -> ObjectPublisher<O> {
let context = dataStack.unsafeContext() let context = dataStack.unsafeContext()
@@ -449,20 +457,18 @@ extension ObjectPublisher where O: NSManagedObject {
/** /**
Returns the value for the property identified by a given key. Returns the value for the property identified by a given key.
*/ */
@available(*, unavailable, message: "KeyPaths accessed from @dynamicMemberLookup types can't generate KVC keys yet (https://bugs.swift.org/browse/SR-11351)") public subscript<V: AllowedObjectiveCKeyPathValue>(dynamicMember member: KeyPath<O, V>) -> V! {
public subscript<V: AllowedObjectiveCKeyPathValue>(dynamicMember member: KeyPath<O, V>) -> V {
fatalError() return self.snapshot?[dynamicMember: member]
// return self.snapshot[dynamicMember: member]
} }
/**
Returns the value for the property identified by a given key. // MARK: Deprecated
*/
@available(*, deprecated, message: "Accessing the property directly now works")
public func value<V: AllowedObjectiveCKeyPathValue>(forKeyPath keyPath: KeyPath<O, V>) -> V! { public func value<V: AllowedObjectiveCKeyPathValue>(forKeyPath keyPath: KeyPath<O, V>) -> V! {
let key = String(keyPath: keyPath) return self[dynamicMember: keyPath]
return self.snapshot?.dictionaryForValues()[key] as! V?
} }
} }

100
Sources/ObjectReader.swift Normal file
View File

@@ -0,0 +1,100 @@
//
// ListState.swift
// CoreStore
//
// Created by John Rommel Estropia on 2020/12/26.
// Copyright © 2020 John Rommel Estropia. All rights reserved.
//
#if canImport(Combine) && canImport(SwiftUI)
import Combine
import SwiftUI
// MARK: - ObjectReader
@available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, *)
public struct ObjectReader<Object: DynamicObject, Content: View, Placeholder: View>: View {
// MARK: Internal
public init(
_ objectPublisher: ObjectPublisher<Object>?,
@ViewBuilder content: @escaping (ObjectSnapshot<Object>) -> Content,
@ViewBuilder placeholder: @escaping () -> Placeholder
) {
self.objectPublisher = .init(
objectPublisher.flatMap {
guard let dataStack = $0.cs_dataStack() else {
return nil
}
return $0.asPublisher(in: dataStack)
}
)
self.content = content
self.placeholder = placeholder
}
public init(
_ objectPublisher: ObjectPublisher<Object>?,
@ViewBuilder content: @escaping (ObjectSnapshot<Object>) -> Content
) where Placeholder == EmptyView {
self.init(
objectPublisher,
content: content,
placeholder: EmptyView.init
)
}
// MARK: View
public var body: some View {
if let snapshot = self.objectPublisher.wrappedValue?.snapshot {
self.content(snapshot)
}
else {
self.placeholder()
}
}
// MARK: Private
@ObservedObject
private var objectPublisher: OptionalObservedObject<ObjectPublisher<Object>>
private let content: (ObjectSnapshot<Object>) -> Content
private let placeholder: () -> Placeholder
// MARK: - OptionalObservedObject
fileprivate final class OptionalObservedObject<T: ObservableObject>: ObservableObject where ObservableObjectPublisher == T.ObjectWillChangePublisher {
// MARK: Internal
let wrappedValue: T?
init(_ wrappedValue: T?) {
self.wrappedValue = wrappedValue
self.objectWillChange = wrappedValue.map(\.objectWillChange) ?? .init()
}
// MARK: ObservableObject
let objectWillChange: ObservableObjectPublisher
}
}
#endif

View File

@@ -26,23 +26,37 @@
import CoreData import CoreData
// MARK: - AnyObjectRepresentation
/**
Used internally by CoreStore. Do not conform to directly.
*/
public protocol AnyObjectRepresentation {
/**
The internal ID for the object.
*/
func objectID() -> NSManagedObjectID
/**
Used internally by CoreStore. Do not call directly.
*/
func cs_dataStack() -> DataStack?
}
// MARK - ObjectRepresentation // MARK - ObjectRepresentation
/** /**
An object that acts as interfaces for `CoreStoreObject`s or `NSManagedObject`s An object that acts as interfaces for `CoreStoreObject`s or `NSManagedObject`s
*/ */
public protocol ObjectRepresentation { public protocol ObjectRepresentation: AnyObjectRepresentation {
/** /**
The object type represented by this protocol The object type represented by this protocol
*/ */
associatedtype ObjectType: DynamicObject associatedtype ObjectType: DynamicObject
/**
The internal ID for the object.
*/
func objectID() -> ObjectType.ObjectID
/** /**
An instance that may be observed for object changes. An instance that may be observed for object changes.
*/ */
@@ -96,14 +110,22 @@ extension DynamicObject where Self: ObjectRepresentation {
.managedObjectContext .managedObjectContext
.flatMap({ ObjectSnapshot<Self>(objectID: self.cs_id(), context: $0) }) .flatMap({ ObjectSnapshot<Self>(objectID: self.cs_id(), context: $0) })
} }
// MARK: ObjectRepresentation // MARK: AnyObjectRepresentation
public func objectID() -> Self.ObjectID { public func objectID() -> Self.ObjectID {
return self.cs_id() return self.cs_id()
} }
public func cs_dataStack() -> DataStack? {
return self.cs_toRaw().managedObjectContext?.parentStack
}
// MARK: ObjectRepresentation
public func asPublisher(in dataStack: DataStack) -> ObjectPublisher<Self> { public func asPublisher(in dataStack: DataStack) -> ObjectPublisher<Self> {

View File

@@ -48,17 +48,25 @@ public struct ObjectSnapshot<O: DynamicObject>: ObjectRepresentation, Hashable {
return self.values return self.values
} }
// MARK: ObjectRepresentation
// MARK: AnyObjectRepresentation
public typealias ObjectType = O
public func objectID() -> O.ObjectID { public func objectID() -> O.ObjectID {
return self.id return self.id
} }
public func cs_dataStack() -> DataStack? {
return self.context.parentStack
}
// MARK: ObjectRepresentation
public typealias ObjectType = O
public func asPublisher(in dataStack: DataStack) -> ObjectPublisher<O> { public func asPublisher(in dataStack: DataStack) -> ObjectPublisher<O> {
let context = dataStack.unsafeContext() let context = dataStack.unsafeContext()
@@ -93,7 +101,7 @@ public struct ObjectSnapshot<O: DynamicObject>: ObjectRepresentation, Hashable {
public static func == (_ lhs: Self, _ rhs: Self) -> Bool { public static func == (_ lhs: Self, _ rhs: Self) -> Bool {
return lhs.id == rhs.id return lhs.id == rhs.id
&& lhs.valuesRef == rhs.valuesRef && (lhs.generation == rhs.generation || lhs.valuesRef == rhs.valuesRef)
} }
@@ -117,18 +125,27 @@ public struct ObjectSnapshot<O: DynamicObject>: ObjectRepresentation, Hashable {
self.id = objectID self.id = objectID
self.context = context self.context = context
self.values = values self.values = values
self.generation = .init()
} }
// MARK: FilePrivate // MARK: FilePrivate
fileprivate var values: [String: Any] fileprivate var values: [String: Any] {
didSet {
self.generation = .init()
}
}
// MARK: Private // MARK: Private
private let id: O.ObjectID private let id: O.ObjectID
private let context: NSManagedObjectContext private let context: NSManagedObjectContext
private var generation: UUID
private var valuesRef: NSDictionary { private var valuesRef: NSDictionary {
@@ -144,29 +161,33 @@ extension ObjectSnapshot where O: NSManagedObject {
/** /**
Returns the value for the property identified by a given key. Returns the value for the property identified by a given key.
*/ */
@available(*, unavailable, message: "KeyPaths accessed from @dynamicMemberLookup types can't generate KVC keys yet (https://bugs.swift.org/browse/SR-11351)") public subscript<V: AllowedObjectiveCKeyPathValue>(dynamicMember member: KeyPath<O, V>) -> V! {
public subscript<V: AllowedObjectiveCKeyPathValue>(dynamicMember member: KeyPath<O, V>) -> V {
let key = String(keyPath: member) get {
return self.values[key] as! V
let key = String(keyPath: member)
return self.values[key] as! V?
}
set {
let key = String(keyPath: member)
self.values[key] = newValue
}
} }
/**
Returns the value for the property identified by a given key. // MARK: Deprecated
*/
@available(*, deprecated, message: "Accessing the property directly now works")
public func value<V: AllowedObjectiveCKeyPathValue>(forKeyPath keyPath: KeyPath<O, V>) -> V! { public func value<V: AllowedObjectiveCKeyPathValue>(forKeyPath keyPath: KeyPath<O, V>) -> V! {
let key = String(keyPath: keyPath) return self[dynamicMember: keyPath]
return self.values[key] as! V?
} }
/** @available(*, deprecated, message: "Mutating the property directly now works")
Mutates the value for the property identified by a given key.
*/
public mutating func setValue<V: AllowedObjectiveCKeyPathValue>(_ value: V!, forKeyPath keyPath: KeyPath<O, V>) { public mutating func setValue<V: AllowedObjectiveCKeyPathValue>(_ value: V!, forKeyPath keyPath: KeyPath<O, V>) {
let key = String(keyPath: keyPath) self[dynamicMember: keyPath] = value
self.values[key] = value
} }
} }

View File

@@ -469,7 +469,7 @@ extension Where where O: CoreStoreObject {
- parameter keyPath: the keyPath to compare with - parameter keyPath: the keyPath to compare with
- parameter null: the arguments for the `==` operator - parameter null: the arguments for the `==` operator
*/ */
public init<V>(_ keyPath: KeyPath<O, ValueContainer<O>.Optional<V>>, isEqualTo null: Void?) { public init<V>(_ keyPath: KeyPath<O, FieldContainer<O>.Stored<V>>, isEqualTo null: Void?) {
self.init(O.meta[keyPath: keyPath].keyPath, isEqualTo: null) self.init(O.meta[keyPath: keyPath].keyPath, isEqualTo: null)
} }
@@ -480,11 +480,44 @@ extension Where where O: CoreStoreObject {
- parameter keyPath: the keyPath to compare with - parameter keyPath: the keyPath to compare with
- parameter null: the arguments for the `==` operator - parameter null: the arguments for the `==` operator
*/ */
public init<D>(_ keyPath: KeyPath<O, RelationshipContainer<O>.ToOne<D>>, isEqualTo null: Void?) { public init<V: FieldRelationshipToOneType>(_ keyPath: KeyPath<O, FieldContainer<O>.Relationship<V>>, isEqualTo null: Void?) {
self.init(O.meta[keyPath: keyPath].keyPath, isEqualTo: null) self.init(O.meta[keyPath: keyPath].keyPath, isEqualTo: null)
} }
/**
Initializes a `Where` clause that compares membership
- parameter keyPath: the keyPath to compare with
- parameter list: the sequence to check membership of
*/
public init<V, S: Sequence>(_ keyPath: KeyPath<O, FieldContainer<O>.Stored<V>>, isMemberOf list: S) where S.Iterator.Element == V {
self.init(O.meta[keyPath: keyPath].keyPath, isMemberOf: list)
}
/**
Initializes a `Where` clause that compares membership
- parameter keyPath: the keyPath to compare with
- parameter list: the sequence to check membership of
*/
public init<V: FieldRelationshipToOneType, S: Sequence>(_ keyPath: KeyPath<O, FieldContainer<O>.Relationship<V>>, isMemberOf list: S) where S.Iterator.Element == V.DestinationObjectType {
self.init(O.meta[keyPath: keyPath].keyPath, isMemberOf: list)
}
/**
Initializes a `Where` clause that compares membership
- parameter keyPath: the keyPath to compare with
- parameter list: the sequence to check membership of
*/
public init<V: FieldRelationshipToOneType, S: Sequence>(_ keyPath: KeyPath<O, FieldContainer<O>.Relationship<V>>, isMemberOf list: S) where S.Iterator.Element: NSManagedObjectID {
self.init(O.meta[keyPath: keyPath].keyPath, isMemberOf: list)
}
/** /**
Initializes a `Where` clause that compares equality Initializes a `Where` clause that compares equality
@@ -507,6 +540,28 @@ extension Where where O: CoreStoreObject {
self.init(O.meta[keyPath: keyPath].keyPath, isEqualTo: value) self.init(O.meta[keyPath: keyPath].keyPath, isEqualTo: value)
} }
/**
Initializes a `Where` clause that compares equality to `nil`
- parameter keyPath: the keyPath to compare with
- parameter null: the arguments for the `==` operator
*/
public init<V>(_ keyPath: KeyPath<O, ValueContainer<O>.Optional<V>>, isEqualTo null: Void?) {
self.init(O.meta[keyPath: keyPath].keyPath, isEqualTo: null)
}
/**
Initializes a `Where` clause that compares equality to `nil`
- parameter keyPath: the keyPath to compare with
- parameter null: the arguments for the `==` operator
*/
public init<D>(_ keyPath: KeyPath<O, RelationshipContainer<O>.ToOne<D>>, isEqualTo null: Void?) {
self.init(O.meta[keyPath: keyPath].keyPath, isEqualTo: null)
}
/** /**
Initializes a `Where` clause that compares equality Initializes a `Where` clause that compares equality