Merge branch 'develop' into swift3_develop

# Conflicts:
#	Cartfile
#	Carthage/Checkouts/GCDKit
#	CoreStore.podspec
#	CoreStore.xcodeproj/project.pbxproj
#	CoreStoreDemo/CoreStoreDemo.xcodeproj/project.pbxproj
#	CoreStoreTests/BaseTests/BaseTestCase.swift
#	CoreStoreTests/FromTests.swift
#	CoreStoreTests/GroupByTests.swift
#	CoreStoreTests/OrderByTests.swift
#	CoreStoreTests/StorageInterfaceTests.swift
#	CoreStoreTests/TweakTests.swift
#	CoreStoreTests/WhereTests.swift
#	README.md
#	Sources/Internal/CoreStoreFetchRequest.swift
#	Sources/Internal/NSManagedObjectContext+Querying.swift
#	Sources/Internal/NSManagedObjectModel+Setup.swift
#	Sources/Migrating/DataStack+Migration.swift
#	Sources/ObjectiveC/CSSQliteStore.swift
#	Sources/ObjectiveC/CSStorageInterface.swift
#	Sources/ObjectiveC/CoreStoreBridge.swift
#	Sources/Observing/ListMonitor.swift
#	Sources/Setup/DataStack.swift
#	Sources/Setup/StorageInterfaces/ICloudStore.swift
#	Sources/Setup/StorageInterfaces/LegacySQLiteStore.swift
#	Sources/Setup/StorageInterfaces/SQLiteStore.swift
#	Sources/Setup/StorageInterfaces/StorageInterface.swift
This commit is contained in:
John Estropia
2016-09-27 18:55:37 +09:00
21 changed files with 227 additions and 158 deletions

View File

@@ -1,5 +1,5 @@
language: objective-c language: objective-c
osx_image: xcode7.3 osx_image: xcode8
sudo: false sudo: false
git: git:
submodules: false submodules: false
@@ -10,16 +10,16 @@ env:
- LC_CTYPE=en_US.UTF-8 - LC_CTYPE=en_US.UTF-8
- LANG=en_US.UTF-8 - LANG=en_US.UTF-8
matrix: matrix:
- DESTINATION="OS=9.3,name=iPhone 6s" SCHEME="CoreStore iOS" SDK=iphonesimulator9.3 RUN_TESTS="YES" POD_LINT="NO" - DESTINATION="OS=10.0,name=iPhone 7" SCHEME="CoreStore iOS" SDK=iphonesimulator10.0 RUN_TESTS="YES" POD_LINT="NO"
- DESTINATION="OS=9.0,name=iPhone 6 Plus" SCHEME="CoreStore iOS" SDK=iphonesimulator9.3 RUN_TESTS="YES" POD_LINT="NO" - DESTINATION="OS=9.0,name=iPhone 6 Plus" SCHEME="CoreStore iOS" SDK=iphonesimulator10.0 RUN_TESTS="YES" POD_LINT="NO"
- DESTINATION="OS=8.4,name=iPhone 6" SCHEME="CoreStore iOS" SDK=iphonesimulator9.3 RUN_TESTS="YES" POD_LINT="NO" - DESTINATION="OS=8.4,name=iPhone 6" SCHEME="CoreStore iOS" SDK=iphonesimulator10.0 RUN_TESTS="YES" POD_LINT="NO"
- DESTINATION="OS=8.3,name=iPhone 5S" SCHEME="CoreStore iOS" SDK=iphonesimulator9.3 RUN_TESTS="YES" POD_LINT="NO" - DESTINATION="OS=8.3,name=iPhone 5S" SCHEME="CoreStore iOS" SDK=iphonesimulator10.0 RUN_TESTS="YES" POD_LINT="NO"
- DESTINATION="OS=8.2,name=iPhone 5" SCHEME="CoreStore iOS" SDK=iphonesimulator9.3 RUN_TESTS="YES" POD_LINT="NO" - DESTINATION="OS=8.2,name=iPhone 5" SCHEME="CoreStore iOS" SDK=iphonesimulator10.0 RUN_TESTS="YES" POD_LINT="NO"
- DESTINATION="OS=8.1,name=iPhone 4S" SCHEME="CoreStore iOS" SDK=iphonesimulator9.3 RUN_TESTS="YES" POD_LINT="YES" - DESTINATION="OS=8.1,name=iPhone 4S" SCHEME="CoreStore iOS" SDK=iphonesimulator10.0 RUN_TESTS="YES" POD_LINT="YES"
- DESTINATION="OS=8.1,name=iPhone 4S" SCHEME="CoreStore iOS7" SDK=iphonesimulator9.3 RUN_TESTS="YES" POD_LINT="YES" - DESTINATION="arch=x86_64" SCHEME="CoreStore OSX" SDK=macosx10.12 RUN_TESTS="YES" POD_LINT="NO"
- DESTINATION="arch=x86_64" SCHEME="CoreStore OSX" SDK=macosx10.11 RUN_TESTS="YES" POD_LINT="NO" - DESTINATION="OS=3.0,name=Apple Watch - 42mm" SCHEME="CoreStore watchOS" SDK=watchsimulator3.0 RUN_TESTS="NO" POD_LINT="NO"
- DESTINATION="OS=2.2,name=Apple Watch - 42mm" SCHEME="CoreStore watchOS" SDK=watchsimulator2.2 RUN_TESTS="NO" POD_LINT="NO" - DESTINATION="OS=2.2,name=Apple Watch - 42mm" SCHEME="CoreStore watchOS" SDK=watchsimulator3.0 RUN_TESTS="NO" POD_LINT="NO"
- DESTINATION="OS=9.2,name=Apple TV 1080p" SCHEME="CoreStore tvOS" SDK=appletvsimulator9.2 RUN_TESTS="YES" POD_LINT="NO" - DESTINATION="OS=9.2,name=Apple TV 1080p" SCHEME="CoreStore tvOS" SDK=appletvsimulator10.0 RUN_TESTS="YES" POD_LINT="NO"
before_install: before_install:
- gem install cocoapods --no-rdoc --no-ri --no-document --quiet - gem install cocoapods --no-rdoc --no-ri --no-document --quiet
- gem install xcpretty --no-rdoc --no-ri --no-document --quiet - gem install xcpretty --no-rdoc --no-ri --no-document --quiet
@@ -36,8 +36,8 @@ script:
xcodebuild -workspace CoreStore.xcworkspace -scheme "$SCHEME" -sdk "$SDK" -destination "$DESTINATION" -configuration Debug ONLY_ACTIVE_ARCH=NO clean test | xcpretty -c; xcodebuild -workspace CoreStore.xcworkspace -scheme "$SCHEME" -sdk "$SDK" -destination "$DESTINATION" -configuration Debug ONLY_ACTIVE_ARCH=NO clean test | xcpretty -c;
xcodebuild -workspace CoreStore.xcworkspace -scheme "$SCHEME" -sdk "$SDK" -destination "$DESTINATION" -configuration Release ONLY_ACTIVE_ARCH=NO clean test | xcpretty -c; xcodebuild -workspace CoreStore.xcworkspace -scheme "$SCHEME" -sdk "$SDK" -destination "$DESTINATION" -configuration Release ONLY_ACTIVE_ARCH=NO clean test | xcpretty -c;
fi fi
- xcodebuild -workspace "CoreStore.xcworkspace" -scheme "CoreStore iOS" -sdk "iphonesimulator9.3" -destination "OS=9.3,name=iPhone 6s" -configuration Debug ONLY_ACTIVE_ARCH=NO clean test | xcpretty -c; - xcodebuild -workspace "CoreStore.xcworkspace" -scheme "CoreStore iOS" -sdk "iphonesimulator10.0" -destination "OS=10.0,name=iPhone 7" -configuration Debug ONLY_ACTIVE_ARCH=NO clean test | xcpretty -c;
- xcodebuild -workspace "CoreStore.xcworkspace" -scheme "CoreStore iOS" -sdk "iphonesimulator9.3" -destination "OS=9.3,name=iPhone 6s" -configuration Release ONLY_ACTIVE_ARCH=NO clean test | xcpretty -c; - xcodebuild -workspace "CoreStore.xcworkspace" -scheme "CoreStore iOS" -sdk "iphonesimulator10.0" -destination "OS=10.0,name=iPhone 7" -configuration Release ONLY_ACTIVE_ARCH=NO clean test | xcpretty -c;
- if [ $POD_LINT == "YES" ]; then - if [ $POD_LINT == "YES" ]; then
pod lib lint --quick; pod lib lint --quick;
fi fi

