diff --git a/PSCCoreData.podspec b/PSCCoreData.podspec new file mode 100644 index 0000000..99842e5 --- /dev/null +++ b/PSCCoreData.podspec @@ -0,0 +1,23 @@ +Pod::Spec.new do |s| + s.platform = :ios, '11.0' + s.ios.deployment_target = '11.0' + s.name = "PSCCoreData" + s.version = "1.0.15" + s.license = 'MIT' + s.summary = "Helper for managing the CoreData Stack." + s.homepage = "https://github.com/PocketScientists/PSCCoreDataStack.git" + s.description = + 'Helper for managing the CoreData Stack. Contains extensions for NSManagedObject and NSManagedObjectContext' + s.authors = { + 'Jürgen Falb' => 'j.falb@nousdigital.net', + 'Philip Messlehner' => 'p.messlehner@pocketscience.com' + } + s.source = { :git => "https://github.com/PocketScientists/PSCCoreDataStack.git", :tag => '1.0.15' } + s.source_files = 'PSCCoreDataStack/*.{h,m}', 'PSCCoreData/PSCCoreData.h' + + s.public_header_files = 'PSCCoreDataStack/*.{h}', 'PSCCoreData/PSCCoreData.h' + + s.frameworks = 'CoreData', 'Foundation', 'UIKit' + + s.requires_arc = true +end diff --git a/PSCCoreData/Info.plist b/PSCCoreData/Info.plist new file mode 100644 index 0000000..910e827 --- /dev/null +++ b/PSCCoreData/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0.15 + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSPrincipalClass + + + diff --git a/PSCCoreData/PSCCoreData.h b/PSCCoreData/PSCCoreData.h new file mode 100644 index 0000000..51a764f --- /dev/null +++ b/PSCCoreData/PSCCoreData.h @@ -0,0 +1,23 @@ +// +// PSCCoreData.h +// PSCCoreData +// +// Created by Juergen Falb on 25.12.17. +// Copyright © 2017 PocketScience. All rights reserved. +// + +#import + +//! Project version number for PSCCoreData. +FOUNDATION_EXPORT double PSCCoreDataVersionNumber; + +//! Project version string for PSCCoreData. +FOUNDATION_EXPORT const unsigned char PSCCoreDataVersionString[]; + +// In this header, you should import all the public headers of your framework using statements like #import +#import +#import +#import +#import +#import +#import diff --git a/PSCCoreDataStack.xcodeproj/project.pbxproj b/PSCCoreDataStack.xcodeproj/project.pbxproj index efef221..6117194 100644 --- a/PSCCoreDataStack.xcodeproj/project.pbxproj +++ b/PSCCoreDataStack.xcodeproj/project.pbxproj @@ -9,11 +9,6 @@ /* Begin PBXBuildFile section */ 9B17A9F617025C8300DEF0B9 /* PSCPersistenceOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B17A9F517025C8300DEF0B9 /* PSCPersistenceOperation.m */; }; 9B5FDB1A16FC65AB002FA5A6 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9B5FDB1916FC65AB002FA5A6 /* Foundation.framework */; }; - 9B5FDB2916FC65AC002FA5A6 /* SenTestingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9B5FDB2816FC65AC002FA5A6 /* SenTestingKit.framework */; }; - 9B5FDB2C16FC65AC002FA5A6 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9B5FDB1916FC65AB002FA5A6 /* Foundation.framework */; }; - 9B5FDB2F16FC65AC002FA5A6 /* libPSCCoreDataStack.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 9B5FDB1616FC65AB002FA5A6 /* libPSCCoreDataStack.a */; }; - 9B5FDB3516FC65AC002FA5A6 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 9B5FDB3316FC65AC002FA5A6 /* InfoPlist.strings */; }; - 9B5FDB3816FC65AC002FA5A6 /* PSCCoreDataStackTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B5FDB3716FC65AC002FA5A6 /* PSCCoreDataStackTests.m */; }; 9B5FDB4916FC65DA002FA5A6 /* NSManagedObject+PSCCoreDataHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B5FDB4216FC65DA002FA5A6 /* NSManagedObject+PSCCoreDataHelper.m */; }; 9B5FDB4A16FC65DA002FA5A6 /* NSManagedObjectContext+PSCCoreDataHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B5FDB4416FC65DA002FA5A6 /* NSManagedObjectContext+PSCCoreDataHelper.m */; }; 9B5FDB4B16FC65DA002FA5A6 /* PSCContextWatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B5FDB4616FC65DA002FA5A6 /* PSCContextWatcher.m */; }; @@ -21,18 +16,24 @@ 9B5FDB4E16FC660C002FA5A6 /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9B5FDB4D16FC660C002FA5A6 /* CoreData.framework */; }; 9B5FDB5916FC7025002FA5A6 /* PSCFetchedResultsControllerUpdater.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B5FDB5816FC7025002FA5A6 /* PSCFetchedResultsControllerUpdater.m */; }; 9B5FDB5B16FC7387002FA5A6 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9B5FDB5A16FC7387002FA5A6 /* UIKit.framework */; }; + A9BD92891FF15E9900F4B027 /* PSCCoreData.h in Headers */ = {isa = PBXBuildFile; fileRef = A9BD92871FF15E9900F4B027 /* PSCCoreData.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A9BD928D1FF15EC300F4B027 /* NSManagedObject+PSCCoreDataHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B5FDB4216FC65DA002FA5A6 /* NSManagedObject+PSCCoreDataHelper.m */; }; + A9BD928E1FF15EC600F4B027 /* NSManagedObjectContext+PSCCoreDataHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B5FDB4416FC65DA002FA5A6 /* NSManagedObjectContext+PSCCoreDataHelper.m */; }; + A9BD928F1FF15EC900F4B027 /* PSCContextWatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B5FDB4616FC65DA002FA5A6 /* PSCContextWatcher.m */; }; + A9BD92901FF15ED000F4B027 /* PSCCoreDataStack.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B5FDB4816FC65DA002FA5A6 /* PSCCoreDataStack.m */; }; + A9BD92911FF15ED500F4B027 /* PSCFetchedResultsControllerUpdater.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B5FDB5816FC7025002FA5A6 /* PSCFetchedResultsControllerUpdater.m */; }; + A9BD92921FF15ED900F4B027 /* PSCPersistenceOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B17A9F517025C8300DEF0B9 /* PSCPersistenceOperation.m */; }; + A9BD92931FF15F1100F4B027 /* NSManagedObject+PSCCoreDataHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = 9B5FDB4116FC65DA002FA5A6 /* NSManagedObject+PSCCoreDataHelper.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A9BD92941FF15F1400F4B027 /* NSManagedObjectContext+PSCCoreDataHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = 9B5FDB4316FC65DA002FA5A6 /* NSManagedObjectContext+PSCCoreDataHelper.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A9BD92951FF15F1700F4B027 /* PSCContextWatcher.h in Headers */ = {isa = PBXBuildFile; fileRef = 9B5FDB4516FC65DA002FA5A6 /* PSCContextWatcher.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A9BD92961FF15F2100F4B027 /* PSCCoreDataStack.h in Headers */ = {isa = PBXBuildFile; fileRef = 9B5FDB4716FC65DA002FA5A6 /* PSCCoreDataStack.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A9BD92971FF15F2500F4B027 /* PSCFetchedResultsControllerUpdater.h in Headers */ = {isa = PBXBuildFile; fileRef = 9B5FDB5716FC7025002FA5A6 /* PSCFetchedResultsControllerUpdater.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A9BD92981FF15F3000F4B027 /* PSCPersistenceOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 9B17A9F417025C8300DEF0B9 /* PSCPersistenceOperation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A9BD92991FF15F3300F4B027 /* PSCLogging.h in Headers */ = {isa = PBXBuildFile; fileRef = 9B6B3C56170F5496004DFAD7 /* PSCLogging.h */; }; + A9BD929A1FF15F5100F4B027 /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9B5FDB4D16FC660C002FA5A6 /* CoreData.framework */; }; + A9BD929B1FF15FEE00F4B027 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9B5FDB5A16FC7387002FA5A6 /* UIKit.framework */; }; /* End PBXBuildFile section */ -/* Begin PBXContainerItemProxy section */ - 9B5FDB2D16FC65AC002FA5A6 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 9B5FDB0E16FC65AB002FA5A6 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 9B5FDB1516FC65AB002FA5A6; - remoteInfo = PSCCoreDataStack; - }; -/* End PBXContainerItemProxy section */ - /* Begin PBXCopyFilesBuildPhase section */ 9B5FDB1416FC65AB002FA5A6 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; @@ -51,7 +52,6 @@ 9B5FDB1616FC65AB002FA5A6 /* libPSCCoreDataStack.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPSCCoreDataStack.a; sourceTree = BUILT_PRODUCTS_DIR; }; 9B5FDB1916FC65AB002FA5A6 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 9B5FDB1D16FC65AB002FA5A6 /* Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Prefix.pch; sourceTree = ""; }; - 9B5FDB2716FC65AC002FA5A6 /* PSCCoreDataStackTests.octest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PSCCoreDataStackTests.octest; sourceTree = BUILT_PRODUCTS_DIR; }; 9B5FDB2816FC65AC002FA5A6 /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = Library/Frameworks/SenTestingKit.framework; sourceTree = DEVELOPER_DIR; }; 9B5FDB3216FC65AC002FA5A6 /* PSCCoreDataStackTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "PSCCoreDataStackTests-Info.plist"; sourceTree = ""; }; 9B5FDB3416FC65AC002FA5A6 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; @@ -70,6 +70,10 @@ 9B5FDB5816FC7025002FA5A6 /* PSCFetchedResultsControllerUpdater.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PSCFetchedResultsControllerUpdater.m; sourceTree = ""; }; 9B5FDB5A16FC7387002FA5A6 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 9B6B3C56170F5496004DFAD7 /* PSCLogging.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PSCLogging.h; sourceTree = ""; }; + A96C0B40238A0B8300BF7682 /* PSCCoreData.podspec */ = {isa = PBXFileReference; lastKnownFileType = text; path = PSCCoreData.podspec; sourceTree = ""; }; + A9BD92851FF15E9900F4B027 /* PSCCoreData.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PSCCoreData.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + A9BD92871FF15E9900F4B027 /* PSCCoreData.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PSCCoreData.h; sourceTree = ""; }; + A9BD92881FF15E9900F4B027 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -83,13 +87,12 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 9B5FDB2316FC65AC002FA5A6 /* Frameworks */ = { + A9BD92811FF15E9900F4B027 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 9B5FDB2916FC65AC002FA5A6 /* SenTestingKit.framework in Frameworks */, - 9B5FDB2C16FC65AC002FA5A6 /* Foundation.framework in Frameworks */, - 9B5FDB2F16FC65AC002FA5A6 /* libPSCCoreDataStack.a in Frameworks */, + A9BD929B1FF15FEE00F4B027 /* UIKit.framework in Frameworks */, + A9BD929A1FF15F5100F4B027 /* CoreData.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -99,7 +102,9 @@ 9B5FDB0D16FC65AB002FA5A6 = { isa = PBXGroup; children = ( + A96C0B40238A0B8300BF7682 /* PSCCoreData.podspec */, 9B5FDB1B16FC65AB002FA5A6 /* PSCCoreDataStack */, + A9BD92861FF15E9900F4B027 /* PSCCoreData */, 9B5FDB1816FC65AB002FA5A6 /* Frameworks */, 9B5FDB3016FC65AC002FA5A6 /* PSCCoreDataStackTests */, 9B5FDB1716FC65AB002FA5A6 /* Products */, @@ -110,7 +115,7 @@ isa = PBXGroup; children = ( 9B5FDB1616FC65AB002FA5A6 /* libPSCCoreDataStack.a */, - 9B5FDB2716FC65AC002FA5A6 /* PSCCoreDataStackTests.octest */, + A9BD92851FF15E9900F4B027 /* PSCCoreData.framework */, ); name = Products; sourceTree = ""; @@ -174,8 +179,35 @@ name = "Supporting Files"; sourceTree = ""; }; + A9BD92861FF15E9900F4B027 /* PSCCoreData */ = { + isa = PBXGroup; + children = ( + A9BD92871FF15E9900F4B027 /* PSCCoreData.h */, + A9BD92881FF15E9900F4B027 /* Info.plist */, + ); + path = PSCCoreData; + sourceTree = ""; + }; /* End PBXGroup section */ +/* Begin PBXHeadersBuildPhase section */ + A9BD92821FF15E9900F4B027 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + A9BD92891FF15E9900F4B027 /* PSCCoreData.h in Headers */, + A9BD92931FF15F1100F4B027 /* NSManagedObject+PSCCoreDataHelper.h in Headers */, + A9BD92941FF15F1400F4B027 /* NSManagedObjectContext+PSCCoreDataHelper.h in Headers */, + A9BD92951FF15F1700F4B027 /* PSCContextWatcher.h in Headers */, + A9BD92961FF15F2100F4B027 /* PSCCoreDataStack.h in Headers */, + A9BD92971FF15F2500F4B027 /* PSCFetchedResultsControllerUpdater.h in Headers */, + A9BD92981FF15F3000F4B027 /* PSCPersistenceOperation.h in Headers */, + A9BD92991FF15F3300F4B027 /* PSCLogging.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + /* Begin PBXNativeTarget section */ 9B5FDB1516FC65AB002FA5A6 /* PSCCoreDataStack */ = { isa = PBXNativeTarget; @@ -194,24 +226,23 @@ productReference = 9B5FDB1616FC65AB002FA5A6 /* libPSCCoreDataStack.a */; productType = "com.apple.product-type.library.static"; }; - 9B5FDB2616FC65AC002FA5A6 /* PSCCoreDataStackTests */ = { + A9BD92841FF15E9900F4B027 /* PSCCoreData */ = { isa = PBXNativeTarget; - buildConfigurationList = 9B5FDB3E16FC65AC002FA5A6 /* Build configuration list for PBXNativeTarget "PSCCoreDataStackTests" */; + buildConfigurationList = A9BD928C1FF15E9900F4B027 /* Build configuration list for PBXNativeTarget "PSCCoreData" */; buildPhases = ( - 9B5FDB2216FC65AC002FA5A6 /* Sources */, - 9B5FDB2316FC65AC002FA5A6 /* Frameworks */, - 9B5FDB2416FC65AC002FA5A6 /* Resources */, - 9B5FDB2516FC65AC002FA5A6 /* ShellScript */, + A9BD92801FF15E9900F4B027 /* Sources */, + A9BD92811FF15E9900F4B027 /* Frameworks */, + A9BD92821FF15E9900F4B027 /* Headers */, + A9BD92831FF15E9900F4B027 /* Resources */, ); buildRules = ( ); dependencies = ( - 9B5FDB2E16FC65AC002FA5A6 /* PBXTargetDependency */, ); - name = PSCCoreDataStackTests; - productName = PSCCoreDataStackTests; - productReference = 9B5FDB2716FC65AC002FA5A6 /* PSCCoreDataStackTests.octest */; - productType = "com.apple.product-type.bundle"; + name = PSCCoreData; + productName = PSCCoreData; + productReference = A9BD92851FF15E9900F4B027 /* PSCCoreData.framework */; + productType = "com.apple.product-type.framework"; }; /* End PBXNativeTarget section */ @@ -219,15 +250,24 @@ 9B5FDB0E16FC65AB002FA5A6 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0460; + LastTestingUpgradeCheck = 0510; + LastUpgradeCheck = 1020; ORGANIZATIONNAME = PocketScience; + TargetAttributes = { + A9BD92841FF15E9900F4B027 = { + CreatedOnToolsVersion = 9.2; + DevelopmentTeam = Y6BEBK9HD8; + ProvisioningStyle = Automatic; + }; + }; }; buildConfigurationList = 9B5FDB1116FC65AB002FA5A6 /* Build configuration list for PBXProject "PSCCoreDataStack" */; compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; + developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, + Base, ); mainGroup = 9B5FDB0D16FC65AB002FA5A6; productRefGroup = 9B5FDB1716FC65AB002FA5A6 /* Products */; @@ -235,38 +275,21 @@ projectRoot = ""; targets = ( 9B5FDB1516FC65AB002FA5A6 /* PSCCoreDataStack */, - 9B5FDB2616FC65AC002FA5A6 /* PSCCoreDataStackTests */, + A9BD92841FF15E9900F4B027 /* PSCCoreData */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ - 9B5FDB2416FC65AC002FA5A6 /* Resources */ = { + A9BD92831FF15E9900F4B027 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 9B5FDB3516FC65AC002FA5A6 /* InfoPlist.strings in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ -/* Begin PBXShellScriptBuildPhase section */ - 9B5FDB2516FC65AC002FA5A6 /* ShellScript */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "# Run the unit tests in this test bundle.\n\"${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests\"\n"; - }; -/* End PBXShellScriptBuildPhase section */ - /* Begin PBXSourcesBuildPhase section */ 9B5FDB1216FC65AB002FA5A6 /* Sources */ = { isa = PBXSourcesBuildPhase; @@ -281,24 +304,21 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 9B5FDB2216FC65AC002FA5A6 /* Sources */ = { + A9BD92801FF15E9900F4B027 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 9B5FDB3816FC65AC002FA5A6 /* PSCCoreDataStackTests.m in Sources */, + A9BD92901FF15ED000F4B027 /* PSCCoreDataStack.m in Sources */, + A9BD928D1FF15EC300F4B027 /* NSManagedObject+PSCCoreDataHelper.m in Sources */, + A9BD928E1FF15EC600F4B027 /* NSManagedObjectContext+PSCCoreDataHelper.m in Sources */, + A9BD928F1FF15EC900F4B027 /* PSCContextWatcher.m in Sources */, + A9BD92921FF15ED900F4B027 /* PSCPersistenceOperation.m in Sources */, + A9BD92911FF15ED500F4B027 /* PSCFetchedResultsControllerUpdater.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ -/* Begin PBXTargetDependency section */ - 9B5FDB2E16FC65AC002FA5A6 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 9B5FDB1516FC65AB002FA5A6 /* PSCCoreDataStack */; - targetProxy = 9B5FDB2D16FC65AC002FA5A6 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - /* Begin PBXVariantGroup section */ 9B5FDB3316FC65AC002FA5A6 /* InfoPlist.strings */ = { isa = PBXVariantGroup; @@ -315,27 +335,44 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ENABLE_OBJC_ARC = YES; + 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_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; COPY_PHASE_STRIP = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; + 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 = 5.0; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; }; @@ -345,20 +382,36 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ENABLE_OBJC_ARC = YES; + 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_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; COPY_PHASE_STRIP = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; + 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 = 5.0; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; SDKROOT = iphoneos; VALIDATE_PRODUCT = YES; }; @@ -388,33 +441,83 @@ }; name = Release; }; - 9B5FDB3F16FC65AC002FA5A6 /* Debug */ = { + A9BD928A1FF15E9900F4B027 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - FRAMEWORK_SEARCH_PATHS = ( - "\"$(SDKROOT)/Developer/Library/Frameworks\"", - "\"$(DEVELOPER_LIBRARY_DIR)/Frameworks\"", - ); - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "PSCCoreDataStack/PSCCoreDataStack-Prefix.pch"; - INFOPLIST_FILE = "PSCCoreDataStackTests/PSCCoreDataStackTests-Info.plist"; - PRODUCT_NAME = "$(TARGET_NAME)"; - WRAPPER_EXTENSION = octest; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = Y6BEBK9HD8; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + INFOPLIST_FILE = PSCCoreData/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 10.3; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.nousdigital.PSCCoreData; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; }; name = Debug; }; - 9B5FDB4016FC65AC002FA5A6 /* Release */ = { + A9BD928B1FF15E9900F4B027 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - FRAMEWORK_SEARCH_PATHS = ( - "\"$(SDKROOT)/Developer/Library/Frameworks\"", - "\"$(DEVELOPER_LIBRARY_DIR)/Frameworks\"", - ); - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "PSCCoreDataStack/PSCCoreDataStack-Prefix.pch"; - INFOPLIST_FILE = "PSCCoreDataStackTests/PSCCoreDataStackTests-Info.plist"; - PRODUCT_NAME = "$(TARGET_NAME)"; - WRAPPER_EXTENSION = octest; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = Y6BEBK9HD8; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_NS_ASSERTIONS = NO; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + INFOPLIST_FILE = PSCCoreData/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 10.3; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = com.nousdigital.PSCCoreData; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; }; name = Release; }; @@ -439,11 +542,11 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 9B5FDB3E16FC65AC002FA5A6 /* Build configuration list for PBXNativeTarget "PSCCoreDataStackTests" */ = { + A9BD928C1FF15E9900F4B027 /* Build configuration list for PBXNativeTarget "PSCCoreData" */ = { isa = XCConfigurationList; buildConfigurations = ( - 9B5FDB3F16FC65AC002FA5A6 /* Debug */, - 9B5FDB4016FC65AC002FA5A6 /* Release */, + A9BD928A1FF15E9900F4B027 /* Debug */, + A9BD928B1FF15E9900F4B027 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; diff --git a/PSCCoreDataStack.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/PSCCoreDataStack.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/PSCCoreDataStack.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/PSCCoreDataStack.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/PSCCoreDataStack.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/PSCCoreDataStack.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/PSCCoreDataStack.xcodeproj/project.xcworkspace/xcshareddata/PSCCoreDataStack.xcscmblueprint b/PSCCoreDataStack.xcodeproj/project.xcworkspace/xcshareddata/PSCCoreDataStack.xcscmblueprint new file mode 100644 index 0000000..baf20a5 --- /dev/null +++ b/PSCCoreDataStack.xcodeproj/project.xcworkspace/xcshareddata/PSCCoreDataStack.xcscmblueprint @@ -0,0 +1,30 @@ +{ + "DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey" : "D261E0A4710B0DA4CAA16F150E6AB7046AB2576A", + "DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey" : { + + }, + "DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey" : { + "D261E0A4710B0DA4CAA16F150E6AB7046AB2576A" : 9223372036854775807, + "5CAD9AD776377F08EC40032FFD796FFA54F88822" : 9223372036854775807 + }, + "DVTSourceControlWorkspaceBlueprintIdentifierKey" : "5385F887-07A2-4B63-A6A2-92D5CD1792C8", + "DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : { + "D261E0A4710B0DA4CAA16F150E6AB7046AB2576A" : "PSCCoreDataStack\/", + "5CAD9AD776377F08EC40032FFD796FFA54F88822" : "" + }, + "DVTSourceControlWorkspaceBlueprintNameKey" : "PSCCoreDataStack", + "DVTSourceControlWorkspaceBlueprintVersion" : 204, + "DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : "PSCCoreDataStack.xcodeproj", + "DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey" : [ + { + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/sources-headless.app.redbull.com\/scm\/fft\/bullchecker-client.git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "5CAD9AD776377F08EC40032FFD796FFA54F88822" + }, + { + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/sources-headless.app.redbull.com\/scm\/fft\/psccoredatastack.git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "D261E0A4710B0DA4CAA16F150E6AB7046AB2576A" + } + ] +} \ No newline at end of file diff --git a/PSCCoreDataStack.xcodeproj/xcshareddata/xcschemes/PSCCoreData.xcscheme b/PSCCoreDataStack.xcodeproj/xcshareddata/xcschemes/PSCCoreData.xcscheme new file mode 100644 index 0000000..1bb0a44 --- /dev/null +++ b/PSCCoreDataStack.xcodeproj/xcshareddata/xcschemes/PSCCoreData.xcscheme @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PSCCoreDataStack/NSManagedObject+PSCCoreDataHelper.h b/PSCCoreDataStack/NSManagedObject+PSCCoreDataHelper.h index a63857b..9825918 100644 --- a/PSCCoreDataStack/NSManagedObject+PSCCoreDataHelper.h +++ b/PSCCoreDataStack/NSManagedObject+PSCCoreDataHelper.h @@ -5,38 +5,41 @@ // Created by Philip Messlehner on 28.02.13. // Copyright (c) 2013 Philip Messlehner. All rights reserved. // - +#import @class PSCContextWatcher; -typedef void(^psc_request_block)(NSFetchRequest *fetchRequest); +typedef void(^psc_request_block)(NSFetchRequest * _Nonnull fetchRequest); +NS_ASSUME_NONNULL_BEGIN @interface NSManagedObject (PSCCoreDataHelper) @property (nonatomic, readonly) NSManagedObjectID *permanentObjectID; -+ (instancetype)newObjectInContext:(NSManagedObjectContext *)context; -+ (instancetype)existingOrNewObjectWithAttribute:(NSString *)attribute matchingValue:(id)value inContext:(NSManagedObjectContext *)context; ++ (instancetype _Nonnull)newObjectInContext:(NSManagedObjectContext *)context; ++ (instancetype _Nonnull)existingOrNewObjectWithAttribute:(NSString *)attribute matchingValue:(nullable id)value inContext:(NSManagedObjectContext *)context; -+ (NSUInteger)deleteAllMatchingPredicate:(NSPredicate *)predicate - requestConfiguration:(psc_request_block)requestConfigurationBlock ++ (NSUInteger)deleteAllMatchingPredicate:(nullable NSPredicate *)predicate + requestConfiguration:(nullable psc_request_block)requestConfigurationBlock inContext:(NSManagedObjectContext *)context - error:(NSError **)error; -+ (NSUInteger)deleteAllMatchingPredicate:(NSPredicate *)predicate inContext:(NSManagedObjectContext *)context error:(NSError **)error; + error:(NSError * _Nullable * _Nullable)error; ++ (NSUInteger)deleteAllMatchingPredicate:(nullable NSPredicate *)predicate inContext:(NSManagedObjectContext *)context error:(NSError * _Nullable * _Nullable)error; -+ (NSFetchRequest *)requestAllMatchingPredicate:(NSPredicate *)predicate error:(NSError **)error; -+ (NSFetchRequest *)requestFirstMatchingPredicate:(NSPredicate *)predicate error:(NSError **)error; ++ (NSFetchRequest *)requestAllMatchingPredicate:(nullable NSPredicate *)predicate error:(NSError * _Nullable * _Nullable)error; ++ (NSFetchRequest *)requestBatchOfSize:(NSUInteger)batchSize atOffset:(NSUInteger)offset withMatchingPredicate:(nullable NSPredicate *)predicate error:(NSError * _Nullable *)error; ++ (NSFetchRequest *)requestFirstMatchingPredicate:(nullable NSPredicate *)predicate error:(NSError * _Nullable * _Nullable)error; -+ (NSArray *)fetchAllMatchingPredicate:(NSPredicate *)predicate - requestConfiguration:(psc_request_block)requestConfigurationBlock - inContext:(NSManagedObjectContext *)context - error:(NSError **)error; -+ (NSArray *)fetchAllMatchingPredicate:(NSPredicate *)predicate inContext:(NSManagedObjectContext *)context error:(NSError **)error; -+ (instancetype)fetchFirstMatchingPredicate:(NSPredicate *)predicate inContext:(NSManagedObjectContext *)context error:(NSError **)error; ++ (nullable NSArray *)fetchAllMatchingPredicate:(nullable NSPredicate *)predicate + requestConfiguration:(nullable psc_request_block)requestConfigurationBlock + inContext:(NSManagedObjectContext *)context + error:(NSError * _Nullable * _Nullable)error; ++ (nullable NSArray *)fetchAllMatchingPredicate:(nullable NSPredicate *)predicate inContext:(NSManagedObjectContext *)context error:(NSError * _Nullable * _Nullable)error; ++ (nullable instancetype)fetchFirstMatchingPredicate:(nullable NSPredicate *)predicate inContext:(NSManagedObjectContext *)context error:(NSError * _Nullable * _Nullable)error; ++ (NSArray *)fetchBatchOfSize:(NSUInteger)batchSize atOffset:(NSUInteger)offset withMatchingPredicate:(nullable NSPredicate *)predicate inContext:(NSManagedObjectContext *)context error:(NSError * _Nullable *)error; -+ (NSUInteger)countOfObjectsMatchingPredicate:(NSPredicate *)predicate inContext:(NSManagedObjectContext *)context error:(NSError **)error; ++ (NSUInteger)countOfObjectsMatchingPredicate:(nullable NSPredicate *)predicate inContext:(NSManagedObjectContext *)context error:(NSError * _Nullable * _Nullable)error; /** High-level action to update the data in Core Data based on an array of dictionaries. @@ -57,9 +60,9 @@ typedef void(^psc_request_block)(NSFetchRequest *fetchRequest); deleteEntitiesNotInDictionary:(BOOL)deleteEntitiesNotInDictionary entityKeyInDictionary:(NSString *)dictionaryIDKeyPath entityKeyInDatabase:(NSString *)databaseIDKey - context:(NSManagedObjectContext *)contex + context:(NSManagedObjectContext *)context updateBlock:(void(^)(id managedObject, NSDictionary *data))updateBlock - error:(NSError **)error; + error:(NSError * _Nullable * _Nullable)error; - (void)reset; - (void)deleteFromContext; @@ -67,3 +70,5 @@ typedef void(^psc_request_block)(NSFetchRequest *fetchRequest); - (id)userInfoValueForKey:(NSString *)key ofProperty:(NSString *)property; @end + +NS_ASSUME_NONNULL_END diff --git a/PSCCoreDataStack/NSManagedObject+PSCCoreDataHelper.m b/PSCCoreDataStack/NSManagedObject+PSCCoreDataHelper.m index 65e03e4..d47407a 100644 --- a/PSCCoreDataStack/NSManagedObject+PSCCoreDataHelper.m +++ b/PSCCoreDataStack/NSManagedObject+PSCCoreDataHelper.m @@ -17,13 +17,13 @@ @implementation NSManagedObject (PSCCoreDataHelper) #pragma mark - Class Methods //////////////////////////////////////////////////////////////////////// -+ (instancetype)newObjectInContext:(NSManagedObjectContext *)context { ++ (instancetype _Nonnull)newObjectInContext:(NSManagedObjectContext *)context { NSParameterAssert(context != nil); return [NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass([self class]) inManagedObjectContext:context]; } -+ (instancetype)existingOrNewObjectWithAttribute:(NSString *)attribute matchingValue:(id)value inContext:(NSManagedObjectContext *)context { ++ (instancetype _Nonnull)existingOrNewObjectWithAttribute:(NSString *)attribute matchingValue:(id)value inContext:(NSManagedObjectContext *)context { NSParameterAssert(attribute != nil); NSParameterAssert(context != nil); @@ -46,7 +46,7 @@ + (instancetype)existingOrNewObjectWithAttribute:(NSString *)attribute matchingV [object setValue:value forKey:attribute]; } - return object; + return (id _Nonnull)object; } + (NSUInteger)deleteAllMatchingPredicate:(NSPredicate *)predicate requestConfiguration:(psc_request_block)requestConfigurationBlock inContext:(NSManagedObjectContext *)context error:(__autoreleasing NSError **)error { @@ -86,6 +86,16 @@ + (NSFetchRequest *)requestAllMatchingPredicate:(NSPredicate *)predicate error:( return request; } ++ (NSFetchRequest *)requestBatchOfSize:(NSUInteger)batchSize atOffset:(NSUInteger)offset withMatchingPredicate:(NSPredicate *)predicate error:(__autoreleasing NSError **)error { + NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass([self class])]; + + request.fetchLimit = batchSize; + request.fetchOffset = offset; + request.predicate = predicate; + + return request; +} + + (NSFetchRequest *)requestFirstMatchingPredicate:(NSPredicate *)predicate error:(NSError **)error { NSFetchRequest *request = [self requestAllMatchingPredicate:predicate error:error]; @@ -109,6 +119,13 @@ + (NSArray *)fetchAllMatchingPredicate:(NSPredicate *)predicate inContext:(NSMan return [self fetchAllMatchingPredicate:predicate requestConfiguration:nil inContext:context error:error]; } ++ (NSArray *)fetchBatchOfSize:(NSUInteger)batchSize atOffset:(NSUInteger)offset withMatchingPredicate:(NSPredicate *)predicate inContext:(NSManagedObjectContext *)context error:(__autoreleasing NSError **)error { + NSFetchRequest *request = [self requestBatchOfSize:batchSize atOffset:offset withMatchingPredicate:predicate error:error]; + + NSArray *objects = [context executeFetchRequest:request error:error]; + return objects; +} + + (instancetype)fetchFirstMatchingPredicate:(NSPredicate *)predicate inContext:(NSManagedObjectContext *)context error:(NSError **)error { NSFetchRequest *fetchRequest = [self requestFirstMatchingPredicate:predicate error:error]; diff --git a/PSCCoreDataStack/NSManagedObjectContext+PSCCoreDataHelper.h b/PSCCoreDataStack/NSManagedObjectContext+PSCCoreDataHelper.h index 666081d..cab50e8 100644 --- a/PSCCoreDataStack/NSManagedObjectContext+PSCCoreDataHelper.h +++ b/PSCCoreDataStack/NSManagedObjectContext+PSCCoreDataHelper.h @@ -5,16 +5,20 @@ // Created by Philip Messlehner on 28.02.13. // Copyright (c) 2013 Philip Messlehner. All rights reserved. // +#import +NS_ASSUME_NONNULL_BEGIN @interface NSManagedObjectContext (PSCCoreDataHelper) -- (NSManagedObjectContext *)newChildContextWithConcurrencyType:(NSUInteger)concurrencyType; +- (NSManagedObjectContext *)newChildContextWithConcurrencyType:(NSManagedObjectContextConcurrencyType)concurrencyType; -- (BOOL)saveAndPropagateToParentContextBlocking:(BOOL)wait error:(NSError **)error __attribute__((deprecated("use 'saveAndPropagateToParentContextBlocking:success:failure' instead"))); -- (BOOL)saveAndPropagateToParentContext:(NSError **)error __attribute__((deprecated("use 'saveAndPropagateToParentContexWithSuccess:failure' instead"))); +- (void)saveAndPropagateToParentContextBlocking:(BOOL)wait error:(NSError * _Nullable * _Nullable)error __attribute__((deprecated("use 'saveAndPropagateToParentContextBlocking:success:failure' instead"))); +- (void)saveAndPropagateToParentContext:(NSError * _Nullable * _Nullable)error __attribute__((deprecated("use 'saveAndPropagateToParentContexWithSuccess:failure' instead"))); -- (BOOL)saveAndPropagateToParentContextBlocking:(BOOL)wait success:(void(^)())sucess failure:(void(^)(NSError *error))failure; -- (BOOL)saveAndPropagateToParentContextWithSuccess:(void(^)())sucess failure:(void(^)(NSError *error))failure; +- (void)saveAndPropagateToParentContextBlocking:(BOOL)wait success:(nullable void(^)(void))sucess failure:(nullable void(^)(NSError *error))failure; +- (void)saveAndPropagateToParentContextWithSuccess:(nullable void(^)(void))sucess failure:(nullable void(^)(NSError *error))failure; @end + +NS_ASSUME_NONNULL_END diff --git a/PSCCoreDataStack/NSManagedObjectContext+PSCCoreDataHelper.m b/PSCCoreDataStack/NSManagedObjectContext+PSCCoreDataHelper.m index 473546b..b0d8f6f 100644 --- a/PSCCoreDataStack/NSManagedObjectContext+PSCCoreDataHelper.m +++ b/PSCCoreDataStack/NSManagedObjectContext+PSCCoreDataHelper.m @@ -11,99 +11,118 @@ @implementation NSManagedObjectContext (PSCCoreDataHelper) -- (NSManagedObjectContext *)newChildContextWithConcurrencyType:(NSUInteger)concurrencyType { +- (NSManagedObjectContext *)newChildContextWithConcurrencyType:(NSManagedObjectContextConcurrencyType)concurrencyType { NSManagedObjectContext *childContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:concurrencyType]; childContext.parentContext = self; return childContext; } -- (BOOL)saveAndPropagateToParentContextBlocking:(BOOL)wait error:(__autoreleasing NSError **)error { - __block BOOL success = YES; - - if (self.hasChanges) { - if (self.concurrencyType == NSConfinementConcurrencyType) { - success = [self save:error]; - } else { - [self performBlockAndWait:^{ - success = [self save:error]; +- (void)saveAndPropagateToParentContextBlocking:(BOOL)wait error:(__autoreleasing NSError **)error { + dispatch_block_t parentCheck = ^{ + if (wait) { + [self.parentContext performBlockAndWait:^{ + if (self.parentContext.hasChanges) { + [self.parentContext save:error]; + } }]; - } - } - - if (!success) { - return NO; - } - - if (self.parentContext.hasChanges) { - dispatch_block_t saveParent = ^{ - success = [self.parentContext save:error]; - }; - - if (self.parentContext.concurrencyType == NSConfinementConcurrencyType) { - saveParent(); - } else if (wait) { - [self.parentContext performBlockAndWait:saveParent]; } else { - [self.parentContext performBlock:saveParent]; + [self.parentContext performBlock:^{ + if (self.parentContext.hasChanges) { + [self.parentContext save:error]; + } + }]; } - } + }; - return success; + if (wait) { + [self performBlockAndWait:^{ + if (self.hasChanges) { + if ([self save:error]) { + parentCheck(); + } + } + else { + parentCheck(); + } + }]; + } else { + [self performBlock:^{ + if (self.hasChanges) { + if ([self save:error]) { + parentCheck(); + } + } + else { + parentCheck(); + } + }]; + } } -- (BOOL)saveAndPropagateToParentContext:(__autoreleasing NSError **)error { - return [self saveAndPropagateToParentContextBlocking:NO error:error]; +- (void)saveAndPropagateToParentContext:(__autoreleasing NSError **)error { + [self saveAndPropagateToParentContextBlocking:NO error:error]; } -- (BOOL)saveAndPropagateToParentContextBlocking:(BOOL)wait success:(void(^)())successBlock failure:(void(^)(NSError *error))failureBlock { - __block BOOL success = YES; - __block NSError *error = nil; - if (self.hasChanges) { - if (self.concurrencyType == NSConfinementConcurrencyType) { - success = [self save:&error]; +- (void)saveAndPropagateToParentContextBlocking:(BOOL)wait success:(void(^)(void))successBlock failure:(void(^)(NSError *error))failureBlock { + dispatch_block_t parentCheck = ^{ + dispatch_block_t saveParent = ^{ + if (self.parentContext.hasChanges) { + NSError *error = nil; + if ([self.parentContext save:&error]) { + if (successBlock) { + successBlock(); + } + } else if (failureBlock) { + failureBlock(error); + } + } else if (successBlock) { + successBlock(); + } + }; + + if (wait) { + [self.parentContext performBlockAndWait: saveParent]; } else { - [self performBlockAndWait:^{ - success = [self save:&error]; - }]; + [self.parentContext performBlock: saveParent]; } - } + }; - if (!success) { - if (failureBlock) { - failureBlock(error); + dispatch_block_t saveChild = ^{ + NSError *error = nil; + if ([self save:&error]) { + parentCheck(); } - return NO; - } - - if (self.parentContext.hasChanges) { - dispatch_block_t saveParent = ^{ - success = [self.parentContext save:&error]; - if (success) { - if (successBlock) { - successBlock(); - } - } else if (failureBlock) { + else { + if (failureBlock) { failureBlock(error); } - }; - - if (self.parentContext.concurrencyType == NSConfinementConcurrencyType) { - saveParent(); - } else if (wait) { - [self.parentContext performBlockAndWait:saveParent]; - } else { - [self.parentContext performBlock:saveParent]; } - } else if (success && successBlock) { - successBlock(); + }; + + if (wait) { + [self performBlockAndWait:^{ + if (self.hasChanges) { + saveChild(); + } + else { + parentCheck(); + } + }]; + } else { + [self performBlock:^{ + if (self.hasChanges) { + saveChild(); + } + else { + parentCheck(); + } + }]; } - - return success; } -- (BOOL)saveAndPropagateToParentContextWithSuccess:(void(^)())successBlock failure:(void(^)(NSError *error))failureBlock { - return [self saveAndPropagateToParentContextBlocking:NO success:successBlock failure:failureBlock]; +- (void)saveAndPropagateToParentContextWithSuccess:(void(^)(void))successBlock failure:(void(^)(NSError *error))failureBlock { + [self saveAndPropagateToParentContextBlocking:NO success:successBlock failure:failureBlock]; } @end diff --git a/PSCCoreDataStack/PSCContextWatcher.h b/PSCCoreDataStack/PSCContextWatcher.h index 10f2df6..d26e4b1 100644 --- a/PSCCoreDataStack/PSCContextWatcher.h +++ b/PSCCoreDataStack/PSCContextWatcher.h @@ -27,14 +27,16 @@ // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. +#import @protocol PSCContextWatcherDelegate; +NS_ASSUME_NONNULL_BEGIN @interface PSCContextWatcher : NSObject -@property (nonatomic, weak) id delegate; +@property (nullable, nonatomic, weak) id delegate; + (instancetype)watcherWithContext:(NSManagedObjectContext *)context; - (instancetype)initWithManagedObjectContext:(NSManagedObjectContext *)context; @@ -52,9 +54,11 @@ @protocol PSCContextWatcherDelegate - (void)contextWatcher:(PSCContextWatcher *)watcher - observedInsertions:(NSSet *)inserts - deletions:(NSSet *)deletions - updates:(NSSet *)updates + observedInsertions:(nullable NSSet *)inserts + deletions:(nullable NSSet *)deletions + updates:(nullable NSSet *)updates inContext:(NSManagedObjectContext *)context; @end + +NS_ASSUME_NONNULL_END diff --git a/PSCCoreDataStack/PSCCoreDataStack.h b/PSCCoreDataStack/PSCCoreDataStack.h index c726ae9..007c833 100644 --- a/PSCCoreDataStack/PSCCoreDataStack.h +++ b/PSCCoreDataStack/PSCCoreDataStack.h @@ -14,28 +14,34 @@ #import "PSCFetchedResultsControllerUpdater.h" #import "PSCPersistenceOperation.h" +NS_ASSUME_NONNULL_BEGIN @interface PSCCoreDataStack : NSObject + (void)setupWithModelURL:(NSURL *)modelURL - storeFileName:(NSString *)storeFileName + storeFileName:(nullable NSString *)storeFileName type:(NSString *)storeType - configuration:(NSString *)configuration - options:(NSDictionary *)options - success:(void(^)())successBlock - error:(void(^)(NSError *error))errorBlock; + storeURL:(nullable NSURL *)storeURL + configuration:(nullable NSString *)configuration + options:(nullable NSDictionary *)options + success:(nullable void(^)(void))successBlock + error:(nullable void(^)(NSError *error))errorBlock; + (void)setupWithModelURL:(NSURL *)modelURL autoMigratedSQLiteStoreFileName:(NSString *)storeFileName - success:(void(^)())successBlock error:(void(^)(NSError *error))errorBlock; + success:(nullable void(^)(void))successBlock error:(nullable void(^)(NSError *error))errorBlock; + (void)saveAndPersistContextBlocking:(BOOL)wait; + (void)saveAndPersistContext; -+ (void)saveAndPersistContextBlocking:(BOOL)wait success:(void(^)())sucessBlock error:(void(^)(NSError *error))errorBlock; -+ (void)saveAndPersistContextWithSuccess:(void(^)())sucessBlock error:(void(^)(NSError *error))errorBlock; ++ (void)saveAndPersistContextBlocking:(BOOL)wait success:(nullable void(^)(void))sucessBlock error:(nullable void(^)(NSError *error))errorBlock; ++ (void)saveAndPersistContextWithSuccess:(nullable void(^)(void))sucessBlock error:(nullable void(^)(NSError *error))errorBlock; + (NSManagedObjectContext *)mainContext; + (NSManagedObjectContext *)newChildContextWithPrivateQueue; ++ (void)migratePersistentStoreToURL:(NSURL *)storeURL; + @end + +NS_ASSUME_NONNULL_END diff --git a/PSCCoreDataStack/PSCCoreDataStack.m b/PSCCoreDataStack/PSCCoreDataStack.m index b8de2d7..9e15965 100644 --- a/PSCCoreDataStack/PSCCoreDataStack.m +++ b/PSCCoreDataStack/PSCCoreDataStack.m @@ -23,47 +23,51 @@ @implementation PSCCoreDataStack + (void)setupWithModelURL:(NSURL *)modelURL storeFileName:(NSString *)storeFileName type:(NSString *)storeType + storeURL:(NSURL *)storeURL configuration:(NSString *)configuration options:(NSDictionary *)options - success:(void(^)())successBlock + success:(void(^)(void))successBlock error:(void(^)(NSError *error))errorBlock { - + NSParameterAssert(modelURL != nil); NSParameterAssert([storeType isEqualToString:NSSQLiteStoreType] || [storeType isEqualToString:NSBinaryStoreType] || [storeType isEqualToString:NSInMemoryStoreType]); if (![storeType isEqualToString:NSInMemoryStoreType]) { - NSParameterAssert(storeFileName != nil); + NSParameterAssert((storeFileName != nil) != (storeURL != nil)); } - + NSManagedObjectModel *model = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]; NSAssert(model != nil, @"Failed to initialize model with URL: %@", modelURL); - + NSPersistentStoreCoordinator *persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model]; NSAssert(persistentStoreCoordinator != nil, @"Failed to initialize persistent store coordinator with model: %@", model); - + psc_privateContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; psc_privateContext.persistentStoreCoordinator = persistentStoreCoordinator; - + psc_mainContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; psc_mainContext.parentContext = psc_privateContext; - + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - NSURL *storeURL = nil; - - if (storeFileName != nil) { - storeURL = [[[NSFileManager new] URLsForDirectory:NSLibraryDirectory inDomains:NSUserDomainMask] lastObject]; - storeURL = [storeURL URLByAppendingPathComponent:storeFileName]; + __block NSURL *url = storeURL; + + if (url == nil) { + url = [[[NSFileManager new] URLsForDirectory:NSLibraryDirectory inDomains:NSUserDomainMask] lastObject]; + + if(storeFileName != nil) { + url = [url URLByAppendingPathComponent:storeFileName]; + } } - + NSError *error = nil; NSPersistentStore *store = [persistentStoreCoordinator addPersistentStoreWithType:storeType configuration:configuration - URL:storeURL + URL:url options:options error:&error]; - + if (store == nil) { PSCCDLog(@"Error adding persistent store to coordinator %@\n%@", [error localizedDescription], [error userInfo]); - + if (errorBlock != nil) { dispatch_async(dispatch_get_main_queue(), ^{ errorBlock(error); @@ -77,12 +81,13 @@ + (void)setupWithModelURL:(NSURL *)modelURL }); } -+ (void)setupWithModelURL:(NSURL *)modelURL autoMigratedSQLiteStoreFileName:(NSString *)storeFileName success:(void(^)())successBlock error:(void(^)(NSError *error))errorBlock { ++ (void)setupWithModelURL:(NSURL *)modelURL autoMigratedSQLiteStoreFileName:(NSString *)storeFileName success:(void(^)(void))successBlock error:(void(^)(NSError *error))errorBlock { NSDictionary *options = @{NSMigratePersistentStoresAutomaticallyOption: @(YES), NSInferMappingModelAutomaticallyOption: @(YES)}; - + [self setupWithModelURL:modelURL storeFileName:storeFileName type:NSSQLiteStoreType + storeURL:nil configuration:nil options:options success:successBlock @@ -101,7 +106,7 @@ + (void)saveAndPersistContext { [self saveAndPersistContextBlocking:NO]; } -+ (void)saveAndPersistContextBlocking:(BOOL)wait success:(void(^)())sucessBlock error:(void(^)(NSError *error))errorBlock { ++ (void)saveAndPersistContextBlocking:(BOOL)wait success:(void(^)(void))sucessBlock error:(void(^)(NSError *error))errorBlock { [[self mainContext] saveAndPropagateToParentContextBlocking:wait success:sucessBlock failure:^(NSError *error) { PSCCDLog(@"%@ %@", [error localizedDescription], [error userInfo]); if (errorBlock) { @@ -110,7 +115,7 @@ + (void)saveAndPersistContextBlocking:(BOOL)wait success:(void(^)())sucessBlock }]; } -+ (void)saveAndPersistContextWithSuccess:(void(^)())sucessBlock error:(void(^)(NSError *error))errorBlock { ++ (void)saveAndPersistContextWithSuccess:(void(^)(void))sucessBlock error:(void(^)(NSError *error))errorBlock { [self saveAndPersistContextBlocking:NO success:sucessBlock error:errorBlock]; } @@ -126,4 +131,40 @@ + (NSManagedObjectContext *)newChildContextWithPrivateQueue { return [[self mainContext] newChildContextWithConcurrencyType:NSPrivateQueueConcurrencyType]; } +//////////////////////////////////////////////////////////////////////// +#pragma mark - Migration +//////////////////////////////////////////////////////////////////////// + ++ (void)migratePersistentStoreToURL:(NSURL *)storeURL { + NSPersistentStoreCoordinator *storeCoordinator = psc_privateContext.persistentStoreCoordinator; + NSArray *stores = storeCoordinator.persistentStores; + + NSAssert([stores count] == 1, @"PSCCoreDataStack doesn't support changing storeURL for multiple Stores"); + + NSPersistentStore *store = stores[0]; + + if (![store.URL isEqual:storeURL]) { + NSError *error; + [psc_privateContext.persistentStoreCoordinator migratePersistentStore:store toURL:storeURL options:nil withType:store.type error:&error]; + + NSAssert(error == nil, @"Error migrating persistent store %@ %@\n%@", psc_privateContext, [error localizedDescription], [error userInfo]); + + NSFileManager *fileManager = [NSFileManager defaultManager]; + + if ([fileManager fileExistsAtPath:[store.URL path]]) { + [fileManager removeItemAtURL:store.URL error:&error]; + } + + NSURL *shm = [[store.URL URLByDeletingPathExtension] URLByAppendingPathExtension:@"sqlite-shm"]; + if ([fileManager fileExistsAtPath:[shm path]]) { + [fileManager removeItemAtURL:shm error:&error]; + } + + NSURL *wal = [[store.URL URLByDeletingPathExtension] URLByAppendingPathExtension:@"sqlite-wal"]; + if ([fileManager fileExistsAtPath:[wal path]]) { + [fileManager removeItemAtURL:wal error:&error]; + } + } +} + @end diff --git a/PSCCoreDataStack/PSCFetchedResultsControllerUpdater.h b/PSCCoreDataStack/PSCFetchedResultsControllerUpdater.h index 4023d46..089fd97 100644 --- a/PSCCoreDataStack/PSCFetchedResultsControllerUpdater.h +++ b/PSCCoreDataStack/PSCFetchedResultsControllerUpdater.h @@ -7,6 +7,8 @@ // // Derived from MrRooni's Gist: https://gist.github.com/MrRooni/4988922 +#import + /** Controller that can be used to gather information about animated updates in a UITableView/UICollectionView. @@ -38,6 +40,8 @@ */ +NS_ASSUME_NONNULL_BEGIN + extern NSString *const PSCFetchedResultsControllerUpdaterControllerDidChangeContentNotification; @interface PSCFetchedResultsControllerUpdater : NSObject @@ -50,10 +54,10 @@ extern NSString *const PSCFetchedResultsControllerUpdaterControllerDidChangeCont @property (nonatomic, readonly) NSIndexSet *deletedSectionIndexes; @property (nonatomic, readonly) NSIndexSet *insertedSectionIndexes; -@property (nonatomic, readonly) NSArray *deletedObjectIndexPaths; -@property (nonatomic, readonly) NSArray *insertedObjectIndexPaths; -@property (nonatomic, readonly) NSArray *updatedObjectIndexPaths; -@property (nonatomic, readonly) NSArray *movedObjectIndexPaths; // only set if reportMovesAsInsertionsAndDeletions is NO +@property (nonatomic, readonly) NSArray *deletedObjectIndexPaths; +@property (nonatomic, readonly) NSArray *insertedObjectIndexPaths; +@property (nonatomic, readonly) NSArray *updatedObjectIndexPaths; +@property (nonatomic, readonly) NSArray *movedObjectIndexPaths; // only set if reportMovesAsInsertionsAndDeletions is NO - (void)reset; - (void)resetSectionChanges; @@ -68,3 +72,5 @@ extern NSString *const PSCFetchedResultsControllerUpdaterControllerDidChangeCont @property (nonatomic, strong) NSIndexPath *toIndexPath; @end + +NS_ASSUME_NONNULL_END diff --git a/PSCCoreDataStack/PSCFetchedResultsControllerUpdater.m b/PSCCoreDataStack/PSCFetchedResultsControllerUpdater.m index b47449f..36e4303 100644 --- a/PSCCoreDataStack/PSCFetchedResultsControllerUpdater.m +++ b/PSCCoreDataStack/PSCFetchedResultsControllerUpdater.m @@ -7,6 +7,7 @@ // #import "PSCFetchedResultsControllerUpdater.h" +#import NSString *const PSCFetchedResultsControllerUpdaterControllerDidChangeContentNotification = @"PSCFetchedResultsControllerUpdaterControllerDidChangeContentNotification"; diff --git a/PSCCoreDataStack/PSCPersistenceOperation.h b/PSCCoreDataStack/PSCPersistenceOperation.h index 8e9fdca..81b72e6 100644 --- a/PSCCoreDataStack/PSCPersistenceOperation.h +++ b/PSCCoreDataStack/PSCPersistenceOperation.h @@ -7,13 +7,12 @@ // #import +#import +NS_ASSUME_NONNULL_BEGIN typedef BOOL(^psc_persistence_block)(NSManagedObjectContext *localContext); -// the queue used in persistDataInBackgroundWithParentContext:block:completion: -dispatch_queue_t psc_persistence_queue(void); - @interface PSCPersistenceOperation : NSOperation @@ -23,14 +22,14 @@ dispatch_queue_t psc_persistence_queue(void); */ + (void)persistDataInBackgroundWithParentContext:(NSManagedObjectContext *)parentContext block:(psc_persistence_block)block - completion:(dispatch_block_t)completion; + completion:(nullable dispatch_block_t)completion; /** Creates an NSOperation subclass that can be used to persist data to a local context */ + (instancetype)operationWithParentContext:(NSManagedObjectContext *)parentContext block:(psc_persistence_block)block - completion:(dispatch_block_t)completion; + completion:(nullable dispatch_block_t)completion; /** Subclasses can override to perform a persistence action */ - (BOOL)persistWithContext:(NSManagedObjectContext *)localContext; @@ -40,3 +39,5 @@ dispatch_queue_t psc_persistence_queue(void); - (void)didNotSaveContext:(NSManagedObjectContext *)localContext; @end + +NS_ASSUME_NONNULL_END diff --git a/PSCCoreDataStack/PSCPersistenceOperation.m b/PSCCoreDataStack/PSCPersistenceOperation.m index 43fe996..7c04f97 100644 --- a/PSCCoreDataStack/PSCPersistenceOperation.m +++ b/PSCCoreDataStack/PSCPersistenceOperation.m @@ -3,7 +3,7 @@ #import "NSManagedObjectContext+PSCCoreDataHelper.h" #import "PSCLogging.h" - +// the queue used in persistDataInBackgroundWithParentContext:block:completion: static dispatch_queue_t _psc_persistence_queue = NULL; @@ -44,19 +44,21 @@ + (void)persistDataInBackgroundWithParentContext:(NSManagedObjectContext *)paren dispatch_async(psc_persistence_queue(), ^{ NSManagedObjectContext *localContext = [parentContext newChildContextWithConcurrencyType:NSPrivateQueueConcurrencyType]; - NSError *error = nil; - if (block != nil) { - block(localContext); - } + [localContext performBlock:^{ + if (block != nil) { + block(localContext); + } - if (![localContext save:&error]) { - PSCCDLog(@"Error persisting local context in PSCPersistenceAction: %@", error); - } + NSError *error = nil; + if (![localContext save:&error]) { + PSCCDLog(@"Error persisting local context in PSCPersistenceAction: %@", error); + } - if (completion != nil) { - dispatch_async(dispatch_get_main_queue(), completion); - } + if (completion != nil) { + dispatch_async(dispatch_get_main_queue(), completion); + } + }]; }); } @@ -91,28 +93,30 @@ - (void)didNotSaveContext:(NSManagedObjectContext *)localContext { - (void)main { NSManagedObjectContext *localContext = [self.parentContext newChildContextWithConcurrencyType:NSPrivateQueueConcurrencyType]; - BOOL save = NO; - - // either persist via block (if set), or call method in subclass - if (self.persistenceBlock != nil) { - save = self.persistenceBlock(localContext); - } else { - save = [self persistWithContext:localContext]; - } - - if (save && localContext.hasChanges) { - NSError *error = nil; - - [self willSaveContext:localContext]; - - if (![localContext save:&error]) { - [self didFailToSaveContext:localContext error:error]; + [localContext performBlock:^{ + BOOL save = NO; + + // either persist via block (if set), or call method in subclass + if (self.persistenceBlock != nil) { + save = self.persistenceBlock(localContext); + } else { + save = [self persistWithContext:localContext]; + } + + if (save && localContext.hasChanges) { + NSError *error = nil; + + [self willSaveContext:localContext]; + + if (![localContext save:&error]) { + [self didFailToSaveContext:localContext error:error]; + } else { + [self didSaveContext:localContext]; + } } else { - [self didSaveContext:localContext]; + [self didNotSaveContext:localContext]; } - } else { - [self didNotSaveContext:localContext]; - } + }]; } //////////////////////////////////////////////////////////////////////// diff --git a/PSCCoreDataStackTests/PSCCoreDataStackTests.h b/PSCCoreDataStackTests/PSCCoreDataStackTests.h index 3ad88c6..64870c7 100644 --- a/PSCCoreDataStackTests/PSCCoreDataStackTests.h +++ b/PSCCoreDataStackTests/PSCCoreDataStackTests.h @@ -6,8 +6,8 @@ // Copyright (c) 2013 PocketScience. All rights reserved. // -#import +#import -@interface PSCCoreDataStackTests : SenTestCase +@interface PSCCoreDataStackTests : XCTestCase @end