diff --git a/.travis.yml b/.travis.yml index ca29d13..869e0d4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ language: objective-c -osx_image: xcode7.3 +osx_image: xcode8 sudo: false git: submodules: false @@ -10,16 +10,16 @@ env: - LC_CTYPE=en_US.UTF-8 - LANG=en_US.UTF-8 matrix: - - DESTINATION="OS=9.3,name=iPhone 6s" SCHEME="CoreStore iOS" SDK=iphonesimulator9.3 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=8.4,name=iPhone 6" SCHEME="CoreStore iOS" SDK=iphonesimulator9.3 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.2,name=iPhone 5" SCHEME="CoreStore iOS" SDK=iphonesimulator9.3 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 iOS7" SDK=iphonesimulator9.3 RUN_TESTS="YES" POD_LINT="YES" - - DESTINATION="arch=x86_64" SCHEME="CoreStore OSX" SDK=macosx10.11 RUN_TESTS="YES" 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=9.2,name=Apple TV 1080p" SCHEME="CoreStore tvOS" SDK=appletvsimulator9.2 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=iphonesimulator10.0 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=iphonesimulator10.0 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=iphonesimulator10.0 RUN_TESTS="YES" POD_LINT="YES" + - DESTINATION="arch=x86_64" SCHEME="CoreStore OSX" SDK=macosx10.12 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=watchsimulator3.0 RUN_TESTS="NO" 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: - gem install cocoapods --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 Release ONLY_ACTIVE_ARCH=NO clean test | xcpretty -c; 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 "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 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 Release ONLY_ACTIVE_ARCH=NO clean test | xcpretty -c; - if [ $POD_LINT == "YES" ]; then pod lib lint --quick; fi diff --git a/CoreStore.podspec b/CoreStore.podspec index 715ba67..e92f916 100644 --- a/CoreStore.podspec +++ b/CoreStore.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "CoreStore" - s.version = "2.0.4" + s.version = "2.1.1" s.license = "MIT" s.summary = "Unleashing the real power of Core Data with the elegance and safety of Swift" s.homepage = "https://github.com/JohnEstropia/CoreStore" @@ -16,6 +16,7 @@ Pod::Spec.new do |s| s.public_header_files = "Sources/**/*.h" s.frameworks = "Foundation", "CoreData" 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' } end diff --git a/CoreStoreDemo/CoreStoreDemo.xcodeproj/project.pbxproj b/CoreStoreDemo/CoreStoreDemo.xcodeproj/project.pbxproj index 00e5f04..1a19818 100644 --- a/CoreStoreDemo/CoreStoreDemo.xcodeproj/project.pbxproj +++ b/CoreStoreDemo/CoreStoreDemo.xcodeproj/project.pbxproj @@ -271,8 +271,6 @@ TargetAttributes = { B54AAD481AF4D26E00848AE0 = { CreatedOnToolsVersion = 6.3; - DevelopmentTeam = 2JT32EJ5BH; - DevelopmentTeamName = "JOHNROMMEL ESTROPIA"; LastSwiftMigration = 0800; }; }; diff --git a/CoreStoreTests/BridgingTests.m b/CoreStoreTests/BridgingTests.m index 886bc40..04c2efa 100644 --- a/CoreStoreTests/BridgingTests.m +++ b/CoreStoreTests/BridgingTests.m @@ -197,4 +197,41 @@ 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 diff --git a/CoreStoreTests/FromTests.swift b/CoreStoreTests/FromTests.swift index 866ce43..6a0a740 100644 --- a/CoreStoreTests/FromTests.swift +++ b/CoreStoreTests/FromTests.swift @@ -74,33 +74,33 @@ final class FromTests: BaseTestCase { let from = From() - let request = NSFetchRequest() + let request = CoreStoreFetchRequest() let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext) XCTAssertTrue(storesFound) XCTAssertNotNil(request.entity) - XCTAssertNotNil(request.affectedStores) + XCTAssertNotNil(request.safeAffectedStores) 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"]) } do { let from = From("Config1") - let request = NSFetchRequest() + let request = CoreStoreFetchRequest() let storesFound = self.expectLogger([.logWarning]) { from.applyToFetchRequest(request, context: dataStack.mainContext) } XCTAssertFalse(storesFound) XCTAssertNotNil(request.entity) - XCTAssertNotNil(request.affectedStores) + XCTAssertNotNil(request.safeAffectedStores) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) - let affectedConfigurations = request.affectedStores!.map { $0.configurationName } + let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName } XCTAssertTrue(affectedConfigurations.isEmpty) } } @@ -115,102 +115,102 @@ final class FromTests: BaseTestCase { let from = From() - let request = NSFetchRequest() + let request = CoreStoreFetchRequest() let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext) XCTAssertTrue(storesFound) XCTAssertNotNil(request.entity) - XCTAssertNotNil(request.affectedStores) + XCTAssertNotNil(request.safeAffectedStores) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) - let affectedConfigurations = request.affectedStores!.map { $0.configurationName } + let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName } XCTAssertEqual(affectedConfigurations, ["Config1"]) } do { let from = From("Config1") - let request = NSFetchRequest() + let request = CoreStoreFetchRequest() let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext) XCTAssertTrue(storesFound) XCTAssertNotNil(request.entity) - XCTAssertNotNil(request.affectedStores) + XCTAssertNotNil(request.safeAffectedStores) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) - let affectedConfigurations = request.affectedStores!.map { $0.configurationName } + let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName } XCTAssertEqual(affectedConfigurations, ["Config1"]) } do { let from = From("Config2") - let request = NSFetchRequest() + let request = CoreStoreFetchRequest() let storesFound = self.expectLogger([.logWarning]) { from.applyToFetchRequest(request, context: dataStack.mainContext) } XCTAssertFalse(storesFound) XCTAssertNotNil(request.entity) - XCTAssertNotNil(request.affectedStores) + XCTAssertNotNil(request.safeAffectedStores) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) - let affectedConfigurations = request.affectedStores!.map { $0.configurationName } + let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName } XCTAssertTrue(affectedConfigurations.isEmpty) } do { let from = From() - let request = NSFetchRequest() + let request = CoreStoreFetchRequest() let storesFound = self.expectLogger([.logWarning]) { from.applyToFetchRequest(request, context: dataStack.mainContext) } XCTAssertFalse(storesFound) XCTAssertNotNil(request.entity) - XCTAssertNotNil(request.affectedStores) + XCTAssertNotNil(request.safeAffectedStores) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) - let affectedConfigurations = request.affectedStores!.map { $0.configurationName } + let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName } XCTAssertTrue(affectedConfigurations.isEmpty) } do { let from = From("Config1") - let request = NSFetchRequest() + let request = CoreStoreFetchRequest() let storesFound = self.expectLogger([.logWarning]) { from.applyToFetchRequest(request, context: dataStack.mainContext) } XCTAssertFalse(storesFound) XCTAssertNotNil(request.entity) - XCTAssertNotNil(request.affectedStores) + XCTAssertNotNil(request.safeAffectedStores) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) - let affectedConfigurations = request.affectedStores!.map { $0.configurationName } + let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName } XCTAssertTrue(affectedConfigurations.isEmpty) } do { let from = From("Config2") - let request = NSFetchRequest() + let request = CoreStoreFetchRequest() let storesFound = self.expectLogger([.logWarning]) { from.applyToFetchRequest(request, context: dataStack.mainContext) } XCTAssertFalse(storesFound) XCTAssertNotNil(request.entity) - XCTAssertNotNil(request.affectedStores) + XCTAssertNotNil(request.safeAffectedStores) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) - let affectedConfigurations = request.affectedStores!.map { $0.configurationName } + let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName } XCTAssertTrue(affectedConfigurations.isEmpty) } } @@ -225,99 +225,99 @@ final class FromTests: BaseTestCase { let from = From() - let request = NSFetchRequest() + let request = CoreStoreFetchRequest() let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext) XCTAssertTrue(storesFound) XCTAssertNotNil(request.entity) - XCTAssertNotNil(request.affectedStores) + XCTAssertNotNil(request.safeAffectedStores) 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) } do { let from = From("Config1") - let request = NSFetchRequest() + let request = CoreStoreFetchRequest() let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext) XCTAssertTrue(storesFound) XCTAssertNotNil(request.entity) - XCTAssertNotNil(request.affectedStores) + XCTAssertNotNil(request.safeAffectedStores) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) - let affectedConfigurations = request.affectedStores!.map { $0.configurationName } + let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName } XCTAssertEqual(affectedConfigurations, ["Config1"]) } do { let from = From("Config2") - let request = NSFetchRequest() + let request = CoreStoreFetchRequest() let storesFound = self.expectLogger([.logWarning]) { from.applyToFetchRequest(request, context: dataStack.mainContext) } XCTAssertFalse(storesFound) XCTAssertNotNil(request.entity) - XCTAssertNotNil(request.affectedStores) + XCTAssertNotNil(request.safeAffectedStores) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) - let affectedConfigurations = request.affectedStores!.map { $0.configurationName } + let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName } XCTAssertTrue(affectedConfigurations.isEmpty) } do { let from = From() - let request = NSFetchRequest() + let request = CoreStoreFetchRequest() let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext) XCTAssertTrue(storesFound) XCTAssertNotNil(request.entity) - XCTAssertNotNil(request.affectedStores) + XCTAssertNotNil(request.safeAffectedStores) 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"]) } do { let from = From("Config1") - let request = NSFetchRequest() + let request = CoreStoreFetchRequest() let storesFound = self.expectLogger([.logWarning]) { from.applyToFetchRequest(request, context: dataStack.mainContext) } XCTAssertFalse(storesFound) XCTAssertNotNil(request.entity) - XCTAssertNotNil(request.affectedStores) + XCTAssertNotNil(request.safeAffectedStores) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) - let affectedConfigurations = request.affectedStores!.map { $0.configurationName } + let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName } XCTAssertTrue(affectedConfigurations.isEmpty) } do { let from = From("Config2") - let request = NSFetchRequest() + let request = CoreStoreFetchRequest() let storesFound = self.expectLogger([.logWarning]) { from.applyToFetchRequest(request, context: dataStack.mainContext) } XCTAssertFalse(storesFound) XCTAssertNotNil(request.entity) - XCTAssertNotNil(request.affectedStores) + XCTAssertNotNil(request.safeAffectedStores) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) - let affectedConfigurations = request.affectedStores!.map { $0.configurationName } + let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName } XCTAssertTrue(affectedConfigurations.isEmpty) } } @@ -332,96 +332,96 @@ final class FromTests: BaseTestCase { let from = From() - let request = NSFetchRequest() + let request = CoreStoreFetchRequest() let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext) XCTAssertTrue(storesFound) XCTAssertNotNil(request.entity) - XCTAssertNotNil(request.affectedStores) + XCTAssertNotNil(request.safeAffectedStores) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) - let affectedConfigurations = request.affectedStores!.map { $0.configurationName } + let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName } XCTAssertEqual(affectedConfigurations, ["Config1"]) } do { let from = From("Config1") - let request = NSFetchRequest() + let request = CoreStoreFetchRequest() let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext) XCTAssertTrue(storesFound) XCTAssertNotNil(request.entity) - XCTAssertNotNil(request.affectedStores) + XCTAssertNotNil(request.safeAffectedStores) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) - let affectedConfigurations = request.affectedStores!.map { $0.configurationName } + let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName } XCTAssertEqual(affectedConfigurations, ["Config1"]) } do { let from = From("Config2") - let request = NSFetchRequest() + let request = CoreStoreFetchRequest() let storesFound = self.expectLogger([.logWarning]) { from.applyToFetchRequest(request, context: dataStack.mainContext) } XCTAssertFalse(storesFound) XCTAssertNotNil(request.entity) - XCTAssertNotNil(request.affectedStores) + XCTAssertNotNil(request.safeAffectedStores) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) - let affectedConfigurations = request.affectedStores!.map { $0.configurationName } + let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName } XCTAssertTrue(affectedConfigurations.isEmpty) } do { let from = From() - let request = NSFetchRequest() + let request = CoreStoreFetchRequest() let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext) XCTAssertTrue(storesFound) XCTAssertNotNil(request.entity) - XCTAssertNotNil(request.affectedStores) + XCTAssertNotNil(request.safeAffectedStores) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) - let affectedConfigurations = request.affectedStores!.map { $0.configurationName } + let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName } XCTAssertEqual(affectedConfigurations, ["Config2"]) } do { let from = From("Config1") - let request = NSFetchRequest() + let request = CoreStoreFetchRequest() let storesFound = self.expectLogger([.logWarning]) { from.applyToFetchRequest(request, context: dataStack.mainContext) } XCTAssertFalse(storesFound) XCTAssertNotNil(request.entity) - XCTAssertNotNil(request.affectedStores) + XCTAssertNotNil(request.safeAffectedStores) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) - let affectedConfigurations = request.affectedStores!.map { $0.configurationName } + let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName } XCTAssertTrue(affectedConfigurations.isEmpty) } do { let from = From("Config2") - let request = NSFetchRequest() + let request = CoreStoreFetchRequest() let storesFound = from.applyToFetchRequest(request, context: dataStack.mainContext) XCTAssertTrue(storesFound) XCTAssertNotNil(request.entity) - XCTAssertNotNil(request.affectedStores) + XCTAssertNotNil(request.safeAffectedStores) XCTAssert(from.entityClass == NSClassFromString(request.entity!.managedObjectClassName)) - let affectedConfigurations = request.affectedStores!.map { $0.configurationName } + let affectedConfigurations = request.safeAffectedStores!.map { $0.configurationName } XCTAssertEqual(affectedConfigurations, ["Config2"]) } } diff --git a/CoreStoreTests/GroupByTests.swift b/CoreStoreTests/GroupByTests.swift index a5a9336..cf1e583 100644 --- a/CoreStoreTests/GroupByTests.swift +++ b/CoreStoreTests/GroupByTests.swift @@ -68,7 +68,7 @@ final class GroupByTests: BaseTestCase { let groupBy = GroupBy(#keyPath(TestEntity1.testString)) - let request = NSFetchRequest() + let request = CoreStoreFetchRequest() _ = From().applyToFetchRequest(request, context: dataStack.mainContext) groupBy.applyToFetchRequest(request) diff --git a/CoreStoreTests/OrderByTests.swift b/CoreStoreTests/OrderByTests.swift index 202f63e..69af761 100644 --- a/CoreStoreTests/OrderByTests.swift +++ b/CoreStoreTests/OrderByTests.swift @@ -179,7 +179,7 @@ final class OrderByTests: XCTestCase { dynamic func test_ThatOrderByClauses_ApplyToFetchRequestsCorrectly() { let orderBy = OrderBy(.ascending("key")) - let request = NSFetchRequest() + let request = CoreStoreFetchRequest() orderBy.applyToFetchRequest(request) XCTAssertNotNil(request.sortDescriptors) XCTAssertEqual(request.sortDescriptors ?? [], orderBy.sortDescriptors) diff --git a/CoreStoreTests/StorageInterfaceTests.swift b/CoreStoreTests/StorageInterfaceTests.swift index 67c1908..9a1206d 100644 --- a/CoreStoreTests/StorageInterfaceTests.swift +++ b/CoreStoreTests/StorageInterfaceTests.swift @@ -93,10 +93,10 @@ final class StorageInterfaceTests: XCTestCase { @objc dynamic func test_ThatFileURLSQLiteStores_ConfigureCorrectly() { - let fileURL = URL(fileURLWithPath: NSTemporaryDirectory()) - .appendingPathComponent(UUID().uuidString, isDirectory: false) - .appendingPathExtension("db") - let bundles = [Bundle(for: type(of: self))] + let fileURL = NSURL(fileURLWithPath: NSTemporaryDirectory()) + .URLByAppendingPathComponent(NSUUID().UUIDString, isDirectory: false)! + .URLByAppendingPathExtension("db")! + let bundles = [NSBundle(forClass: self.dynamicType)] let store = SQLiteStore( fileURL: fileURL, @@ -149,8 +149,8 @@ final class StorageInterfaceTests: XCTestCase { in: .userDomainMask).first! let legacyDefaultFileURL = legacyDefaultRootDirectory - .appendingPathComponent(DataStack.applicationName, isDirectory: false) - .appendingPathExtension("sqlite") + .URLByAppendingPathComponent(DataStack.applicationName, isDirectory: false)! + .URLByAppendingPathExtension("sqlite")! XCTAssertEqual(LegacySQLiteStore.defaultRootDirectory, legacyDefaultRootDirectory) XCTAssertEqual(LegacySQLiteStore.defaultFileURL, legacyDefaultFileURL) @@ -172,10 +172,10 @@ final class StorageInterfaceTests: XCTestCase { @objc dynamic func test_ThatFileURLLegacySQLiteStores_ConfigureCorrectly() { - let fileURL = URL(fileURLWithPath: NSTemporaryDirectory()) - .appendingPathComponent(UUID().uuidString, isDirectory: false) - .appendingPathExtension("db") - let bundles = [Bundle(for: type(of: self))] + let fileURL = NSURL(fileURLWithPath: NSTemporaryDirectory()) + .URLByAppendingPathComponent(NSUUID().UUIDString, isDirectory: false)! + .URLByAppendingPathExtension("db")! + let bundles = [NSBundle(forClass: self.dynamicType)] let store = LegacySQLiteStore( fileURL: fileURL, diff --git a/CoreStoreTests/TweakTests.swift b/CoreStoreTests/TweakTests.swift index 9088071..d8f1aae 100644 --- a/CoreStoreTests/TweakTests.swift +++ b/CoreStoreTests/TweakTests.swift @@ -43,7 +43,7 @@ final class TweakTests: XCTestCase { $0.fetchLimit = 200 $0.predicate = predicate } - let request = NSFetchRequest() + let request = CoreStoreFetchRequest() tweak.applyToFetchRequest(request) XCTAssertEqual(request.fetchOffset, 100) XCTAssertEqual(request.fetchLimit, 200) diff --git a/CoreStoreTests/WhereTests.swift b/CoreStoreTests/WhereTests.swift index 3474eaa..46ed81c 100644 --- a/CoreStoreTests/WhereTests.swift +++ b/CoreStoreTests/WhereTests.swift @@ -142,7 +142,7 @@ final class WhereTests: XCTestCase { dynamic func test_ThatWhereClauses_ApplyToFetchRequestsCorrectly() { let whereClause = Where("key", isEqualTo: "value") - let request = NSFetchRequest() + let request = CoreStoreFetchRequest() whereClause.applyToFetchRequest(request) XCTAssertNotNil(request.predicate) XCTAssertEqual(request.predicate, whereClause.predicate) diff --git a/README.md b/README.md index e7cf20f..abcb927 100644 --- a/README.md +++ b/README.md @@ -17,8 +17,12 @@ Unleashing the real power of Core Data with the elegance and safety of Swift Reach me on Twitter!