View File

@@ -1,6 +1,6 @@
Pod::Spec.new do |s| Pod::Spec.new do |s|
s.name = "CoreStore" s.name = "CoreStore"
s.version = "2.0.4" s.version = "2.1.1"
s.license = "MIT" s.license = "MIT"
s.summary = "Unleashing the real power of Core Data with the elegance and safety of Swift" s.summary = "Unleashing the real power of Core Data with the elegance and safety of Swift"
s.homepage = "https://github.com/JohnEstropia/CoreStore" s.homepage = "https://github.com/JohnEstropia/CoreStore"
@@ -16,6 +16,7 @@ Pod::Spec.new do |s|
s.public_header_files = "Sources/**/*.h" s.public_header_files = "Sources/**/*.h"
s.frameworks = "Foundation", "CoreData" s.frameworks = "Foundation", "CoreData"
s.requires_arc = true s.requires_arc = true
s.pod_target_xcconfig = { 'OTHER_SWIFT_FLAGS' => '-D USE_FRAMEWORKS', s.pod_target_xcconfig = { 'OTHER_SWIFT_FLAGS[config=Debug]' => '-D USE_FRAMEWORKS -D DEBUG',
'OTHER_SWIFT_FLAGS[config=Release]' => '-D USE_FRAMEWORKS',
'GCC_PREPROCESSOR_DEFINITIONS' => 'USE_FRAMEWORKS=1' } 'GCC_PREPROCESSOR_DEFINITIONS' => 'USE_FRAMEWORKS=1' }
end end

View File

@@ -271,8 +271,6 @@
TargetAttributes = { TargetAttributes = {
B54AAD481AF4D26E00848AE0 = { B54AAD481AF4D26E00848AE0 = {
CreatedOnToolsVersion = 6.3; CreatedOnToolsVersion = 6.3;
DevelopmentTeam = 2JT32EJ5BH;
DevelopmentTeamName = "JOHNROMMEL ESTROPIA";
LastSwiftMigration = 0800; LastSwiftMigration = 0800;
}; };
}; };

View File

@@ -197,4 +197,41 @@
XCTAssertNil(sqliteError); XCTAssertNil(sqliteError);
} }
- (void)test_ThatTransactions_BridgeCorrectly {
[CSCoreStore
setDefaultStack:[[CSDataStack alloc]
initWithModelName:@"Model"
bundle:[NSBundle bundleForClass:[self class]]
versionChain:nil]];
[CSCoreStore
addInMemoryStorageAndWait:[CSInMemoryStore new]
error:nil];
{
CSUnsafeDataTransaction *transaction = [CSCoreStore beginUnsafe];
XCTAssertNotNil(transaction);
XCTAssert([transaction isKindOfClass:[CSUnsafeDataTransaction class]]);
}
{
XCTestExpectation *expectation = [self expectationWithDescription:@"sync"];
[CSCoreStore beginSynchronous:^(CSSynchronousDataTransaction * _Nonnull transaction) {
XCTAssertNotNil(transaction);
XCTAssert([transaction isKindOfClass:[CSSynchronousDataTransaction class]]);
[expectation fulfill];
}];
}
{
XCTestExpectation *expectation = [self expectationWithDescription:@"async"];
[CSCoreStore beginAsynchronous:^(CSAsynchronousDataTransaction * _Nonnull transaction) {
XCTAssertNotNil(transaction);
XCTAssert([transaction isKindOfClass:[CSAsynchronousDataTransaction class]]);
[expectation fulfill];
}];
}
[self waitForExpectationsWithTimeout:10 handler:nil];
}
@end @end

View File

@@ -74,33 +74,33 @@ final class FromTests: BaseTestCase {
let from = From<TestEntity1>() let from = From<TestEntity1>()
let request = NSFetchRequest<TestEntity1>() let request = CoreStoreFetchRequest()
let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext) let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext)
XCTAssertTrue(storesFound) XCTAssertTrue(storesFound)
XCTAssertNotNil(request.entity) XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores) XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName } let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertEqual(affectedConfigurations, ["PF_DEFAULT_CONFIGURATION_NAME"]) XCTAssertEqual(affectedConfigurations, ["PF_DEFAULT_CONFIGURATION_NAME"])
} }
do { do {
let from = From<TestEntity1>("Config1") let from = From<TestEntity1>("Config1")
let request = NSFetchRequest<TestEntity1>() let request = CoreStoreFetchRequest()
let storesFound = self.expectLogger([.logWarning]) { let storesFound = self.expectLogger([.logWarning]) {
from.applyToFetchRequest(request, context: dataStack.mainContext) from.applyToFetchRequest(request, context: dataStack.mainContext)
} }
XCTAssertFalse(storesFound) XCTAssertFalse(storesFound)
XCTAssertNotNil(request.entity) XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores) XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName } let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertTrue(affectedConfigurations.isEmpty) XCTAssertTrue(affectedConfigurations.isEmpty)
} }
} }
@@ -115,102 +115,102 @@ final class FromTests: BaseTestCase {
let from = From<TestEntity1>() let from = From<TestEntity1>()
let request = NSFetchRequest<TestEntity1>() let request = CoreStoreFetchRequest()
let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext) let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext)
XCTAssertTrue(storesFound) XCTAssertTrue(storesFound)
XCTAssertNotNil(request.entity) XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores) XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName } let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertEqual(affectedConfigurations, ["Config1"]) XCTAssertEqual(affectedConfigurations, ["Config1"])
} }
do { do {
let from = From<TestEntity1>("Config1") let from = From<TestEntity1>("Config1")
let request = NSFetchRequest<TestEntity1>() let request = CoreStoreFetchRequest()
let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext) let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext)
XCTAssertTrue(storesFound) XCTAssertTrue(storesFound)
XCTAssertNotNil(request.entity) XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores) XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName } let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertEqual(affectedConfigurations, ["Config1"]) XCTAssertEqual(affectedConfigurations, ["Config1"])
} }
do { do {
let from = From<TestEntity1>("Config2") let from = From<TestEntity1>("Config2")
let request = NSFetchRequest<TestEntity1>() let request = CoreStoreFetchRequest()
let storesFound = self.expectLogger([.logWarning]) { let storesFound = self.expectLogger([.logWarning]) {
from.applyToFetchRequest(request, context: dataStack.mainContext) from.applyToFetchRequest(request, context: dataStack.mainContext)
} }
XCTAssertFalse(storesFound) XCTAssertFalse(storesFound)
XCTAssertNotNil(request.entity) XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores) XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName } let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertTrue(affectedConfigurations.isEmpty) XCTAssertTrue(affectedConfigurations.isEmpty)
} }
do { do {
let from = From<TestEntity2>() let from = From<TestEntity2>()
let request = NSFetchRequest<TestEntity2>() let request = CoreStoreFetchRequest()
let storesFound = self.expectLogger([.logWarning]) { let storesFound = self.expectLogger([.logWarning]) {
from.applyToFetchRequest(request, context: dataStack.mainContext) from.applyToFetchRequest(request, context: dataStack.mainContext)
} }
XCTAssertFalse(storesFound) XCTAssertFalse(storesFound)
XCTAssertNotNil(request.entity) XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores) XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName } let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertTrue(affectedConfigurations.isEmpty) XCTAssertTrue(affectedConfigurations.isEmpty)
} }
do { do {
let from = From<TestEntity2>("Config1") let from = From<TestEntity2>("Config1")
let request = NSFetchRequest<TestEntity2>() let request = CoreStoreFetchRequest()
let storesFound = self.expectLogger([.logWarning]) { let storesFound = self.expectLogger([.logWarning]) {
from.applyToFetchRequest(request, context: dataStack.mainContext) from.applyToFetchRequest(request, context: dataStack.mainContext)
} }
XCTAssertFalse(storesFound) XCTAssertFalse(storesFound)
XCTAssertNotNil(request.entity) XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores) XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName } let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertTrue(affectedConfigurations.isEmpty) XCTAssertTrue(affectedConfigurations.isEmpty)
} }
do { do {
let from = From<TestEntity2>("Config2") let from = From<TestEntity2>("Config2")
let request = NSFetchRequest<TestEntity2>() let request = CoreStoreFetchRequest()
let storesFound = self.expectLogger([.logWarning]) { let storesFound = self.expectLogger([.logWarning]) {
from.applyToFetchRequest(request, context: dataStack.mainContext) from.applyToFetchRequest(request, context: dataStack.mainContext)
} }
XCTAssertFalse(storesFound) XCTAssertFalse(storesFound)
XCTAssertNotNil(request.entity) XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores) XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName } let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertTrue(affectedConfigurations.isEmpty) XCTAssertTrue(affectedConfigurations.isEmpty)
} }
} }
@@ -225,99 +225,99 @@ final class FromTests: BaseTestCase {
let from = From<TestEntity1>() let from = From<TestEntity1>()
let request = NSFetchRequest<TestEntity1>() let request = CoreStoreFetchRequest()
let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext) let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext)
XCTAssertTrue(storesFound) XCTAssertTrue(storesFound)
XCTAssertNotNil(request.entity) XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores) XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName } let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertEqual(Set(affectedConfigurations), ["PF_DEFAULT_CONFIGURATION_NAME", "Config1"] as Set) XCTAssertEqual(Set(affectedConfigurations), ["PF_DEFAULT_CONFIGURATION_NAME", "Config1"] as Set)
} }
do { do {
let from = From<TestEntity1>("Config1") let from = From<TestEntity1>("Config1")
let request = NSFetchRequest<TestEntity1>() let request = CoreStoreFetchRequest()
let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext) let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext)
XCTAssertTrue(storesFound) XCTAssertTrue(storesFound)
XCTAssertNotNil(request.entity) XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores) XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName } let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertEqual(affectedConfigurations, ["Config1"]) XCTAssertEqual(affectedConfigurations, ["Config1"])
} }
do { do {
let from = From<TestEntity1>("Config2") let from = From<TestEntity1>("Config2")
let request = NSFetchRequest<TestEntity1>() let request = CoreStoreFetchRequest()
let storesFound = self.expectLogger([.logWarning]) { let storesFound = self.expectLogger([.logWarning]) {
from.applyToFetchRequest(request, context: dataStack.mainContext) from.applyToFetchRequest(request, context: dataStack.mainContext)
} }
XCTAssertFalse(storesFound) XCTAssertFalse(storesFound)
XCTAssertNotNil(request.entity) XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores) XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName } let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertTrue(affectedConfigurations.isEmpty) XCTAssertTrue(affectedConfigurations.isEmpty)
} }
do { do {
let from = From<TestEntity2>() let from = From<TestEntity2>()
let request = NSFetchRequest<TestEntity2>() let request = CoreStoreFetchRequest()
let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext) let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext)
XCTAssertTrue(storesFound) XCTAssertTrue(storesFound)
XCTAssertNotNil(request.entity) XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores) XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName } let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertEqual(affectedConfigurations, ["PF_DEFAULT_CONFIGURATION_NAME"]) XCTAssertEqual(affectedConfigurations, ["PF_DEFAULT_CONFIGURATION_NAME"])
} }
do { do {
let from = From<TestEntity2>("Config1") let from = From<TestEntity2>("Config1")
let request = NSFetchRequest<TestEntity2>() let request = CoreStoreFetchRequest()
let storesFound = self.expectLogger([.logWarning]) { let storesFound = self.expectLogger([.logWarning]) {
from.applyToFetchRequest(request, context: dataStack.mainContext) from.applyToFetchRequest(request, context: dataStack.mainContext)
} }
XCTAssertFalse(storesFound) XCTAssertFalse(storesFound)
XCTAssertNotNil(request.entity) XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores) XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName } let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertTrue(affectedConfigurations.isEmpty) XCTAssertTrue(affectedConfigurations.isEmpty)
} }
do { do {
let from = From<TestEntity2>("Config2") let from = From<TestEntity2>("Config2")
let request = NSFetchRequest<TestEntity2>() let request = CoreStoreFetchRequest()
let storesFound = self.expectLogger([.logWarning]) { let storesFound = self.expectLogger([.logWarning]) {
from.applyToFetchRequest(request, context: dataStack.mainContext) from.applyToFetchRequest(request, context: dataStack.mainContext)
} }
XCTAssertFalse(storesFound) XCTAssertFalse(storesFound)
XCTAssertNotNil(request.entity) XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores) XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName } let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertTrue(affectedConfigurations.isEmpty) XCTAssertTrue(affectedConfigurations.isEmpty)
} }
} }
@@ -332,96 +332,96 @@ final class FromTests: BaseTestCase {
let from = From<TestEntity1>() let from = From<TestEntity1>()
let request = NSFetchRequest<TestEntity1>() let request = CoreStoreFetchRequest()
let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext) let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext)
XCTAssertTrue(storesFound) XCTAssertTrue(storesFound)
XCTAssertNotNil(request.entity) XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores) XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName } let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertEqual(affectedConfigurations, ["Config1"]) XCTAssertEqual(affectedConfigurations, ["Config1"])
} }
do { do {
let from = From<TestEntity1>("Config1") let from = From<TestEntity1>("Config1")
let request = NSFetchRequest<TestEntity1>() let request = CoreStoreFetchRequest()
let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext) let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext)
XCTAssertTrue(storesFound) XCTAssertTrue(storesFound)
XCTAssertNotNil(request.entity) XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores) XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName } let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertEqual(affectedConfigurations, ["Config1"]) XCTAssertEqual(affectedConfigurations, ["Config1"])
} }
do { do {
let from = From<TestEntity1>("Config2") let from = From<TestEntity1>("Config2")
let request = NSFetchRequest<TestEntity1>() let request = CoreStoreFetchRequest()
let storesFound = self.expectLogger([.logWarning]) { let storesFound = self.expectLogger([.logWarning]) {
from.applyToFetchRequest(request, context: dataStack.mainContext) from.applyToFetchRequest(request, context: dataStack.mainContext)
} }
XCTAssertFalse(storesFound) XCTAssertFalse(storesFound)
XCTAssertNotNil(request.entity) XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores) XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName } let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertTrue(affectedConfigurations.isEmpty) XCTAssertTrue(affectedConfigurations.isEmpty)
} }
do { do {
let from = From<TestEntity2>() let from = From<TestEntity2>()
let request = NSFetchRequest<TestEntity2>() let request = CoreStoreFetchRequest()
let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext) let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext)
XCTAssertTrue(storesFound) XCTAssertTrue(storesFound)
XCTAssertNotNil(request.entity) XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores) XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName } let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertEqual(affectedConfigurations, ["Config2"]) XCTAssertEqual(affectedConfigurations, ["Config2"])
} }
do { do {
let from = From<TestEntity2>("Config1") let from = From<TestEntity2>("Config1")
let request = NSFetchRequest<TestEntity2>() let request = CoreStoreFetchRequest()
let storesFound = self.expectLogger([.logWarning]) { let storesFound = self.expectLogger([.logWarning]) {
from.applyToFetchRequest(request, context: dataStack.mainContext) from.applyToFetchRequest(request, context: dataStack.mainContext)
} }
XCTAssertFalse(storesFound) XCTAssertFalse(storesFound)
XCTAssertNotNil(request.entity) XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores) XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName } let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertTrue(affectedConfigurations.isEmpty) XCTAssertTrue(affectedConfigurations.isEmpty)
} }
do { do {
let from = From<TestEntity2>("Config2") let from = From<TestEntity2>("Config2")
let request = NSFetchRequest<TestEntity2>() let request = CoreStoreFetchRequest()
let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext) let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext)
XCTAssertTrue(storesFound) XCTAssertTrue(storesFound)
XCTAssertNotNil(request.entity) XCTAssertNotNil(request.entity)
XCTAssertNotNil(request.affectedStores) XCTAssertNotNil(request.safeAffectedStores)
XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName))
let affectedConfigurations = request.affectedStores!.map { $0.configurationName } let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName }
XCTAssertEqual(affectedConfigurations, ["Config2"]) XCTAssertEqual(affectedConfigurations, ["Config2"])
} }
} }