-* Swift 2.2 (Xcode 7.3) + * 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! 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 *objects = 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 -``` -SWIFT_OBJC_INTERFACE_HEADER_NAME=$(SWIFT_OBJC_INTERFACE_HEADER_NAME) -``` -to your target's `GCC_PREPROCESSOR_DEFINITIONS` build setting. - -GCC_PREPROCESSOR_DEFINITIONS +To use these syntax sugars, include *CoreStoreBridge.h* in your Objective-C source files. # Roadmap @@ -1429,12 +1427,14 @@ to your target's `GCC_PREPROCESSOR_DEFINITIONS` build setting. # Installation - Requires: - - iOS 7 SDK and above - - Swift 2.2 (Xcode 7.3) + - iOS 8 SDK and above + - Swift 2.3 (Xcode 8) +- Dependencies: + - [GCDKit](https://github.com/JohnEstropia/GCDKit) - 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. -### Install with CocoaPods (iOS 7 not supported) +### Install with CocoaPods ``` pod 'CoreStore' ``` @@ -1443,7 +1443,7 @@ This installs CoreStore as a framework. Declare `import CoreStore` in your swift ### Install with Carthage In your `Cartfile`, add ``` -github "JohnEstropia/CoreStore" >= 2.0.0 +github "JohnEstropia/CoreStore" >= 2.1.0 ``` and run ``` @@ -1456,7 +1456,7 @@ git submodule add https://github.com/JohnEstropia/CoreStore.git - - # Changesets ### Upgrading from 1.x.x to 2.x.x **Obsoleted** diff --git a/Sources/Info.plist b/Sources/Info.plist index 241ef86..449c7b6 100644 --- a/Sources/Info.plist +++ b/Sources/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 2.0.4 + 2.1.1 CFBundleSignature ???? CFBundleVersion diff --git a/Sources/Internal/CoreStoreFetchRequest.swift b/Sources/Internal/CoreStoreFetchRequest+CoreStore.swift similarity index 100% rename from Sources/Internal/CoreStoreFetchRequest.swift rename to Sources/Internal/CoreStoreFetchRequest+CoreStore.swift diff --git a/Sources/Internal/FetchedResultsControllerDelegate.swift b/Sources/Internal/FetchedResultsControllerDelegate.swift index 453c908..3d8a8a5 100644 --- a/Sources/Internal/FetchedResultsControllerDelegate.swift +++ b/Sources/Internal/FetchedResultsControllerDelegate.swift @@ -132,6 +132,16 @@ internal final class FetchedResultsControllerDelegate *safeAffectedStores; + +@end + + #endif /* CoreStoreBridge_h */ diff --git a/Sources/ObjectiveC/CoreStoreBridge.m b/Sources/ObjectiveC/CoreStoreBridge.m index 6c770c5..2ded9b0 100644 --- a/Sources/ObjectiveC/CoreStoreBridge.m +++ b/Sources/ObjectiveC/CoreStoreBridge.m @@ -26,23 +26,8 @@ #import "CoreStoreBridge.h" -#if USE_FRAMEWORKS #import -#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 @@ -233,3 +218,40 @@ CSWhere *_Nonnull CSWherePredicate(NSPredicate *_Nonnull predicate) CORESTORE_RE return [[CSWhere alloc] initWithPredicate:predicate]; } + + +#pragma mark CoreStoreFetchRequest + +@interface _CSFetchRequest () + +@property (nullable, nonatomic, copy) NSArray *safeAffectedStores; +@property (nullable, nonatomic, assign) CFArrayRef releaseArray; + +@end + +@implementation _CSFetchRequest + +// MARK: NSFetchRequest + +- (void)setAffectedStores:(NSArray *_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 diff --git a/Sources/Observing/ListMonitor.swift b/Sources/Observing/ListMonitor.swift index d91d196..415a01c 100644 --- a/Sources/Observing/ListMonitor.swift +++ b/Sources/Observing/ListMonitor.swift @@ -1068,7 +1068,7 @@ public final class ListMonitor: Hashable { self.isPersistentStoreChanging = true 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 } @@ -1089,7 +1089,7 @@ public final class ListMonitor: Hashable { if !self.isPendingRefetch { - let previousStores = Set(self.fetchedResultsController.fetchRequest.affectedStores ?? []) + let previousStores = Set((self.fetchedResultsController.fetchRequest as! CoreStoreFetchRequest).safeAffectedStores ?? []) let currentStores = previousStores .subtracting(note.userInfo?[NSRemovedPersistentStoresKey] as? [NSPersistentStore] ?? []) .union(note.userInfo?[NSAddedPersistentStoresKey] as? [NSPersistentStore] ?? [])