View File

@@ -68,7 +68,7 @@ final class GroupByTests: BaseTestCase {
let groupBy = GroupBy(#keyPath(TestEntity1.testString)) let groupBy = GroupBy(#keyPath(TestEntity1.testString))
let request = NSFetchRequest<TestEntity1>() let request = CoreStoreFetchRequest()
_ = From<TestEntity1>().applyToFetchRequest(request, context: dataStack.mainContext) _ = From<TestEntity1>().applyToFetchRequest(request, context: dataStack.mainContext)
groupBy.applyToFetchRequest(request) groupBy.applyToFetchRequest(request)

View File

@@ -179,7 +179,7 @@ final class OrderByTests: XCTestCase {
dynamic func test_ThatOrderByClauses_ApplyToFetchRequestsCorrectly() { dynamic func test_ThatOrderByClauses_ApplyToFetchRequestsCorrectly() {
let orderBy = OrderBy(.ascending("key")) let orderBy = OrderBy(.ascending("key"))
let request = NSFetchRequest<NSFetchRequestResult>() let request = CoreStoreFetchRequest()
orderBy.applyToFetchRequest(request) orderBy.applyToFetchRequest(request)
XCTAssertNotNil(request.sortDescriptors) XCTAssertNotNil(request.sortDescriptors)
XCTAssertEqual(request.sortDescriptors ?? [], orderBy.sortDescriptors) XCTAssertEqual(request.sortDescriptors ?? [], orderBy.sortDescriptors)

View File

@@ -93,10 +93,10 @@ final class StorageInterfaceTests: XCTestCase {
@objc @objc
dynamic func test_ThatFileURLSQLiteStores_ConfigureCorrectly() { dynamic func test_ThatFileURLSQLiteStores_ConfigureCorrectly() {
let fileURL = URL(fileURLWithPath: NSTemporaryDirectory()) let fileURL = NSURL(fileURLWithPath: NSTemporaryDirectory())
.appendingPathComponent(UUID().uuidString, isDirectory: false) .URLByAppendingPathComponent(NSUUID().UUIDString, isDirectory: false)!
.appendingPathExtension("db") .URLByAppendingPathExtension("db")!
let bundles = [Bundle(for: type(of: self))] let bundles = [NSBundle(forClass: self.dynamicType)]
let store = SQLiteStore( let store = SQLiteStore(
fileURL: fileURL, fileURL: fileURL,
@@ -149,8 +149,8 @@ final class StorageInterfaceTests: XCTestCase {
in: .userDomainMask).first! in: .userDomainMask).first!
let legacyDefaultFileURL = legacyDefaultRootDirectory let legacyDefaultFileURL = legacyDefaultRootDirectory
.appendingPathComponent(DataStack.applicationName, isDirectory: false) .URLByAppendingPathComponent(DataStack.applicationName, isDirectory: false)!
.appendingPathExtension("sqlite") .URLByAppendingPathExtension("sqlite")!
XCTAssertEqual(LegacySQLiteStore.defaultRootDirectory, legacyDefaultRootDirectory) XCTAssertEqual(LegacySQLiteStore.defaultRootDirectory, legacyDefaultRootDirectory)
XCTAssertEqual(LegacySQLiteStore.defaultFileURL, legacyDefaultFileURL) XCTAssertEqual(LegacySQLiteStore.defaultFileURL, legacyDefaultFileURL)
@@ -172,10 +172,10 @@ final class StorageInterfaceTests: XCTestCase {
@objc @objc
dynamic func test_ThatFileURLLegacySQLiteStores_ConfigureCorrectly() { dynamic func test_ThatFileURLLegacySQLiteStores_ConfigureCorrectly() {
let fileURL = URL(fileURLWithPath: NSTemporaryDirectory()) let fileURL = NSURL(fileURLWithPath: NSTemporaryDirectory())
.appendingPathComponent(UUID().uuidString, isDirectory: false) .URLByAppendingPathComponent(NSUUID().UUIDString, isDirectory: false)!
.appendingPathExtension("db") .URLByAppendingPathExtension("db")!
let bundles = [Bundle(for: type(of: self))] let bundles = [NSBundle(forClass: self.dynamicType)]
let store = LegacySQLiteStore( let store = LegacySQLiteStore(
fileURL: fileURL, fileURL: fileURL,

View File

@@ -43,7 +43,7 @@ final class TweakTests: XCTestCase {
$0.fetchLimit = 200 $0.fetchLimit = 200
$0.predicate = predicate $0.predicate = predicate
} }
let request = NSFetchRequest<NSFetchRequestResult>() let request = CoreStoreFetchRequest()
tweak.applyToFetchRequest(request) tweak.applyToFetchRequest(request)
XCTAssertEqual(request.fetchOffset, 100) XCTAssertEqual(request.fetchOffset, 100)
XCTAssertEqual(request.fetchLimit, 200) XCTAssertEqual(request.fetchLimit, 200)

View File

@@ -142,7 +142,7 @@ final class WhereTests: XCTestCase {
dynamic func test_ThatWhereClauses_ApplyToFetchRequestsCorrectly() { dynamic func test_ThatWhereClauses_ApplyToFetchRequestsCorrectly() {
let whereClause = Where("key", isEqualTo: "value") let whereClause = Where("key", isEqualTo: "value")
let request = NSFetchRequest<NSFetchRequestResult>() let request = CoreStoreFetchRequest()
whereClause.applyToFetchRequest(request) whereClause.applyToFetchRequest(request)
XCTAssertNotNil(request.predicate) XCTAssertNotNil(request.predicate)
XCTAssertEqual(request.predicate, whereClause.predicate) XCTAssertEqual(request.predicate, whereClause.predicate)

View File

@@ -17,8 +17,12 @@ Unleashing the real power of Core Data with the elegance and safety of Swift
<a href="https://twitter.com/JohnEstropia"><img alt="Reach me on Twitter!" src="https://img.shields.io/badge/twitter-%40JohnEstropia-3498db.svg" /></a> <a href="https://twitter.com/JohnEstropia"><img alt="Reach me on Twitter!" src="https://img.shields.io/badge/twitter-%40JohnEstropia-3498db.svg" /></a>
<br /> <br />
</p> </p>
* Swift 2.2 (Xcode 7.3)
* iOS 7+ / macOS 10.10+ / watchOS 2.0+ / tvOS 9.0+ * iOS 7+ / macOS 10.10+ / watchOS 2.0+ / tvOS 9.0+
- for Swift 2.2 (Xcode 7.3 and iOS 7): Use version [2.0.6](https://github.com/JohnEstropia/CoreStore/releases/tag/2.0.6) or the [master_ios_7_to_9](https://github.com/JohnEstropia/CoreStore/tree/master_ios_7_to_9) branch
- for Swift 2.3 (Xcode 8): Use version [2.1.0](https://github.com/JohnEstropia/CoreStore/releases/tag/2.1.0) or the [master](https://github.com/JohnEstropia/CoreStore/tree/master) branch
- for Swift 3 (Xcode 8): Use the [swift3_develop](https://github.com/JohnEstropia/CoreStore/tree/swift3_develop) branch
* **New in CoreStore 2.0:** Objective-C support! All CoreStore types now have their corresponding Objective-C "bridging classes". Perfect for projects transitioning from Objective-C to Swift! * **New in CoreStore 2.0:** Objective-C support! All CoreStore types now have their corresponding Objective-C "bridging classes". Perfect for projects transitioning from Objective-C to Swift!
Upgrading from CoreStore 1.x to 2.x? Check out the [new features](#new-in-corestore-20) and make sure to read the [Migration guide](#upgrading-from-1xx-to-2xx). Upgrading from CoreStore 1.x to 2.x? Check out the [new features](#new-in-corestore-20) and make sure to read the [Migration guide](#upgrading-from-1xx-to-2xx).
@@ -1411,13 +1415,7 @@ NSArray<MYPerson *> *objects =
CSSortAscending(CSKeyPath(MYPerson, firstName)), nil)]]; CSSortAscending(CSKeyPath(MYPerson, firstName)), nil)]];
``` ```
To use these syntax sugars, include *CoreStoreBridge.h* in your Objective-C source files. For projects that support iOS 7 (and thus cannot build CoreStore as a module), you will need to add To use these syntax sugars, include *CoreStoreBridge.h* in your Objective-C source files.
```
SWIFT_OBJC_INTERFACE_HEADER_NAME=$(SWIFT_OBJC_INTERFACE_HEADER_NAME)
```
to your target's `GCC_PREPROCESSOR_DEFINITIONS` build setting.
<img width="797" alt="GCC_PREPROCESSOR_DEFINITIONS" src="https://cloud.githubusercontent.com/assets/3029684/16714547/92497fc4-4701-11e6-81db-6b1a11743cc5.png" />
# Roadmap # Roadmap
@@ -1429,12 +1427,14 @@ to your target's `GCC_PREPROCESSOR_DEFINITIONS` build setting.
# Installation # Installation
- Requires: - Requires:
- iOS 7 SDK and above - iOS 8 SDK and above
- Swift 2.2 (Xcode 7.3) - Swift 2.3 (Xcode 8)
- Dependencies:
- [GCDKit](https://github.com/JohnEstropia/GCDKit)
- Other notes: - Other notes:
- The `com.apple.CoreData.ConcurrencyDebug` debug argument should be turned off for the app. CoreStore already guarantees safety for you by making the main context read-only, and by only executing transactions serially. - The `com.apple.CoreData.ConcurrencyDebug` debug argument should be turned off for the app. CoreStore already guarantees safety for you by making the main context read-only, and by only executing transactions serially.
### Install with CocoaPods (iOS 7 not supported) ### Install with CocoaPods
``` ```
pod 'CoreStore' pod 'CoreStore'
``` ```
@@ -1443,7 +1443,7 @@ This installs CoreStore as a framework. Declare `import CoreStore` in your swift
### Install with Carthage ### Install with Carthage
In your `Cartfile`, add In your `Cartfile`, add
``` ```
github "JohnEstropia/CoreStore" >= 2.0.0 github "JohnEstropia/CoreStore" >= 2.1.0
``` ```
and run and run
``` ```
@@ -1456,7 +1456,7 @@ git submodule add https://github.com/JohnEstropia/CoreStore.git <destination dir
``` ```
Drag and drop **CoreStore.xcodeproj** to your project. Drag and drop **CoreStore.xcodeproj** to your project.
#### To install as a framework (iOS 7 not supported): #### To install as a framework:
Drag and drop **CoreStore.xcodeproj** to your project. Drag and drop **CoreStore.xcodeproj** to your project.
#### To include directly in your app module: #### To include directly in your app module:
@@ -1467,15 +1467,6 @@ Add all *.swift* files to your project.
To use the Objective-C syntax sugars, import *CoreStoreBridge.h* in your *.m* source files. To use the Objective-C syntax sugars, import *CoreStoreBridge.h* in your *.m* source files.
For projects that support iOS 7 (and thus cannot build CoreStore as a module), you will need to add
```
SWIFT_OBJC_INTERFACE_HEADER_NAME=$(SWIFT_OBJC_INTERFACE_HEADER_NAME)
```
to your target's `GCC_PREPROCESSOR_DEFINITIONS` build setting:
<img width="797" alt="GCC_PREPROCESSOR_DEFINITIONS" src="https://cloud.githubusercontent.com/assets/3029684/16714547/92497fc4-4701-11e6-81db-6b1a11743cc5.png" />
# Changesets # Changesets
### Upgrading from 1.x.x to 2.x.x ### Upgrading from 1.x.x to 2.x.x
**Obsoleted** **Obsoleted**

View File

@@ -15,7 +15,7 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>FMWK</string> <string>FMWK</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>2.0.4</string> <string>2.1.1</string>
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>????</string> <string>????</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>

View File

@@ -132,6 +132,16 @@ internal final class FetchedResultsControllerDelegate<EntityType: NSManagedObjec
} }
} }
if #available(iOS 10.0, tvOS 10.0, watchOS 3.0, *) {
// I don't know if iOS 10 even attempted to fix this mess...
if case .update = actualType,
indexPath != nil && newIndexPath != nil {
actualType = .move
}
}
switch actualType { switch actualType {
case .update: case .update:
@@ -142,7 +152,7 @@ internal final class FetchedResultsControllerDelegate<EntityType: NSManagedObjec
if self.deletedSections.contains(section) if self.deletedSections.contains(section)
|| self.insertedSections.contains(section) { || self.insertedSections.contains(section) {
return return
} }
case .move: case .move:

View File

@@ -143,7 +143,7 @@ public final class CSAsynchronousDataTransaction: CSBaseDataTransaction {
// MARK: CoreStoreObjectiveCType // MARK: CoreStoreObjectiveCType
internal typealias SwiftType = AsynchronousDataTransaction public typealias SwiftType = AsynchronousDataTransaction
public override var bridgeToSwift: AsynchronousDataTransaction { public override var bridgeToSwift: AsynchronousDataTransaction {
@@ -152,21 +152,21 @@ public final class CSAsynchronousDataTransaction: CSBaseDataTransaction {
public required init(_ swiftValue: AsynchronousDataTransaction) { public required init(_ swiftValue: AsynchronousDataTransaction) {
super.init(swiftValue) super.init(swiftValue as BaseDataTransaction)
} }
public required init(_ swiftValue: BaseDataTransaction) { public required init(_ swiftValue: BaseDataTransaction) {
fatalError("init(_:) requires an AsynchronousDataTransaction instance") super.init(swiftValue as! AsynchronousDataTransaction)
} }
} }
// MARK: - AsynchronousDataTransaction // MARK: - AsynchronousDataTransaction
extension AsynchronousDataTransaction { extension AsynchronousDataTransaction: CoreStoreSwiftType {
// MARK: CoreStoreSwiftType // MARK: CoreStoreSwiftType
internal typealias ObjectiveCType = CSAsynchronousDataTransaction public typealias ObjectiveCType = CSAsynchronousDataTransaction
} }

View File

@@ -278,8 +278,6 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
// MARK: CoreStoreObjectiveCType // MARK: CoreStoreObjectiveCType
public typealias SwiftType = BaseDataTransaction
public required init(_ swiftValue: BaseDataTransaction) { public required init(_ swiftValue: BaseDataTransaction) {
self.swiftTransaction = swiftValue self.swiftTransaction = swiftValue
@@ -298,11 +296,11 @@ public class CSBaseDataTransaction: NSObject, CoreStoreObjectiveCType {
} }
// MARK: - BaseDataTransaction //// MARK: - BaseDataTransaction
//
extension BaseDataTransaction: CoreStoreSwiftType { //extension BaseDataTransaction: CoreStoreSwiftType {
//
// MARK: CoreStoreSwiftType // // MARK: CoreStoreSwiftType
//
public typealias ObjectiveCType = CSBaseDataTransaction // public typealias ObjectiveCType = CSBaseDataTransaction
} //}

View File

@@ -142,7 +142,7 @@ public final class CSSynchronousDataTransaction: CSBaseDataTransaction {
// MARK: CoreStoreObjectiveCType // MARK: CoreStoreObjectiveCType
internal typealias SwiftType = SynchronousDataTransaction public typealias SwiftType = SynchronousDataTransaction
public override var bridgeToSwift: SynchronousDataTransaction { public override var bridgeToSwift: SynchronousDataTransaction {
@@ -151,21 +151,21 @@ public final class CSSynchronousDataTransaction: CSBaseDataTransaction {
public required init(_ swiftValue: SynchronousDataTransaction) { public required init(_ swiftValue: SynchronousDataTransaction) {
super.init(swiftValue) super.init(swiftValue as BaseDataTransaction)
} }
public required init(_ swiftValue: BaseDataTransaction) { public required init(_ swiftValue: BaseDataTransaction) {
fatalError("init(_:) requires a BaseDataTransaction instance") super.init(swiftValue as! SynchronousDataTransaction)
} }
} }
// MARK: - SynchronousDataTransaction // MARK: - SynchronousDataTransaction
extension SynchronousDataTransaction { extension SynchronousDataTransaction: CoreStoreSwiftType {
// MARK: CoreStoreSwiftType // MARK: CoreStoreSwiftType
internal typealias ObjectiveCType = CSSynchronousDataTransaction public typealias ObjectiveCType = CSSynchronousDataTransaction
} }

View File

@@ -172,7 +172,7 @@ public final class CSUnsafeDataTransaction: CSBaseDataTransaction {
// MARK: CoreStoreObjectiveCType // MARK: CoreStoreObjectiveCType
internal typealias SwiftType = UnsafeDataTransaction public typealias SwiftType = UnsafeDataTransaction
public override var bridgeToSwift: UnsafeDataTransaction { public override var bridgeToSwift: UnsafeDataTransaction {
@@ -181,21 +181,21 @@ public final class CSUnsafeDataTransaction: CSBaseDataTransaction {
public required init(_ swiftValue: UnsafeDataTransaction) { public required init(_ swiftValue: UnsafeDataTransaction) {
super.init(swiftValue) super.init(swiftValue as BaseDataTransaction)
} }
public required init(_ swiftValue: BaseDataTransaction) { public required init(_ swiftValue: BaseDataTransaction) {
fatalError("init(_:) requires an UnsafeDataTransaction instance") super.init(swiftValue as! UnsafeDataTransaction)
} }
} }
// MARK: - UnsafeDataTransaction // MARK: - UnsafeDataTransaction
extension UnsafeDataTransaction { extension UnsafeDataTransaction: CoreStoreSwiftType {
// MARK: CoreStoreSwiftType // MARK: CoreStoreSwiftType
internal typealias ObjectiveCType = CSUnsafeDataTransaction public typealias ObjectiveCType = CSUnsafeDataTransaction
} }

View File

@@ -570,4 +570,16 @@ CORESTORE_EXTERN
CSWhere *_Nonnull CSWherePredicate(NSPredicate *_Nonnull predicate) CORESTORE_RETURNS_RETAINED; CSWhere *_Nonnull CSWherePredicate(NSPredicate *_Nonnull predicate) CORESTORE_RETURNS_RETAINED;
#pragma mark CoreStoreFetchRequest
// Bugfix for NSFetchRequest messing up memory management for `affectedStores`
// http://stackoverflow.com/questions/14396375/nsfetchedresultscontroller-crashes-in-ios-6-if-affectedstores-is-specified
NS_SWIFT_NAME(CoreStoreFetchRequest)
@interface _CSFetchRequest: NSFetchRequest
@property (nullable, nonatomic, copy, readonly) NSArray<NSPersistentStore *> *safeAffectedStores;
@end
#endif /* CoreStoreBridge_h */ #endif /* CoreStoreBridge_h */

View File

@@ -26,23 +26,8 @@
#import "CoreStoreBridge.h" #import "CoreStoreBridge.h"
#if USE_FRAMEWORKS
#import <CoreStore/CoreStore-Swift.h> #import <CoreStore/CoreStore-Swift.h>
#elif !defined(SWIFT_OBJC_INTERFACE_HEADER_NAME)
#error Add "SWIFT_OBJC_INTERFACE_HEADER_NAME=$(SWIFT_OBJC_INTERFACE_HEADER_NAME)" to the project's GCC_PREPROCESSOR_DEFINITIONS settings
#elif __has_include(SWIFT_OBJC_INTERFACE_HEADER_NAME)
#import SWIFT_OBJC_INTERFACE_HEADER_NAME
#else
#define _STRINGIFY(x) #x
#define STRINGIFY(x) _STRINGIFY(x)
#import STRINGIFY(SWIFT_OBJC_INTERFACE_HEADER_NAME)
#endif
#pragma mark - Clauses #pragma mark - Clauses
@@ -233,3 +218,40 @@ CSWhere *_Nonnull CSWherePredicate(NSPredicate *_Nonnull predicate) CORESTORE_RE
return [[CSWhere alloc] initWithPredicate:predicate]; return [[CSWhere alloc] initWithPredicate:predicate];
} }
#pragma mark CoreStoreFetchRequest
@interface _CSFetchRequest ()
@property (nullable, nonatomic, copy) NSArray<NSPersistentStore *> *safeAffectedStores;
@property (nullable, nonatomic, assign) CFArrayRef releaseArray;
@end
@implementation _CSFetchRequest
// MARK: NSFetchRequest
- (void)setAffectedStores:(NSArray<NSPersistentStore *> *_Nullable)affectedStores {
// Bugfix for NSFetchRequest messing up memory management for `affectedStores`
// http://stackoverflow.com/questions/14396375/nsfetchedresultscontroller-crashes-in-ios-6-if-affectedstores-is-specified
if (NSFoundationVersionNumber < NSFoundationVersionNumber10_0) {
self.safeAffectedStores = affectedStores;
[super setAffectedStores:affectedStores];
return;
}
if (self.releaseArray != NULL) {
CFRelease(self.releaseArray);
self.releaseArray = NULL;
}
self.safeAffectedStores = affectedStores;
[super setAffectedStores:affectedStores];
self.releaseArray = CFBridgingRetain([super affectedStores]);
}
@end

View File

@@ -1068,7 +1068,7 @@ public final class ListMonitor<T: NSManagedObject>: Hashable {
self.isPersistentStoreChanging = true self.isPersistentStoreChanging = true
guard let removedStores = (note.userInfo?[NSRemovedPersistentStoresKey] as? [NSPersistentStore]).flatMap(Set.init), guard let removedStores = (note.userInfo?[NSRemovedPersistentStoresKey] as? [NSPersistentStore]).flatMap(Set.init),
!Set(self.fetchedResultsController.fetchRequest.affectedStores ?? []).intersection(removedStores).isEmpty else { !Set((self.fetchedResultsController.fetchRequest as! CoreStoreFetchRequest).affectedStores ?? []).intersection(removedStores).isEmpty else {
return return
} }
@@ -1089,7 +1089,7 @@ public final class ListMonitor<T: NSManagedObject>: Hashable {
if !self.isPendingRefetch { if !self.isPendingRefetch {
let previousStores = Set(self.fetchedResultsController.fetchRequest.affectedStores ?? []) let previousStores = Set((self.fetchedResultsController.fetchRequest as! CoreStoreFetchRequest).safeAffectedStores ?? [])
let currentStores = previousStores let currentStores = previousStores
.subtracting(note.userInfo?[NSRemovedPersistentStoresKey] as? [NSPersistentStore] ?? []) .subtracting(note.userInfo?[NSRemovedPersistentStoresKey] as? [NSPersistentStore] ?? [])
.union(note.userInfo?[NSAddedPersistentStoresKey] as? [NSPersistentStore] ?? []) .union(note.userInfo?[NSAddedPersistentStoresKey] as? [NSPersistentStore] ?? [])