├── .gitignore ├── Cartfile ├── Cartfile.resolved ├── LICENSE ├── PGMappingKit.podspec ├── PGMappingKit.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcshareddata │ └── xcschemes │ └── PGMappingKit.xcscheme ├── PGMappingKit ├── Info.plist ├── NSManagedObjectContext+PGMapping.h ├── NSManagedObjectContext+PGMapping.m ├── NSManagedObjectContext+PGObject.h ├── NSManagedObjectContext+PGObject.m ├── NSMutableDictionary+PGSafeCheck.h ├── NSMutableDictionary+PGSafeCheck.m ├── NSObject+PGKeyValueCoding.h ├── NSObject+PGKeyValueCoding.m ├── NSObject+PGNilObject.h ├── NSObject+PGNilObject.m ├── NSObject+PGPropertyList.h ├── NSObject+PGPropertyList.m ├── PGMappingDescription.h ├── PGMappingDescription.m ├── PGMappingKit.h ├── PGNetworkHandler+PGCoreData.h ├── PGNetworkHandler+PGCoreData.m ├── PGNetworkHandler+PGData.h ├── PGNetworkHandler+PGData.m ├── PGNetworkHandler.h └── PGNetworkHandler.m ├── PGMappingKitTests ├── Info.plist └── PGNetworkMappingTests.m └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # OS X Temporary Files 2 | 3 | .DS_Store 4 | .Trashes 5 | 6 | *.swp 7 | 8 | # Xcode Temporary Files 9 | 10 | *~.nib 11 | 12 | # Xcode Build Folder 13 | 14 | DerivedData/ 15 | build/ 16 | 17 | # Xcode Private Settings 18 | 19 | *.pbxuser 20 | *.mode1v3 21 | *.mode2v3 22 | *.perspectivev3 23 | 24 | !default.pbxuser 25 | !default.mode1v3 26 | !default.mode2v3 27 | !default.perspectivev3 28 | 29 | # Xcode Semi-personal Settings 30 | 31 | xcuserdata/ 32 | 33 | *.xccheckout 34 | 35 | # Xcode Deprecated Classes 36 | 37 | *.moved-aside 38 | 39 | # CocoaPods 40 | 41 | Pods/ 42 | 43 | !Podfile 44 | !Podfile.lock 45 | 46 | # Carthage 47 | 48 | Carthage/ 49 | 50 | !Cartfile 51 | !Cartfile.resolved 52 | 53 | # Reference 54 | # 55 | # .DS_Store http://www.westwind.com/reference/os-x/invisibles.html 56 | # .pbxuser http://lists.apple.com/archives/xcode-users/2004/Jan/msg00193.html 57 | # .mode1v3 http://lists.apple.com/archives/xcode-users/2007/Oct/msg00465.html 58 | # .mode2v3 http://lists.apple.com/archives/xcode-users/2007/Oct/msg00465.html 59 | # .perspectivev3 http://stackoverflow.com/questions/5223297/xcode-projects-what-is-a-perspectivev3-file 60 | # .xccheckout http://stackoverflow.com/a/19260712/153422 61 | # !Podfile.lock http://guides.cocoapods.org/using/using-cocoapods.html -------------------------------------------------------------------------------- /Cartfile: -------------------------------------------------------------------------------- 1 | github "AFNetworking/AFNetworking" ~> 3.0 2 | 3 | -------------------------------------------------------------------------------- /Cartfile.resolved: -------------------------------------------------------------------------------- 1 | github "AFNetworking/AFNetworking" "3.0.4" 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 Plot Guru 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /PGMappingKit.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'PGMappingKit' 3 | s.version = '1.0' 4 | s.license = 'MIT' 5 | s.summary = 'Lightweight JSON Synchronization to Core Data' 6 | s.homepage = 'https://github.com/PlotGuru/PGMappingKit' 7 | s.social_media_url = 'https://twitter.com/PlotGuru' 8 | s.author = { "Justin Jia" => "justin.jia.developer@gmail.com" } 9 | s.source = { :git => "https://github.com/PlotGuru/PGMappingKit.git", :tag => s.version.to_s } 10 | 11 | s.platform = :ios, '8.0' 12 | s.requires_arc = true 13 | 14 | s.source_files = 'PGMappingKit/*.{h,m}' 15 | s.frameworks = 'Foundation' 16 | s.dependency 'AFNetworking', '~> 3.0' 17 | end 18 | -------------------------------------------------------------------------------- /PGMappingKit.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 47; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | D01424181C1A2E04008F1C91 /* AFNetworking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D01424171C1A2E04008F1C91 /* AFNetworking.framework */; }; 11 | D02372AF1C1CE2C1007D541A /* AFNetworking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D01424171C1A2E04008F1C91 /* AFNetworking.framework */; }; 12 | D02372B11C1CE3B0007D541A /* AFNetworking.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = D01424171C1A2E04008F1C91 /* AFNetworking.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 13 | D02372B61C1CE439007D541A /* PGNetworkHandler+PGCoreData.h in Headers */ = {isa = PBXBuildFile; fileRef = D02372B41C1CE439007D541A /* PGNetworkHandler+PGCoreData.h */; settings = {ATTRIBUTES = (Public, ); }; }; 14 | D02372B71C1CE439007D541A /* PGNetworkHandler+PGCoreData.m in Sources */ = {isa = PBXBuildFile; fileRef = D02372B51C1CE439007D541A /* PGNetworkHandler+PGCoreData.m */; }; 15 | D0667CD21BF4049500682856 /* PGNetworkMappingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D0667CD11BF4049500682856 /* PGNetworkMappingTests.m */; }; 16 | D06C355D1BF01C06003D9D72 /* PGMappingKit.h in Headers */ = {isa = PBXBuildFile; fileRef = D06C355C1BF01C06003D9D72 /* PGMappingKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; 17 | D06C35641BF01C06003D9D72 /* PGMappingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D06C35591BF01C06003D9D72 /* PGMappingKit.framework */; }; 18 | D06C357D1BF01E6C003D9D72 /* PGNetworkHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = D06C35731BF01E6C003D9D72 /* PGNetworkHandler.h */; settings = {ATTRIBUTES = (Public, ); }; }; 19 | D06C357E1BF01E6C003D9D72 /* PGNetworkHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = D06C35741BF01E6C003D9D72 /* PGNetworkHandler.m */; }; 20 | D06C357F1BF01E6C003D9D72 /* NSManagedObjectContext+PGMapping.h in Headers */ = {isa = PBXBuildFile; fileRef = D06C35751BF01E6C003D9D72 /* NSManagedObjectContext+PGMapping.h */; settings = {ATTRIBUTES = (Public, ); }; }; 21 | D06C35801BF01E6C003D9D72 /* NSManagedObjectContext+PGMapping.m in Sources */ = {isa = PBXBuildFile; fileRef = D06C35761BF01E6C003D9D72 /* NSManagedObjectContext+PGMapping.m */; }; 22 | D06C35811BF01E6C003D9D72 /* PGMappingDescription.h in Headers */ = {isa = PBXBuildFile; fileRef = D06C35771BF01E6C003D9D72 /* PGMappingDescription.h */; settings = {ATTRIBUTES = (Public, ); }; }; 23 | D06C35821BF01E6C003D9D72 /* PGMappingDescription.m in Sources */ = {isa = PBXBuildFile; fileRef = D06C35781BF01E6C003D9D72 /* PGMappingDescription.m */; }; 24 | D06C35831BF01E6C003D9D72 /* NSObject+PGKeyValueCoding.h in Headers */ = {isa = PBXBuildFile; fileRef = D06C35791BF01E6C003D9D72 /* NSObject+PGKeyValueCoding.h */; }; 25 | D06C35841BF01E6C003D9D72 /* NSObject+PGKeyValueCoding.m in Sources */ = {isa = PBXBuildFile; fileRef = D06C357A1BF01E6C003D9D72 /* NSObject+PGKeyValueCoding.m */; }; 26 | D06C35851BF01E6C003D9D72 /* NSObject+PGPropertyList.h in Headers */ = {isa = PBXBuildFile; fileRef = D06C357B1BF01E6C003D9D72 /* NSObject+PGPropertyList.h */; }; 27 | D06C35861BF01E6C003D9D72 /* NSObject+PGPropertyList.m in Sources */ = {isa = PBXBuildFile; fileRef = D06C357C1BF01E6C003D9D72 /* NSObject+PGPropertyList.m */; }; 28 | D06C35891BF01E8B003D9D72 /* NSMutableDictionary+PGSafeCheck.h in Headers */ = {isa = PBXBuildFile; fileRef = D06C35871BF01E8B003D9D72 /* NSMutableDictionary+PGSafeCheck.h */; }; 29 | D06C358A1BF01E8B003D9D72 /* NSMutableDictionary+PGSafeCheck.m in Sources */ = {isa = PBXBuildFile; fileRef = D06C35881BF01E8B003D9D72 /* NSMutableDictionary+PGSafeCheck.m */; }; 30 | D0C8CB491C0128F800A35C46 /* NSObject+PGNilObject.h in Headers */ = {isa = PBXBuildFile; fileRef = D0C8CB471C0128F800A35C46 /* NSObject+PGNilObject.h */; settings = {ATTRIBUTES = (Public, ); }; }; 31 | D0C8CB4A1C0128F800A35C46 /* NSObject+PGNilObject.m in Sources */ = {isa = PBXBuildFile; fileRef = D0C8CB481C0128F800A35C46 /* NSObject+PGNilObject.m */; }; 32 | D0C8CB4D1C01293400A35C46 /* NSManagedObjectContext+PGObject.h in Headers */ = {isa = PBXBuildFile; fileRef = D0C8CB4B1C01293400A35C46 /* NSManagedObjectContext+PGObject.h */; settings = {ATTRIBUTES = (Public, ); }; }; 33 | D0C8CB4E1C01293400A35C46 /* NSManagedObjectContext+PGObject.m in Sources */ = {isa = PBXBuildFile; fileRef = D0C8CB4C1C01293400A35C46 /* NSManagedObjectContext+PGObject.m */; }; 34 | D0F483D21C46E9C900C7FFFF /* PGNetworkHandler+PGData.h in Headers */ = {isa = PBXBuildFile; fileRef = D0F483D01C46E9C900C7FFFF /* PGNetworkHandler+PGData.h */; settings = {ATTRIBUTES = (Public, ); }; }; 35 | D0F483D31C46E9C900C7FFFF /* PGNetworkHandler+PGData.m in Sources */ = {isa = PBXBuildFile; fileRef = D0F483D11C46E9C900C7FFFF /* PGNetworkHandler+PGData.m */; }; 36 | /* End PBXBuildFile section */ 37 | 38 | /* Begin PBXContainerItemProxy section */ 39 | D06C35651BF01C06003D9D72 /* PBXContainerItemProxy */ = { 40 | isa = PBXContainerItemProxy; 41 | containerPortal = D06C35501BF01C06003D9D72 /* Project object */; 42 | proxyType = 1; 43 | remoteGlobalIDString = D06C35581BF01C06003D9D72; 44 | remoteInfo = PGMappingKit; 45 | }; 46 | /* End PBXContainerItemProxy section */ 47 | 48 | /* Begin PBXCopyFilesBuildPhase section */ 49 | D02372B01C1CE39F007D541A /* Copy Frameworks */ = { 50 | isa = PBXCopyFilesBuildPhase; 51 | buildActionMask = 2147483647; 52 | dstPath = ""; 53 | dstSubfolderSpec = 10; 54 | files = ( 55 | D02372B11C1CE3B0007D541A /* AFNetworking.framework in Copy Frameworks */, 56 | ); 57 | name = "Copy Frameworks"; 58 | runOnlyForDeploymentPostprocessing = 0; 59 | }; 60 | /* End PBXCopyFilesBuildPhase section */ 61 | 62 | /* Begin PBXFileReference section */ 63 | D01424171C1A2E04008F1C91 /* AFNetworking.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AFNetworking.framework; path = ../Carthage/Build/iOS/AFNetworking.framework; sourceTree = ""; }; 64 | D02372B41C1CE439007D541A /* PGNetworkHandler+PGCoreData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "PGNetworkHandler+PGCoreData.h"; sourceTree = ""; }; 65 | D02372B51C1CE439007D541A /* PGNetworkHandler+PGCoreData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "PGNetworkHandler+PGCoreData.m"; sourceTree = ""; }; 66 | D0667CD11BF4049500682856 /* PGNetworkMappingTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGNetworkMappingTests.m; sourceTree = ""; }; 67 | D06C35591BF01C06003D9D72 /* PGMappingKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PGMappingKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 68 | D06C355C1BF01C06003D9D72 /* PGMappingKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PGMappingKit.h; sourceTree = ""; }; 69 | D06C355E1BF01C06003D9D72 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 70 | D06C35631BF01C06003D9D72 /* PGMappingKitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PGMappingKitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 71 | D06C356A1BF01C06003D9D72 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 72 | D06C35731BF01E6C003D9D72 /* PGNetworkHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGNetworkHandler.h; sourceTree = ""; }; 73 | D06C35741BF01E6C003D9D72 /* PGNetworkHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGNetworkHandler.m; sourceTree = ""; }; 74 | D06C35751BF01E6C003D9D72 /* NSManagedObjectContext+PGMapping.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSManagedObjectContext+PGMapping.h"; sourceTree = ""; }; 75 | D06C35761BF01E6C003D9D72 /* NSManagedObjectContext+PGMapping.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSManagedObjectContext+PGMapping.m"; sourceTree = ""; }; 76 | D06C35771BF01E6C003D9D72 /* PGMappingDescription.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGMappingDescription.h; sourceTree = ""; }; 77 | D06C35781BF01E6C003D9D72 /* PGMappingDescription.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGMappingDescription.m; sourceTree = ""; }; 78 | D06C35791BF01E6C003D9D72 /* NSObject+PGKeyValueCoding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+PGKeyValueCoding.h"; sourceTree = ""; }; 79 | D06C357A1BF01E6C003D9D72 /* NSObject+PGKeyValueCoding.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+PGKeyValueCoding.m"; sourceTree = ""; }; 80 | D06C357B1BF01E6C003D9D72 /* NSObject+PGPropertyList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+PGPropertyList.h"; sourceTree = ""; }; 81 | D06C357C1BF01E6C003D9D72 /* NSObject+PGPropertyList.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+PGPropertyList.m"; sourceTree = ""; }; 82 | D06C35871BF01E8B003D9D72 /* NSMutableDictionary+PGSafeCheck.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSMutableDictionary+PGSafeCheck.h"; sourceTree = ""; }; 83 | D06C35881BF01E8B003D9D72 /* NSMutableDictionary+PGSafeCheck.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSMutableDictionary+PGSafeCheck.m"; sourceTree = ""; }; 84 | D0C8CB471C0128F800A35C46 /* NSObject+PGNilObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+PGNilObject.h"; sourceTree = ""; }; 85 | D0C8CB481C0128F800A35C46 /* NSObject+PGNilObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+PGNilObject.m"; sourceTree = ""; }; 86 | D0C8CB4B1C01293400A35C46 /* NSManagedObjectContext+PGObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSManagedObjectContext+PGObject.h"; sourceTree = ""; }; 87 | D0C8CB4C1C01293400A35C46 /* NSManagedObjectContext+PGObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSManagedObjectContext+PGObject.m"; sourceTree = ""; }; 88 | D0F483D01C46E9C900C7FFFF /* PGNetworkHandler+PGData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "PGNetworkHandler+PGData.h"; sourceTree = ""; }; 89 | D0F483D11C46E9C900C7FFFF /* PGNetworkHandler+PGData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "PGNetworkHandler+PGData.m"; sourceTree = ""; }; 90 | /* End PBXFileReference section */ 91 | 92 | /* Begin PBXFrameworksBuildPhase section */ 93 | D06C35551BF01C06003D9D72 /* Frameworks */ = { 94 | isa = PBXFrameworksBuildPhase; 95 | buildActionMask = 2147483647; 96 | files = ( 97 | D01424181C1A2E04008F1C91 /* AFNetworking.framework in Frameworks */, 98 | ); 99 | runOnlyForDeploymentPostprocessing = 0; 100 | }; 101 | D06C35601BF01C06003D9D72 /* Frameworks */ = { 102 | isa = PBXFrameworksBuildPhase; 103 | buildActionMask = 2147483647; 104 | files = ( 105 | D02372AF1C1CE2C1007D541A /* AFNetworking.framework in Frameworks */, 106 | D06C35641BF01C06003D9D72 /* PGMappingKit.framework in Frameworks */, 107 | ); 108 | runOnlyForDeploymentPostprocessing = 0; 109 | }; 110 | /* End PBXFrameworksBuildPhase section */ 111 | 112 | /* Begin PBXGroup section */ 113 | D014243D1C1A312D008F1C91 /* Frameworks */ = { 114 | isa = PBXGroup; 115 | children = ( 116 | D01424171C1A2E04008F1C91 /* AFNetworking.framework */, 117 | ); 118 | name = Frameworks; 119 | path = PGMappingKit; 120 | sourceTree = ""; 121 | }; 122 | D06C354F1BF01C06003D9D72 = { 123 | isa = PBXGroup; 124 | children = ( 125 | D06C355B1BF01C06003D9D72 /* PGMappingKit */, 126 | D06C35671BF01C06003D9D72 /* PGMappingKitTests */, 127 | D06C355A1BF01C06003D9D72 /* Products */, 128 | D014243D1C1A312D008F1C91 /* Frameworks */, 129 | ); 130 | sourceTree = ""; 131 | }; 132 | D06C355A1BF01C06003D9D72 /* Products */ = { 133 | isa = PBXGroup; 134 | children = ( 135 | D06C35591BF01C06003D9D72 /* PGMappingKit.framework */, 136 | D06C35631BF01C06003D9D72 /* PGMappingKitTests.xctest */, 137 | ); 138 | name = Products; 139 | sourceTree = ""; 140 | }; 141 | D06C355B1BF01C06003D9D72 /* PGMappingKit */ = { 142 | isa = PBXGroup; 143 | children = ( 144 | D06C355C1BF01C06003D9D72 /* PGMappingKit.h */, 145 | D06C355E1BF01C06003D9D72 /* Info.plist */, 146 | D06C358E1BF01FE7003D9D72 /* PGNetworkHandler */, 147 | D06C358D1BF01FC5003D9D72 /* PGMappingDescription */, 148 | D06C358B1BF01E90003D9D72 /* PGExtension */, 149 | ); 150 | path = PGMappingKit; 151 | sourceTree = ""; 152 | }; 153 | D06C35671BF01C06003D9D72 /* PGMappingKitTests */ = { 154 | isa = PBXGroup; 155 | children = ( 156 | D06C356A1BF01C06003D9D72 /* Info.plist */, 157 | D0667CD11BF4049500682856 /* PGNetworkMappingTests.m */, 158 | ); 159 | path = PGMappingKitTests; 160 | sourceTree = ""; 161 | }; 162 | D06C358B1BF01E90003D9D72 /* PGExtension */ = { 163 | isa = PBXGroup; 164 | children = ( 165 | D06C35871BF01E8B003D9D72 /* NSMutableDictionary+PGSafeCheck.h */, 166 | D06C35881BF01E8B003D9D72 /* NSMutableDictionary+PGSafeCheck.m */, 167 | D06C35791BF01E6C003D9D72 /* NSObject+PGKeyValueCoding.h */, 168 | D06C357A1BF01E6C003D9D72 /* NSObject+PGKeyValueCoding.m */, 169 | D06C357B1BF01E6C003D9D72 /* NSObject+PGPropertyList.h */, 170 | D06C357C1BF01E6C003D9D72 /* NSObject+PGPropertyList.m */, 171 | ); 172 | name = PGExtension; 173 | sourceTree = ""; 174 | }; 175 | D06C358D1BF01FC5003D9D72 /* PGMappingDescription */ = { 176 | isa = PBXGroup; 177 | children = ( 178 | D06C35771BF01E6C003D9D72 /* PGMappingDescription.h */, 179 | D06C35781BF01E6C003D9D72 /* PGMappingDescription.m */, 180 | D0C8CB4B1C01293400A35C46 /* NSManagedObjectContext+PGObject.h */, 181 | D0C8CB4C1C01293400A35C46 /* NSManagedObjectContext+PGObject.m */, 182 | D0C8CB471C0128F800A35C46 /* NSObject+PGNilObject.h */, 183 | D0C8CB481C0128F800A35C46 /* NSObject+PGNilObject.m */, 184 | ); 185 | name = PGMappingDescription; 186 | sourceTree = ""; 187 | }; 188 | D06C358E1BF01FE7003D9D72 /* PGNetworkHandler */ = { 189 | isa = PBXGroup; 190 | children = ( 191 | D06C35731BF01E6C003D9D72 /* PGNetworkHandler.h */, 192 | D06C35741BF01E6C003D9D72 /* PGNetworkHandler.m */, 193 | D02372B41C1CE439007D541A /* PGNetworkHandler+PGCoreData.h */, 194 | D02372B51C1CE439007D541A /* PGNetworkHandler+PGCoreData.m */, 195 | D0F483D01C46E9C900C7FFFF /* PGNetworkHandler+PGData.h */, 196 | D0F483D11C46E9C900C7FFFF /* PGNetworkHandler+PGData.m */, 197 | D06C35751BF01E6C003D9D72 /* NSManagedObjectContext+PGMapping.h */, 198 | D06C35761BF01E6C003D9D72 /* NSManagedObjectContext+PGMapping.m */, 199 | ); 200 | name = PGNetworkHandler; 201 | sourceTree = ""; 202 | }; 203 | /* End PBXGroup section */ 204 | 205 | /* Begin PBXHeadersBuildPhase section */ 206 | D06C35561BF01C06003D9D72 /* Headers */ = { 207 | isa = PBXHeadersBuildPhase; 208 | buildActionMask = 2147483647; 209 | files = ( 210 | D06C357D1BF01E6C003D9D72 /* PGNetworkHandler.h in Headers */, 211 | D02372B61C1CE439007D541A /* PGNetworkHandler+PGCoreData.h in Headers */, 212 | D06C357F1BF01E6C003D9D72 /* NSManagedObjectContext+PGMapping.h in Headers */, 213 | D06C35811BF01E6C003D9D72 /* PGMappingDescription.h in Headers */, 214 | D06C355D1BF01C06003D9D72 /* PGMappingKit.h in Headers */, 215 | D0C8CB4D1C01293400A35C46 /* NSManagedObjectContext+PGObject.h in Headers */, 216 | D0F483D21C46E9C900C7FFFF /* PGNetworkHandler+PGData.h in Headers */, 217 | D06C35831BF01E6C003D9D72 /* NSObject+PGKeyValueCoding.h in Headers */, 218 | D0C8CB491C0128F800A35C46 /* NSObject+PGNilObject.h in Headers */, 219 | D06C35891BF01E8B003D9D72 /* NSMutableDictionary+PGSafeCheck.h in Headers */, 220 | D06C35851BF01E6C003D9D72 /* NSObject+PGPropertyList.h in Headers */, 221 | ); 222 | runOnlyForDeploymentPostprocessing = 0; 223 | }; 224 | /* End PBXHeadersBuildPhase section */ 225 | 226 | /* Begin PBXNativeTarget section */ 227 | D06C35581BF01C06003D9D72 /* PGMappingKit */ = { 228 | isa = PBXNativeTarget; 229 | buildConfigurationList = D06C356D1BF01C06003D9D72 /* Build configuration list for PBXNativeTarget "PGMappingKit" */; 230 | buildPhases = ( 231 | D06C35541BF01C06003D9D72 /* Sources */, 232 | D06C35551BF01C06003D9D72 /* Frameworks */, 233 | D06C35561BF01C06003D9D72 /* Headers */, 234 | D06C35571BF01C06003D9D72 /* Resources */, 235 | ); 236 | buildRules = ( 237 | ); 238 | dependencies = ( 239 | ); 240 | name = PGMappingKit; 241 | productName = PGMappingKit; 242 | productReference = D06C35591BF01C06003D9D72 /* PGMappingKit.framework */; 243 | productType = "com.apple.product-type.framework"; 244 | }; 245 | D06C35621BF01C06003D9D72 /* PGMappingKitTests */ = { 246 | isa = PBXNativeTarget; 247 | buildConfigurationList = D06C35701BF01C06003D9D72 /* Build configuration list for PBXNativeTarget "PGMappingKitTests" */; 248 | buildPhases = ( 249 | D06C355F1BF01C06003D9D72 /* Sources */, 250 | D06C35601BF01C06003D9D72 /* Frameworks */, 251 | D06C35611BF01C06003D9D72 /* Resources */, 252 | D02372B01C1CE39F007D541A /* Copy Frameworks */, 253 | ); 254 | buildRules = ( 255 | ); 256 | dependencies = ( 257 | D06C35661BF01C06003D9D72 /* PBXTargetDependency */, 258 | ); 259 | name = PGMappingKitTests; 260 | productName = PGMappingKitTests; 261 | productReference = D06C35631BF01C06003D9D72 /* PGMappingKitTests.xctest */; 262 | productType = "com.apple.product-type.bundle.unit-test"; 263 | }; 264 | /* End PBXNativeTarget section */ 265 | 266 | /* Begin PBXProject section */ 267 | D06C35501BF01C06003D9D72 /* Project object */ = { 268 | isa = PBXProject; 269 | attributes = { 270 | CLASSPREFIX = PG; 271 | LastUpgradeCheck = 0710; 272 | ORGANIZATIONNAME = "Plot Guru"; 273 | TargetAttributes = { 274 | D06C35581BF01C06003D9D72 = { 275 | CreatedOnToolsVersion = 7.1; 276 | }; 277 | D06C35621BF01C06003D9D72 = { 278 | CreatedOnToolsVersion = 7.1; 279 | }; 280 | }; 281 | }; 282 | buildConfigurationList = D06C35531BF01C06003D9D72 /* Build configuration list for PBXProject "PGMappingKit" */; 283 | compatibilityVersion = "Xcode 6.3"; 284 | developmentRegion = English; 285 | hasScannedForEncodings = 0; 286 | knownRegions = ( 287 | en, 288 | ); 289 | mainGroup = D06C354F1BF01C06003D9D72; 290 | productRefGroup = D06C355A1BF01C06003D9D72 /* Products */; 291 | projectDirPath = ""; 292 | projectRoot = ""; 293 | targets = ( 294 | D06C35581BF01C06003D9D72 /* PGMappingKit */, 295 | D06C35621BF01C06003D9D72 /* PGMappingKitTests */, 296 | ); 297 | }; 298 | /* End PBXProject section */ 299 | 300 | /* Begin PBXResourcesBuildPhase section */ 301 | D06C35571BF01C06003D9D72 /* Resources */ = { 302 | isa = PBXResourcesBuildPhase; 303 | buildActionMask = 2147483647; 304 | files = ( 305 | ); 306 | runOnlyForDeploymentPostprocessing = 0; 307 | }; 308 | D06C35611BF01C06003D9D72 /* Resources */ = { 309 | isa = PBXResourcesBuildPhase; 310 | buildActionMask = 2147483647; 311 | files = ( 312 | ); 313 | runOnlyForDeploymentPostprocessing = 0; 314 | }; 315 | /* End PBXResourcesBuildPhase section */ 316 | 317 | /* Begin PBXSourcesBuildPhase section */ 318 | D06C35541BF01C06003D9D72 /* Sources */ = { 319 | isa = PBXSourcesBuildPhase; 320 | buildActionMask = 2147483647; 321 | files = ( 322 | D06C358A1BF01E8B003D9D72 /* NSMutableDictionary+PGSafeCheck.m in Sources */, 323 | D06C35861BF01E6C003D9D72 /* NSObject+PGPropertyList.m in Sources */, 324 | D06C35801BF01E6C003D9D72 /* NSManagedObjectContext+PGMapping.m in Sources */, 325 | D06C35821BF01E6C003D9D72 /* PGMappingDescription.m in Sources */, 326 | D06C35841BF01E6C003D9D72 /* NSObject+PGKeyValueCoding.m in Sources */, 327 | D02372B71C1CE439007D541A /* PGNetworkHandler+PGCoreData.m in Sources */, 328 | D0C8CB4E1C01293400A35C46 /* NSManagedObjectContext+PGObject.m in Sources */, 329 | D0F483D31C46E9C900C7FFFF /* PGNetworkHandler+PGData.m in Sources */, 330 | D06C357E1BF01E6C003D9D72 /* PGNetworkHandler.m in Sources */, 331 | D0C8CB4A1C0128F800A35C46 /* NSObject+PGNilObject.m in Sources */, 332 | ); 333 | runOnlyForDeploymentPostprocessing = 0; 334 | }; 335 | D06C355F1BF01C06003D9D72 /* Sources */ = { 336 | isa = PBXSourcesBuildPhase; 337 | buildActionMask = 2147483647; 338 | files = ( 339 | D0667CD21BF4049500682856 /* PGNetworkMappingTests.m in Sources */, 340 | ); 341 | runOnlyForDeploymentPostprocessing = 0; 342 | }; 343 | /* End PBXSourcesBuildPhase section */ 344 | 345 | /* Begin PBXTargetDependency section */ 346 | D06C35661BF01C06003D9D72 /* PBXTargetDependency */ = { 347 | isa = PBXTargetDependency; 348 | target = D06C35581BF01C06003D9D72 /* PGMappingKit */; 349 | targetProxy = D06C35651BF01C06003D9D72 /* PBXContainerItemProxy */; 350 | }; 351 | /* End PBXTargetDependency section */ 352 | 353 | /* Begin XCBuildConfiguration section */ 354 | D06C356B1BF01C06003D9D72 /* Debug */ = { 355 | isa = XCBuildConfiguration; 356 | buildSettings = { 357 | ALWAYS_SEARCH_USER_PATHS = NO; 358 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 359 | CLANG_CXX_LIBRARY = "libc++"; 360 | CLANG_ENABLE_MODULES = YES; 361 | CLANG_ENABLE_OBJC_ARC = YES; 362 | CLANG_WARN_BOOL_CONVERSION = YES; 363 | CLANG_WARN_CONSTANT_CONVERSION = YES; 364 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 365 | CLANG_WARN_EMPTY_BODY = YES; 366 | CLANG_WARN_ENUM_CONVERSION = YES; 367 | CLANG_WARN_INT_CONVERSION = YES; 368 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 369 | CLANG_WARN_UNREACHABLE_CODE = YES; 370 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 371 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 372 | COPY_PHASE_STRIP = NO; 373 | CURRENT_PROJECT_VERSION = 1; 374 | DEBUG_INFORMATION_FORMAT = dwarf; 375 | ENABLE_STRICT_OBJC_MSGSEND = YES; 376 | ENABLE_TESTABILITY = YES; 377 | GCC_C_LANGUAGE_STANDARD = gnu99; 378 | GCC_DYNAMIC_NO_PIC = NO; 379 | GCC_NO_COMMON_BLOCKS = YES; 380 | GCC_OPTIMIZATION_LEVEL = 0; 381 | GCC_PREPROCESSOR_DEFINITIONS = ( 382 | "DEBUG=1", 383 | "$(inherited)", 384 | ); 385 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 386 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 387 | GCC_WARN_UNDECLARED_SELECTOR = YES; 388 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 389 | GCC_WARN_UNUSED_FUNCTION = YES; 390 | GCC_WARN_UNUSED_VARIABLE = YES; 391 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 392 | MTL_ENABLE_DEBUG_INFO = YES; 393 | ONLY_ACTIVE_ARCH = YES; 394 | SDKROOT = iphoneos; 395 | TARGETED_DEVICE_FAMILY = "1,2"; 396 | VERSIONING_SYSTEM = "apple-generic"; 397 | VERSION_INFO_PREFIX = ""; 398 | }; 399 | name = Debug; 400 | }; 401 | D06C356C1BF01C06003D9D72 /* Release */ = { 402 | isa = XCBuildConfiguration; 403 | buildSettings = { 404 | ALWAYS_SEARCH_USER_PATHS = NO; 405 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 406 | CLANG_CXX_LIBRARY = "libc++"; 407 | CLANG_ENABLE_MODULES = YES; 408 | CLANG_ENABLE_OBJC_ARC = YES; 409 | CLANG_WARN_BOOL_CONVERSION = YES; 410 | CLANG_WARN_CONSTANT_CONVERSION = YES; 411 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 412 | CLANG_WARN_EMPTY_BODY = YES; 413 | CLANG_WARN_ENUM_CONVERSION = YES; 414 | CLANG_WARN_INT_CONVERSION = YES; 415 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 416 | CLANG_WARN_UNREACHABLE_CODE = YES; 417 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 418 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 419 | COPY_PHASE_STRIP = NO; 420 | CURRENT_PROJECT_VERSION = 1; 421 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 422 | ENABLE_NS_ASSERTIONS = NO; 423 | ENABLE_STRICT_OBJC_MSGSEND = YES; 424 | GCC_C_LANGUAGE_STANDARD = gnu99; 425 | GCC_NO_COMMON_BLOCKS = YES; 426 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 427 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 428 | GCC_WARN_UNDECLARED_SELECTOR = YES; 429 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 430 | GCC_WARN_UNUSED_FUNCTION = YES; 431 | GCC_WARN_UNUSED_VARIABLE = YES; 432 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 433 | MTL_ENABLE_DEBUG_INFO = NO; 434 | SDKROOT = iphoneos; 435 | TARGETED_DEVICE_FAMILY = "1,2"; 436 | VALIDATE_PRODUCT = YES; 437 | VERSIONING_SYSTEM = "apple-generic"; 438 | VERSION_INFO_PREFIX = ""; 439 | }; 440 | name = Release; 441 | }; 442 | D06C356E1BF01C06003D9D72 /* Debug */ = { 443 | isa = XCBuildConfiguration; 444 | buildSettings = { 445 | DEFINES_MODULE = YES; 446 | DYLIB_COMPATIBILITY_VERSION = 1; 447 | DYLIB_CURRENT_VERSION = 1; 448 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 449 | FRAMEWORK_SEARCH_PATHS = ( 450 | "$(inherited)", 451 | "$(PROJECT_DIR)/Carthage/Build/iOS", 452 | ); 453 | INFOPLIST_FILE = PGMappingKit/Info.plist; 454 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 455 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 456 | PRODUCT_BUNDLE_IDENTIFIER = com.plotguru.PGMappingKit; 457 | PRODUCT_NAME = "$(TARGET_NAME)"; 458 | SKIP_INSTALL = YES; 459 | }; 460 | name = Debug; 461 | }; 462 | D06C356F1BF01C06003D9D72 /* Release */ = { 463 | isa = XCBuildConfiguration; 464 | buildSettings = { 465 | DEFINES_MODULE = YES; 466 | DYLIB_COMPATIBILITY_VERSION = 1; 467 | DYLIB_CURRENT_VERSION = 1; 468 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 469 | FRAMEWORK_SEARCH_PATHS = ( 470 | "$(inherited)", 471 | "$(PROJECT_DIR)/Carthage/Build/iOS", 472 | ); 473 | INFOPLIST_FILE = PGMappingKit/Info.plist; 474 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 475 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 476 | PRODUCT_BUNDLE_IDENTIFIER = com.plotguru.PGMappingKit; 477 | PRODUCT_NAME = "$(TARGET_NAME)"; 478 | SKIP_INSTALL = YES; 479 | }; 480 | name = Release; 481 | }; 482 | D06C35711BF01C06003D9D72 /* Debug */ = { 483 | isa = XCBuildConfiguration; 484 | buildSettings = { 485 | FRAMEWORK_SEARCH_PATHS = ( 486 | "$(inherited)", 487 | "$(PROJECT_DIR)/Carthage/Build/iOS", 488 | ); 489 | INFOPLIST_FILE = PGMappingKitTests/Info.plist; 490 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 491 | PRODUCT_BUNDLE_IDENTIFIER = com.plotguru.PGMappingKitTests; 492 | PRODUCT_NAME = "$(TARGET_NAME)"; 493 | }; 494 | name = Debug; 495 | }; 496 | D06C35721BF01C06003D9D72 /* Release */ = { 497 | isa = XCBuildConfiguration; 498 | buildSettings = { 499 | FRAMEWORK_SEARCH_PATHS = ( 500 | "$(inherited)", 501 | "$(PROJECT_DIR)/Carthage/Build/iOS", 502 | ); 503 | INFOPLIST_FILE = PGMappingKitTests/Info.plist; 504 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 505 | PRODUCT_BUNDLE_IDENTIFIER = com.plotguru.PGMappingKitTests; 506 | PRODUCT_NAME = "$(TARGET_NAME)"; 507 | }; 508 | name = Release; 509 | }; 510 | /* End XCBuildConfiguration section */ 511 | 512 | /* Begin XCConfigurationList section */ 513 | D06C35531BF01C06003D9D72 /* Build configuration list for PBXProject "PGMappingKit" */ = { 514 | isa = XCConfigurationList; 515 | buildConfigurations = ( 516 | D06C356B1BF01C06003D9D72 /* Debug */, 517 | D06C356C1BF01C06003D9D72 /* Release */, 518 | ); 519 | defaultConfigurationIsVisible = 0; 520 | defaultConfigurationName = Release; 521 | }; 522 | D06C356D1BF01C06003D9D72 /* Build configuration list for PBXNativeTarget "PGMappingKit" */ = { 523 | isa = XCConfigurationList; 524 | buildConfigurations = ( 525 | D06C356E1BF01C06003D9D72 /* Debug */, 526 | D06C356F1BF01C06003D9D72 /* Release */, 527 | ); 528 | defaultConfigurationIsVisible = 0; 529 | defaultConfigurationName = Release; 530 | }; 531 | D06C35701BF01C06003D9D72 /* Build configuration list for PBXNativeTarget "PGMappingKitTests" */ = { 532 | isa = XCConfigurationList; 533 | buildConfigurations = ( 534 | D06C35711BF01C06003D9D72 /* Debug */, 535 | D06C35721BF01C06003D9D72 /* Release */, 536 | ); 537 | defaultConfigurationIsVisible = 0; 538 | defaultConfigurationName = Release; 539 | }; 540 | /* End XCConfigurationList section */ 541 | }; 542 | rootObject = D06C35501BF01C06003D9D72 /* Project object */; 543 | } 544 | -------------------------------------------------------------------------------- /PGMappingKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /PGMappingKit.xcodeproj/xcshareddata/xcschemes/PGMappingKit.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 65 | 71 | 72 | 73 | 74 | 75 | 76 | 82 | 83 | 89 | 90 | 91 | 92 | 94 | 95 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /PGMappingKit/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /PGMappingKit/NSManagedObjectContext+PGMapping.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2015 by Plot Guru. 3 | // 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | // 23 | 24 | @import CoreData; 25 | 26 | @class PGMappingDescription; 27 | 28 | NS_ASSUME_NONNULL_BEGIN 29 | 30 | @interface NSManagedObjectContext (PGMappingDescription) 31 | 32 | - (id)save:(nullable NSDictionary *)data description:(PGMappingDescription *)mapping error:(NSError **)error; 33 | - (id)save:(nullable NSDictionary *)data to:(id)object description:(PGMappingDescription *)mapping error:(NSError **)error; 34 | 35 | @end 36 | 37 | NS_ASSUME_NONNULL_END 38 | -------------------------------------------------------------------------------- /PGMappingKit/NSManagedObjectContext+PGMapping.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2015 by Plot Guru. 3 | // 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | // 23 | 24 | #import "NSManagedObjectContext+PGMapping.h" 25 | #import "PGMappingDescription.h" 26 | #import "NSObject+PGKeyValueCoding.h" 27 | 28 | @implementation NSManagedObjectContext (PGMappingDescription) 29 | 30 | - (id)save:(nullable NSDictionary *)data description:(PGMappingDescription *)mapping error:(NSError **)error 31 | { 32 | NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:mapping.localName]; 33 | fetchRequest.predicate = [NSPredicate predicateWithFormat:@"%K == %@", mapping.localIDKey, data[mapping.remoteIDKey]]; 34 | 35 | NSManagedObject *object = [self executeFetchRequest:fetchRequest error:error].firstObject; 36 | 37 | if (!object) { 38 | object = [NSEntityDescription insertNewObjectForEntityForName:mapping.localName inManagedObjectContext:self]; 39 | } 40 | 41 | return [self save:data to:object description:mapping error:error]; 42 | } 43 | 44 | - (id)save:(nullable NSDictionary *)data to:(id)object description:(PGMappingDescription *)mapping error:(NSError **)error 45 | { 46 | for (NSString *key in data.allKeys) { 47 | id remoteKey = [mapping localKeyForRemoteKey:key]; 48 | id value = data[key]; 49 | 50 | if ([remoteKey isKindOfClass:[PGMappingDescription class]]) { 51 | PGMappingDescription *mappedMapping = remoteKey; 52 | 53 | if ([value isKindOfClass:[NSDictionary class]]) { 54 | [object safelySetValue:[self save:value description:mappedMapping error:error] forKey:mappedMapping.remoteName]; 55 | } else if ([value isKindOfClass:[NSArray class]]) { 56 | NSArray *dataArray = value; 57 | for (id data in dataArray) { 58 | if ([data isKindOfClass:[NSDictionary class]]) { 59 | [object safelyAddValue:[self save:data description:mappedMapping error:error] forKey:mappedMapping.remoteName]; 60 | } 61 | } 62 | } else { 63 | NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:mappedMapping.localName]; 64 | fetchRequest.predicate = [NSPredicate predicateWithFormat:@"%K == %@", mappedMapping.localIDKey, value]; 65 | 66 | NSManagedObject *relatedObject = [self executeFetchRequest:fetchRequest error:error].firstObject; 67 | [object safelySetValue:relatedObject forKey:mappedMapping.remoteName]; 68 | } 69 | } else if ([remoteKey isKindOfClass:[NSString class]]) { 70 | [object safelySetValue:value forKey:remoteKey]; 71 | } 72 | } 73 | 74 | return object; 75 | } 76 | 77 | @end 78 | -------------------------------------------------------------------------------- /PGMappingKit/NSManagedObjectContext+PGObject.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2015 by Plot Guru. 3 | // 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | // 23 | 24 | @import Foundation; 25 | @import CoreData; 26 | 27 | @class PGMappingDescription; 28 | 29 | NS_ASSUME_NONNULL_BEGIN 30 | 31 | @interface NSManagedObjectContext (PGObject) 32 | 33 | - (nullable id)objectWithType:(NSString *)type identifier:(nullable id)identifier forKey:(NSString *)key error:(NSError **)error; 34 | - (nullable NSArray *)objectsWithType:(NSString *)type error:(NSError **)error; 35 | - (nullable id)objectWithMapping:(PGMappingDescription *)mapping data:(nullable NSDictionary *)data error:(NSError **)error; 36 | - (nullable id)objectWithMapping:(PGMappingDescription *)mapping identifier:(nullable id)identifier error:(NSError **)error; 37 | - (nullable NSArray *)objectsWithMapping:(PGMappingDescription *)mapping error:(NSError **)error; 38 | 39 | @end 40 | 41 | NS_ASSUME_NONNULL_END 42 | -------------------------------------------------------------------------------- /PGMappingKit/NSManagedObjectContext+PGObject.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2015 by Plot Guru. 3 | // 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | // 23 | 24 | #import "NSManagedObjectContext+PGObject.h" 25 | #import "PGMappingDescription.h" 26 | 27 | NS_ASSUME_NONNULL_BEGIN 28 | 29 | @implementation NSManagedObjectContext (PGObject) 30 | 31 | - (nullable id)objectWithType:(NSString *)type identifier:(nullable id)identifier forKey:(NSString *)key error:(NSError **)error 32 | { 33 | NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:type]; 34 | 35 | fetchRequest.predicate = [NSPredicate predicateWithFormat:@"%K == %@", key, identifier]; 36 | 37 | return [self executeFetchRequest:fetchRequest error:error].firstObject; 38 | } 39 | 40 | - (nullable NSArray *)objectsWithType:(NSString *)type error:(NSError **)error 41 | { 42 | return [self executeFetchRequest:[NSFetchRequest fetchRequestWithEntityName:type] error:error]; 43 | } 44 | 45 | - (nullable id)objectWithMapping:(PGMappingDescription *)mapping data:(nullable NSDictionary *)data error:(NSError **)error 46 | { 47 | return [self objectWithType:mapping.localName identifier:data ? data[mapping.remoteIDKey] : nil forKey:mapping.localIDKey error:error]; 48 | } 49 | 50 | - (nullable id)objectWithMapping:(PGMappingDescription *)mapping identifier:(nullable id)identifier error:(NSError **)error 51 | { 52 | return [self objectWithType:mapping.localName identifier:identifier forKey:mapping.remoteIDKey error:error]; 53 | } 54 | 55 | - (nullable NSArray *)objectsWithMapping:(PGMappingDescription *)mapping error:(NSError **)error 56 | { 57 | return [self objectsWithType:mapping.localName error:error]; 58 | } 59 | 60 | @end 61 | 62 | NS_ASSUME_NONNULL_END 63 | -------------------------------------------------------------------------------- /PGMappingKit/NSMutableDictionary+PGSafeCheck.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2015 by Plot Guru. 3 | // 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | // 23 | 24 | @import Foundation; 25 | 26 | NS_ASSUME_NONNULL_BEGIN 27 | 28 | @interface NSMutableDictionary (PGSafeCheck) 29 | 30 | - (void)setObjectIfExists:(nullable id)anObject forKey:(id)aKey; 31 | 32 | @end 33 | 34 | NS_ASSUME_NONNULL_END 35 | -------------------------------------------------------------------------------- /PGMappingKit/NSMutableDictionary+PGSafeCheck.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2015 by Plot Guru. 3 | // 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | // 23 | 24 | #import "NSMutableDictionary+PGSafeCheck.h" 25 | 26 | NS_ASSUME_NONNULL_BEGIN 27 | 28 | @implementation NSMutableDictionary (PGSafeCheck) 29 | 30 | - (void)setObjectIfExists:(nullable id)anObject forKey:(id)aKey 31 | { 32 | if (anObject) { 33 | self[aKey] = anObject; 34 | } else { 35 | [self removeObjectForKey:aKey]; 36 | } 37 | } 38 | 39 | @end 40 | 41 | NS_ASSUME_NONNULL_END -------------------------------------------------------------------------------- /PGMappingKit/NSObject+PGKeyValueCoding.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2015 by Plot Guru. 3 | // 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | // 23 | 24 | @import Foundation; 25 | 26 | NS_ASSUME_NONNULL_BEGIN 27 | 28 | @interface NSObject (PGKeyValueCoding) 29 | 30 | - (void)safelySetValue:(nullable id)value forKey:(NSString *)key; 31 | - (void)safelyAddValue:(nullable id)value forKey:(NSString *)key; 32 | 33 | @end 34 | 35 | NS_ASSUME_NONNULL_END -------------------------------------------------------------------------------- /PGMappingKit/NSObject+PGKeyValueCoding.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2015 by Plot Guru. 3 | // 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | // 23 | 24 | #import "NSObject+PGKeyValueCoding.h" 25 | 26 | NS_ASSUME_NONNULL_BEGIN 27 | 28 | @implementation NSObject (PGKeyValueCoding) 29 | 30 | - (void)safelySetValue:(nullable id)value forKey:(NSString *)key 31 | { 32 | if ([self respondsToSelector:NSSelectorFromString(key)]) { 33 | [self setValue:value forKey:key]; 34 | } 35 | } 36 | 37 | - (void)safelyAddValue:(nullable id)value forKey:(NSString *)key 38 | { 39 | if ([self respondsToSelector:NSSelectorFromString(key)]) { 40 | id oldValue = [self valueForKey:key]; 41 | if ([oldValue respondsToSelector:@selector(mutableCopy)]) { 42 | id newValue = [oldValue mutableCopy]; 43 | if ([newValue respondsToSelector:@selector(addObject:)] && value) { 44 | [newValue addObject:value]; 45 | [self setValue:newValue forKey:key]; 46 | } 47 | } 48 | } 49 | } 50 | 51 | @end 52 | 53 | NS_ASSUME_NONNULL_END 54 | 55 | -------------------------------------------------------------------------------- /PGMappingKit/NSObject+PGNilObject.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2015 by Plot Guru. 3 | // 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | // 23 | 24 | @import Foundation; 25 | 26 | #define PGEntity(Class) NSStringFromClass([Class class]) 27 | 28 | #define PGAttribute(Class, PropertyName) @(((void)(NO && ((void)[Class nilObject].PropertyName, NO)), # PropertyName)) 29 | 30 | NS_ASSUME_NONNULL_BEGIN 31 | 32 | @interface NSObject (PGPropertyName) 33 | 34 | + (nullable instancetype)nilObject; 35 | 36 | @end 37 | 38 | NS_ASSUME_NONNULL_END 39 | -------------------------------------------------------------------------------- /PGMappingKit/NSObject+PGNilObject.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2015 by Plot Guru. 3 | // 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | // 23 | 24 | #import "NSObject+PGNilObject.h" 25 | 26 | NS_ASSUME_NONNULL_BEGIN 27 | 28 | @implementation NSObject (PGPropertyName) 29 | 30 | + (nullable instancetype)nilObject 31 | { 32 | return nil; 33 | } 34 | 35 | @end 36 | 37 | NS_ASSUME_NONNULL_END 38 | -------------------------------------------------------------------------------- /PGMappingKit/NSObject+PGPropertyList.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2015 by Plot Guru. 3 | // 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | // 23 | 24 | @import Foundation; 25 | @import ObjectiveC.runtime; 26 | 27 | NS_ASSUME_NONNULL_BEGIN 28 | 29 | @interface NSObject (PGPropertyList) 30 | 31 | + (nullable NSDictionary *)propertiesOfObject:(nullable id)object; 32 | + (nullable NSDictionary *)propertiesOfClass:(nullable Class)classType; 33 | + (nullable NSDictionary *)propertiesOfSubclass:(nullable Class)classType; 34 | 35 | @end 36 | 37 | NS_ASSUME_NONNULL_END 38 | -------------------------------------------------------------------------------- /PGMappingKit/NSObject+PGPropertyList.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2015 by Plot Guru. 3 | // 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | // 23 | 24 | #import "NSObject+PGPropertyList.h" 25 | 26 | NS_ASSUME_NONNULL_BEGIN 27 | 28 | @implementation NSObject (PGPropertyList) 29 | 30 | + (nullable NSDictionary *)propertiesOfObject:(nullable id)object 31 | { 32 | return [self propertiesOfClass:[object class]]; 33 | } 34 | 35 | + (nullable NSDictionary *)propertiesOfClass:(nullable Class)classType 36 | { 37 | return [self propertiesForHierarchyOfClass:classType onDictionary:[NSMutableDictionary dictionary]]; 38 | } 39 | 40 | + (nullable NSDictionary *)propertiesOfSubclass:(nullable Class)classType 41 | { 42 | if (classType == NULL) { 43 | return nil; 44 | } 45 | 46 | return [self propertiesForSubclass:classType onDictionary:[NSMutableDictionary dictionary]]; 47 | } 48 | 49 | + (NSMutableDictionary *)propertiesForHierarchyOfClass:(Class)classType onDictionary:(NSMutableDictionary *)properties 50 | { 51 | if (classType == NULL) { 52 | return nil; 53 | } 54 | 55 | if (classType == [NSObject class]) { 56 | return properties; 57 | } 58 | 59 | [self propertiesForSubclass:classType onDictionary:properties]; 60 | 61 | return [self propertiesForHierarchyOfClass:[classType superclass] onDictionary:properties]; 62 | } 63 | 64 | + (NSMutableDictionary *)propertiesForSubclass:(Class)classType onDictionary:(NSMutableDictionary *)properties 65 | { 66 | unsigned int numberOfProperties = 0; 67 | objc_property_t *propertyList = class_copyPropertyList(classType, &numberOfProperties); 68 | for (unsigned int i = 0; i < numberOfProperties; i++) { 69 | objc_property_t property = propertyList[i]; 70 | const char *propertyName = property_getName(property); 71 | if(propertyName) { 72 | const char *propertyType = getPropertyType(property); 73 | properties[@(propertyName)] = @(propertyType); 74 | } 75 | } 76 | free(propertyList); 77 | 78 | return properties; 79 | } 80 | 81 | static const char *getPropertyType(objc_property_t property) 82 | { 83 | const char *attributes = property_getAttributes(property); 84 | char buffer[1 + strlen(attributes)]; 85 | strcpy(buffer, attributes); 86 | char *state = buffer, *attribute; 87 | while ((attribute = strsep(&state, ",")) != NULL) { 88 | if (attribute[0] == 'T' && attribute[1] != '@') { // C primitive type (search "Objective-C Property Attribute Description Examples" for examples) 89 | NSString *name = [[NSString alloc] initWithBytes:attribute + 1 length:strlen(attribute) - 1 encoding:NSASCIIStringEncoding]; 90 | return (const char *)[name cStringUsingEncoding:NSASCIIStringEncoding]; 91 | } else if (attribute[0] == 'T' && attribute[1] == '@' && strlen(attribute) == 2) { // Objective-C id type 92 | return "id"; 93 | } else if (attribute[0] == 'T' && attribute[1] == '@') { // Another Objective-C id type 94 | NSString *name = [[NSString alloc] initWithBytes:attribute + 3 length:strlen(attribute) - 4 encoding:NSASCIIStringEncoding]; 95 | return (const char *)[name cStringUsingEncoding:NSASCIIStringEncoding]; 96 | } 97 | } 98 | return ""; 99 | } 100 | 101 | @end 102 | 103 | NS_ASSUME_NONNULL_END 104 | -------------------------------------------------------------------------------- /PGMappingKit/PGMappingDescription.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2015 by Plot Guru. 3 | // 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | // 23 | 24 | @import Foundation; 25 | 26 | NS_ASSUME_NONNULL_BEGIN 27 | 28 | /** 29 | * `PGMappingDescription` is used to describe the relationship between a Core Data entity and its related JSON response. It supports one-way nested mapping description. 30 | */ 31 | @interface PGMappingDescription : NSObject 32 | 33 | /** 34 | * The name of the represented entity. 35 | */ 36 | @property (strong, nonatomic, readonly) NSString *localName; 37 | 38 | /** 39 | * The outmost key of the represented JSON response. Will be ignored if this `PGMappingDescription` is not nested. 40 | */ 41 | @property (strong, nonatomic, readonly) NSString *remoteName; 42 | 43 | /** 44 | * The unique ID key of the represented entity. 45 | */ 46 | @property (strong, nonatomic, readonly) NSString *localIDKey; 47 | 48 | /** 49 | * The unique ID key of the represented JSON response. 50 | */ 51 | @property (strong, nonatomic, readonly) NSString *remoteIDKey; 52 | 53 | /** 54 | * Creates and returns a `PGMappingDescription` object. 55 | * 56 | * @param names A dictionary with only one value. Key is the outmost key of the represented JSON response and value is the name of the represented entity. 57 | * @param IDs A dictionary with only one value. Key is the unique ID key of the represented JSON response and value is the unique ID key of the represented entity. 58 | * @param mapping The relationship between the represented entity and JSON response. Keys are keys of the represented JSON reponse and values are attributes' names of the represented entity. Don't need to include `localIDKey` and `remoteIDKey` again. 59 | * 60 | * @return Created `PGMappingDescription` object. 61 | */ 62 | + (instancetype)name:(NSDictionary *)names ID:(NSDictionary *)IDs mapping:(NSDictionary *)mapping; 63 | 64 | /** 65 | * Creates and returns a `PGMappingDescription` object. 66 | * 67 | * @param localName The name of the represented entity. 68 | * @param remoteName The outmost key of the represented JSON response. 69 | * @param localIDKey The unique ID key of the represented entity. 70 | * @param remoteIDKey The unique ID key of the represented JSON response. 71 | * @param mapping The relationship between the represented entity and JSON response. Keys are keys of the represented JSON reponse and values are attributes' names of the represented entity. Don't need to include `localIDKey` and `remoteIDKey` again. 72 | * 73 | * @return Created `PGMappingDescription` object. 74 | */ 75 | - (instancetype)initWithLocalName:(NSString *)localName 76 | remoteName:(NSString *)remoteName 77 | localIDKey:(NSString *)localIDKey 78 | remoteIDKey:(NSString *)remoteIDKey 79 | mapping:(NSDictionary *)mapping NS_DESIGNATED_INITIALIZER; 80 | 81 | /** 82 | * Returns an attribute's name or another `PGMappingDescription` object. 83 | * 84 | * @param remoteKey A key in the represented JSON response. 85 | * 86 | * @return An attribute's name in the represented entity or another `PGMappingDescription` object. Will return the input is nothing is found. 87 | */ 88 | - (id)localKeyForRemoteKey:(NSString *)remoteKey; 89 | 90 | /** 91 | * Returns a key. 92 | * 93 | * @param localKey An attribute's name in the represented entity or another `PGMappingDescription` object. 94 | * 95 | * @return A key in the represented JSON response or another `PGMappingDescription` object. Will return the input if nothing is found. 96 | */ 97 | - (NSString *)remoteKeyForLocalKey:(id)localKey; 98 | 99 | @end 100 | 101 | NS_ASSUME_NONNULL_END 102 | -------------------------------------------------------------------------------- /PGMappingKit/PGMappingDescription.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2015 by Plot Guru. 3 | // 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | // 23 | 24 | #import "PGMappingDescription.h" 25 | 26 | NS_ASSUME_NONNULL_BEGIN 27 | 28 | @interface PGMappingDescription () 29 | 30 | @property (strong, nonatomic) NSString *localName; 31 | 32 | @property (strong, nonatomic) NSString *remoteName; 33 | 34 | @property (strong, nonatomic) NSString *localIDKey; 35 | 36 | @property (strong, nonatomic) NSString *remoteIDKey; 37 | 38 | @property (strong, nonatomic) NSMutableDictionary *mapping; 39 | 40 | @end 41 | 42 | @implementation PGMappingDescription 43 | 44 | + (instancetype)name:(NSDictionary *)names ID:(NSDictionary *)IDs mapping:(NSDictionary *)mapping 45 | { 46 | return [[self alloc] initWithLocalName:names.allValues.firstObject ?: @"" 47 | remoteName:names.allKeys.firstObject ?: @"" 48 | localIDKey:IDs.allValues.firstObject ?: @"" 49 | remoteIDKey:IDs.allKeys.firstObject ?: @"" 50 | mapping:mapping]; 51 | } 52 | 53 | - (instancetype)init 54 | { 55 | return [self initWithLocalName:@"" remoteName:@"" localIDKey:@"" remoteIDKey:@"" mapping:@{}]; 56 | } 57 | 58 | - (instancetype)initWithLocalName:(NSString *)localName 59 | remoteName:(NSString *)remoteName 60 | localIDKey:(NSString *)localIDKey 61 | remoteIDKey:(NSString *)remoteIDKey 62 | mapping:(NSDictionary *)mapping 63 | { 64 | self = [super init]; 65 | if (self) { 66 | self.localName = localName; 67 | self.remoteName = remoteName; 68 | self.localIDKey = localIDKey; 69 | self.remoteIDKey = remoteIDKey; 70 | 71 | self.mapping = mapping.mutableCopy; 72 | self.mapping[remoteIDKey] = localIDKey; 73 | } 74 | return self; 75 | } 76 | 77 | - (id)localKeyForRemoteKey:(NSString *)remoteKey; 78 | { 79 | return self.mapping[remoteKey] ?: remoteKey; 80 | } 81 | 82 | - (NSString *)remoteKeyForLocalKey:(id)localKey 83 | { 84 | return [self.mapping allKeysForObject:localKey].firstObject ?: localKey; 85 | } 86 | 87 | @end 88 | 89 | NS_ASSUME_NONNULL_END 90 | -------------------------------------------------------------------------------- /PGMappingKit/PGMappingKit.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2015 by Plot Guru. 3 | // 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | // 23 | 24 | @import Foundation; 25 | @import AFNetworking; 26 | 27 | FOUNDATION_EXPORT double PGMappingKitVersionNumber; 28 | FOUNDATION_EXPORT const unsigned char PGMappingKitVersionString[]; 29 | 30 | #import 31 | #import 32 | #import 33 | #import 34 | #import 35 | #import 36 | #import 37 | -------------------------------------------------------------------------------- /PGMappingKit/PGNetworkHandler+PGCoreData.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2015 by Plot Guru. 3 | // 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | // 23 | 24 | @import CoreData; 25 | 26 | typedef NS_ENUM(NSInteger, PGSaveOption) { 27 | PGSaveOptionUpdate, 28 | PGSaveOptionReplace, 29 | PGSaveOptionReplaceAll, 30 | }; 31 | 32 | #import "PGNetworkHandler.h" 33 | 34 | NS_ASSUME_NONNULL_BEGIN 35 | 36 | @interface PGNetworkHandler (PGCoreData) 37 | 38 | - (nullable NSURLSessionDataTask *)PUT:(NSString *)URLString 39 | from:(nullable NSDictionary *)data 40 | to:(NSManagedObjectContext *)context 41 | mapping:(PGMappingDescription *)mapping 42 | option:(PGSaveOption)option 43 | success:(nullable void (^)(NSURLSessionDataTask *task, NSArray *results))success 44 | failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure 45 | finish:(nullable void (^)(NSURLSessionDataTask * _Nullable task))finish; 46 | 47 | - (nullable NSURLSessionDataTask *)POST:(NSString *)URLString 48 | from:(nullable NSDictionary *)data 49 | to:(NSManagedObjectContext *)context 50 | mapping:(PGMappingDescription *)mapping 51 | option:(PGSaveOption)option 52 | progress:(nullable void (^)(NSProgress *progress))progress 53 | success:(nullable void (^)(NSURLSessionDataTask *task, NSArray *results))success 54 | failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure 55 | finish:(nullable void (^)(NSURLSessionDataTask * _Nullable task))finish; 56 | 57 | - (nullable NSURLSessionDataTask *)GET:(NSString *)URLString 58 | from:(nullable NSDictionary *)data 59 | to:(NSManagedObjectContext *)context 60 | mapping:(PGMappingDescription *)mapping 61 | option:(PGSaveOption)option 62 | progress:(nullable void (^)(NSProgress *progress))progress 63 | success:(nullable void (^)(NSURLSessionDataTask *task, NSArray *results))success 64 | failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure 65 | finish:(nullable void (^)(NSURLSessionDataTask * _Nullable task))finish; 66 | 67 | - (nullable NSURLSessionDataTask *)DELETE:(NSString *)URLString 68 | from:(nullable NSDictionary *)data 69 | to:(NSManagedObjectContext *)context 70 | mapping:(PGMappingDescription *)mapping 71 | option:(PGSaveOption)option 72 | success:(nullable void (^)(NSURLSessionDataTask *task, NSArray *results))success 73 | failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure 74 | finish:(nullable void (^)(NSURLSessionDataTask * _Nullable task))finish; 75 | 76 | @end 77 | 78 | NS_ASSUME_NONNULL_END 79 | -------------------------------------------------------------------------------- /PGMappingKit/PGNetworkHandler+PGCoreData.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2015 by Plot Guru. 3 | // 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | // 23 | 24 | #import "PGNetworkHandler+PGCoreData.h" 25 | #import "PGMappingDescription.h" 26 | #import "NSManagedObjectContext+PGObject.h" 27 | #import "NSManagedObjectContext+PGMapping.h" 28 | 29 | NS_ASSUME_NONNULL_BEGIN 30 | 31 | @interface PGNetworkHandler (PGCoreDataInternal) 32 | 33 | - (void)succeedWithTask:(NSURLSessionDataTask *)task 34 | responseObject:(nullable id)responseObject 35 | context:(NSManagedObjectContext *)context 36 | mapping:(PGMappingDescription *)mapping 37 | option:(PGSaveOption)option 38 | success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success 39 | failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure; 40 | 41 | @end 42 | 43 | @implementation PGNetworkHandler (PGCoreDataInternal) 44 | 45 | - (void)succeedWithTask:(NSURLSessionDataTask *)task 46 | responseObject:(nullable id)responseObject 47 | context:(NSManagedObjectContext *)context 48 | mapping:(PGMappingDescription *)mapping 49 | option:(PGSaveOption)option 50 | success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success 51 | failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure 52 | { 53 | NSError *error = nil; 54 | 55 | if (option == PGSaveOptionReplaceAll) { 56 | NSArray *oldObjects = [context objectsWithMapping:mapping error:&error]; 57 | 58 | for (NSManagedObject *oldObject in oldObjects) { 59 | [context deleteObject:oldObject]; 60 | } 61 | } 62 | 63 | [context save:&error]; 64 | 65 | NSMutableArray *results = [NSMutableArray array]; 66 | 67 | NSArray *responseArray = [responseObject isKindOfClass:[NSArray class]] ? responseObject : (responseObject ? @[responseObject] : nil); 68 | for (id responseArrayItem in responseArray) { 69 | if ([responseArrayItem isKindOfClass:[NSDictionary class]]) { 70 | if (option == PGSaveOptionReplace) { 71 | NSManagedObject *object = [context objectWithMapping:mapping data:responseArrayItem error:&error]; 72 | if (object) { 73 | [context deleteObject:object]; 74 | } 75 | } 76 | [results addObject:[context save:responseArrayItem description:mapping error:&error]]; 77 | } 78 | } 79 | 80 | [context save:&error]; 81 | 82 | if (!error) { 83 | if (success) { 84 | success(task, results.copy); 85 | } 86 | } else { 87 | if (failure) { 88 | failure(task, error); 89 | } 90 | } 91 | } 92 | 93 | @end 94 | 95 | @implementation PGNetworkHandler (PGCoreData) 96 | 97 | - (nullable NSURLSessionDataTask *)PUT:(NSString *)URLString 98 | from:(nullable NSDictionary *)data 99 | to:(NSManagedObjectContext *)context 100 | mapping:(PGMappingDescription *)mapping 101 | option:(PGSaveOption)option 102 | success:(nullable void (^)(NSURLSessionDataTask *task, NSArray *results))success 103 | failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure 104 | finish:(nullable void (^)(NSURLSessionDataTask * _Nullable task))finish 105 | { 106 | return [self PUT:URLString from:data success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { 107 | [self succeedWithTask:task responseObject:responseObject context:context mapping:mapping option:option success:success failure:failure]; 108 | } failure:failure finish:finish]; 109 | } 110 | 111 | - (nullable NSURLSessionDataTask *)POST:(NSString *)URLString 112 | from:(nullable NSDictionary *)data 113 | to:(NSManagedObjectContext *)context 114 | mapping:(PGMappingDescription *)mapping 115 | option:(PGSaveOption)option 116 | progress:(nullable void (^)(NSProgress *progress))progress 117 | success:(nullable void (^)(NSURLSessionDataTask *task, NSArray *results))success 118 | failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure 119 | finish:(nullable void (^)(NSURLSessionDataTask * _Nullable task))finish 120 | { 121 | return [self POST:URLString from:data progress:progress success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { 122 | [self succeedWithTask:task responseObject:responseObject context:context mapping:mapping option:option success:success failure:failure]; 123 | } failure:failure finish:finish]; 124 | } 125 | 126 | - (nullable NSURLSessionDataTask *)GET:(NSString *)URLString 127 | from:(nullable NSDictionary *)data 128 | to:(NSManagedObjectContext *)context 129 | mapping:(PGMappingDescription *)mapping 130 | option:(PGSaveOption)option 131 | progress:(nullable void (^)(NSProgress *progress))progress 132 | success:(nullable void (^)(NSURLSessionDataTask *task, NSArray *results))success 133 | failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure 134 | finish:(nullable void (^)(NSURLSessionDataTask * _Nullable task))finish 135 | { 136 | return [self GET:URLString from:data progress:progress success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { 137 | [self succeedWithTask:task responseObject:responseObject context:context mapping:mapping option:option success:success failure:failure]; 138 | } failure:failure finish:finish]; 139 | } 140 | 141 | - (nullable NSURLSessionDataTask *)DELETE:(NSString *)URLString 142 | from:(nullable NSDictionary *)data 143 | to:(NSManagedObjectContext *)context 144 | mapping:(PGMappingDescription *)mapping 145 | option:(PGSaveOption)option 146 | success:(nullable void (^)(NSURLSessionDataTask *task, NSArray *results))success 147 | failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure 148 | finish:(nullable void (^)(NSURLSessionDataTask * _Nullable task))finish 149 | { 150 | return [self DELETE:URLString from:data success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { 151 | [self succeedWithTask:task responseObject:responseObject context:context mapping:mapping option:option success:success failure:failure]; 152 | } failure:failure finish:finish]; 153 | } 154 | 155 | @end 156 | 157 | NS_ASSUME_NONNULL_END 158 | -------------------------------------------------------------------------------- /PGMappingKit/PGNetworkHandler+PGData.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2016 by Plot Guru. 3 | // 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | // 23 | 24 | #import "PGNetworkHandler.h" 25 | 26 | NS_ASSUME_NONNULL_BEGIN 27 | 28 | @interface PGNetworkHandler (PGData) 29 | 30 | - (NSMutableDictionary *)dataFromObject:(nullable id)object mapping:(PGMappingDescription *)mapping; 31 | 32 | @end 33 | 34 | NS_ASSUME_NONNULL_END 35 | -------------------------------------------------------------------------------- /PGMappingKit/PGNetworkHandler+PGData.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2016 by Plot Guru. 3 | // 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | // 23 | 24 | #import "PGNetworkHandler+PGData.h" 25 | #import "PGMappingDescription.h" 26 | #import "NSMutableDictionary+PGSafeCheck.h" 27 | #import "NSObject+PGPropertyList.h" 28 | 29 | NS_ASSUME_NONNULL_BEGIN 30 | 31 | @implementation PGNetworkHandler (PGData) 32 | 33 | - (NSMutableDictionary *)dataFromObject:(nullable id)object mapping:(PGMappingDescription *)mapping; 34 | { 35 | NSMutableDictionary *data = [NSMutableDictionary dictionary]; 36 | 37 | NSDictionary *properties = [NSObject propertiesOfObject:object]; 38 | for (NSString *propertyName in properties.allKeys) { 39 | NSString *remoteKey = [mapping remoteKeyForLocalKey:propertyName]; 40 | [data setObjectIfExists:[object valueForKey:propertyName] forKey:remoteKey]; 41 | } 42 | 43 | return data; 44 | } 45 | 46 | @end 47 | 48 | NS_ASSUME_NONNULL_END 49 | -------------------------------------------------------------------------------- /PGMappingKit/PGNetworkHandler.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2015 by Plot Guru. 3 | // 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | // 23 | 24 | @import AFNetworking; 25 | 26 | @class PGMappingDescription; 27 | 28 | NS_ASSUME_NONNULL_BEGIN 29 | 30 | @interface PGNetworkHandler : AFHTTPSessionManager 31 | 32 | @property (nonatomic, getter=isCanceled) BOOL canceled; 33 | 34 | - (nullable NSURLSessionDataTask *)PUT:(NSString *)URLString 35 | from:(nullable NSDictionary *)data 36 | success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success 37 | failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure 38 | finish:(nullable void (^)(NSURLSessionDataTask * _Nullable task))finish; 39 | 40 | - (nullable NSURLSessionDataTask *)POST:(NSString *)URLString 41 | from:(nullable NSDictionary *)data 42 | progress:(nullable void (^)(NSProgress *progress))progress 43 | success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success 44 | failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure 45 | finish:(nullable void (^)(NSURLSessionDataTask * _Nullable task))finish; 46 | 47 | - (nullable NSURLSessionDataTask *)GET:(NSString *)URLString 48 | from:(nullable NSDictionary *)data 49 | progress:(nullable void (^)(NSProgress *progress))progress 50 | success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success 51 | failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure 52 | finish:(nullable void (^)(NSURLSessionDataTask * _Nullable task))finish; 53 | 54 | - (nullable NSURLSessionDataTask *)DELETE:(NSString *)URLString 55 | from:(nullable NSDictionary *)data 56 | success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success 57 | failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure 58 | finish:(nullable void (^)(NSURLSessionDataTask * _Nullable task))finish; 59 | 60 | @end 61 | 62 | NS_ASSUME_NONNULL_END 63 | -------------------------------------------------------------------------------- /PGMappingKit/PGNetworkHandler.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2015 by Plot Guru. 3 | // 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | // 23 | 24 | #import "PGNetworkHandler.h" 25 | #import "PGMappingDescription.h" 26 | 27 | NS_ASSUME_NONNULL_BEGIN 28 | 29 | @interface PGNetworkHandler () 30 | 31 | - (void)succeedWithTask:(NSURLSessionDataTask *)task 32 | responseObject:(nullable id)responseObject 33 | success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success 34 | finish:(nullable void (^)(NSURLSessionDataTask * _Nullable task))finish; 35 | 36 | - (void)failedWithTask:(nullable NSURLSessionDataTask *)task 37 | error:(NSError *)error 38 | failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure 39 | finish:(nullable void (^)(NSURLSessionDataTask * _Nullable task))finish; 40 | 41 | @end 42 | 43 | @implementation PGNetworkHandler 44 | 45 | - (instancetype)initWithBaseURL:(nullable NSURL *)url sessionConfiguration:(nullable NSURLSessionConfiguration *)configuration 46 | { 47 | self = [super initWithBaseURL:url sessionConfiguration:configuration]; 48 | if (self) { 49 | self.requestSerializer = [AFJSONRequestSerializer serializer]; 50 | self.responseSerializer = [AFJSONResponseSerializer serializer]; 51 | } 52 | return self; 53 | } 54 | 55 | - (void)succeedWithTask:(NSURLSessionDataTask *)task 56 | responseObject:(nullable id)responseObject 57 | success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success 58 | finish:(nullable void (^)(NSURLSessionDataTask * _Nullable task))finish 59 | { 60 | if (self.isCanceled) { 61 | return; 62 | } 63 | 64 | [[NSOperationQueue mainQueue] addOperationWithBlock:^{ 65 | if (success) { 66 | success(task, responseObject); 67 | } 68 | 69 | if (finish) { 70 | finish(task); 71 | } 72 | }]; 73 | } 74 | 75 | - (void)failedWithTask:(nullable NSURLSessionDataTask *)task 76 | error:(NSError *)error 77 | failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure 78 | finish:(nullable void (^)(NSURLSessionDataTask * _Nullable task))finish 79 | { 80 | if (self.isCanceled) { 81 | return; 82 | } 83 | 84 | [[NSOperationQueue mainQueue] addOperationWithBlock:^{ 85 | if (failure) { 86 | failure(task, error); 87 | } 88 | 89 | if (finish) { 90 | finish(task); 91 | } 92 | }]; 93 | } 94 | 95 | #pragma mark - PUT 96 | 97 | - (nullable NSURLSessionDataTask *)PUT:(NSString *)URLString 98 | from:(nullable NSDictionary *)data 99 | success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success 100 | failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure 101 | finish:(nullable void (^)(NSURLSessionDataTask * _Nullable task))finish 102 | { 103 | return [self PUT:URLString parameters:data success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { 104 | [self succeedWithTask:task responseObject:responseObject success:success finish:finish]; 105 | } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { 106 | [self failedWithTask:task error:error failure:failure finish:finish]; 107 | }]; 108 | } 109 | 110 | #pragma mark - POST 111 | 112 | - (nullable NSURLSessionDataTask *)POST:(NSString *)URLString 113 | from:(nullable NSDictionary *)data 114 | progress:(nullable void (^)(NSProgress *progress))progress 115 | success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success 116 | failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure 117 | finish:(nullable void (^)(NSURLSessionDataTask * _Nullable task))finish 118 | { 119 | return [self POST:URLString parameters:data progress:progress success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { 120 | [self succeedWithTask:task responseObject:responseObject success:success finish:finish]; 121 | } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { 122 | [self failedWithTask:task error:error failure:failure finish:finish]; 123 | }]; 124 | } 125 | 126 | #pragma mark - GET 127 | 128 | - (nullable NSURLSessionDataTask *)GET:(NSString *)URLString 129 | from:(nullable NSDictionary *)data 130 | progress:(nullable void (^)(NSProgress *progress))progress 131 | success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success 132 | failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure 133 | finish:(nullable void (^)(NSURLSessionDataTask * _Nullable task))finish 134 | { 135 | return [self GET:URLString parameters:data progress:progress success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { 136 | [self succeedWithTask:task responseObject:responseObject success:success finish:finish]; 137 | } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { 138 | [self failedWithTask:task error:error failure:failure finish:finish]; 139 | }]; 140 | } 141 | 142 | #pragma mark - DELETE 143 | 144 | - (nullable NSURLSessionDataTask *)DELETE:(NSString *)URLString 145 | from:(nullable NSDictionary *)data 146 | success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success 147 | failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure 148 | finish:(nullable void (^)(NSURLSessionDataTask * _Nullable task))finish 149 | { 150 | return [self DELETE:URLString parameters:data success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { 151 | [self succeedWithTask:task responseObject:responseObject success:success finish:finish]; 152 | } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { 153 | [self failedWithTask:task error:error failure:failure finish:finish]; 154 | }]; 155 | } 156 | 157 | @end 158 | 159 | NS_ASSUME_NONNULL_END 160 | -------------------------------------------------------------------------------- /PGMappingKitTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /PGMappingKitTests/PGNetworkMappingTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2015 by Plot Guru. 3 | // 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | // 23 | 24 | @import XCTest; 25 | 26 | #import "PGMappingDescription.h" 27 | 28 | @interface PGMappingDescriptionTests : XCTestCase 29 | 30 | @property (strong, nonatomic) NSArray *userInfoDescriptionArray; 31 | @property (strong, nonatomic) NSDictionary *userInfoMappingDictionary; 32 | 33 | @property (strong, nonatomic) NSString *userInfoEntityName; 34 | @property (strong, nonatomic) NSString *userInfoMappedKey; 35 | 36 | @property (strong, nonatomic) NSString *userInfoUniqueIdentifierKey; 37 | @property (strong, nonatomic) NSString *userInfoMappedUniqueIdentifierKey; 38 | 39 | @property (strong, nonatomic) NSString *imageURLAttributeName; 40 | @property (strong, nonatomic) NSString *imageURLKey; 41 | 42 | @property (strong, nonatomic) NSString *usernameAttributeName; 43 | @property (strong, nonatomic) NSString *usernameKey; 44 | 45 | @end 46 | 47 | @implementation PGMappingDescriptionTests 48 | 49 | - (void)setUp 50 | { 51 | [super setUp]; 52 | 53 | self.userInfoEntityName = @"PGUserInfo"; 54 | self.userInfoMappedKey = @"user_info"; 55 | 56 | self.userInfoUniqueIdentifierKey = @"uniqueID"; 57 | self.userInfoMappedUniqueIdentifierKey = @"id"; 58 | 59 | self.imageURLAttributeName = @"imageURL"; 60 | self.imageURLKey = @"image_url"; 61 | 62 | self.usernameAttributeName = @"username"; 63 | self.usernameKey = @"username"; 64 | 65 | self.userInfoDescriptionArray = @[@{self.userInfoMappedKey: self.userInfoEntityName}, @{self.userInfoMappedUniqueIdentifierKey: self.userInfoUniqueIdentifierKey}]; 66 | self.userInfoMappingDictionary = @{self.imageURLKey: self.imageURLAttributeName, self.usernameKey: self.usernameAttributeName}; 67 | } 68 | 69 | - (void)tearDown 70 | { 71 | [super tearDown]; 72 | } 73 | 74 | - (void)testInit 75 | { 76 | PGMappingDescription *mappingA = [PGMappingDescription mappingFromDescription:self.userInfoDescriptionArray description:self.userInfoMappingDictionary]; 77 | PGMappingDescription *mappingB = [[PGMappingDescription alloc] initWithDescription:self.userInfoDescriptionArray description:self.userInfoMappingDictionary]; 78 | 79 | XCTAssertEqualObjects(mappingA.localName, mappingB.localName); 80 | XCTAssertEqualObjects(mappingA.remoteName, mappingB.remoteName); 81 | XCTAssertEqualObjects(mappingA.localIDKey, mappingB.localIDKey); 82 | XCTAssertEqualObjects(mappingA.mappedUniqueIdentifierKey, mappingB.mappedUniqueIdentifierKey); 83 | XCTAssertEqualObjects([mappingA mappingForKey:self.imageURLKey], [mappingB mappingForKey:self.imageURLKey]); 84 | XCTAssertEqualObjects([mappingA mappingForKey:self.usernameKey], [mappingB mappingForKey:self.usernameKey]); 85 | 86 | XCTAssertNoThrow([PGMappingDescription mappingFromDescription:nil description:nil]); 87 | XCTAssertNoThrow([PGMappingDescription new]); 88 | } 89 | 90 | - (void)testSimpleMapping 91 | { 92 | PGMappingDescription *mapping = [PGMappingDescription mappingFromDescription:self.userInfoDescriptionArray description:self.userInfoMappingDictionary]; 93 | 94 | XCTAssertEqualObjects(mapping.localName, self.userInfoEntityName); 95 | XCTAssertEqualObjects(mapping.remoteName, self.userInfoMappedKey); 96 | XCTAssertEqualObjects(mapping.localIDKey, self.userInfoUniqueIdentifierKey); 97 | XCTAssertEqualObjects(mapping.mappedUniqueIdentifierKey, self.userInfoMappedUniqueIdentifierKey); 98 | 99 | XCTAssertEqualObjects([mapping mappingForKey:self.imageURLKey], self.imageURLAttributeName, @"Attribute name and the key are different."); 100 | XCTAssertEqualObjects([mapping mappingForKey:self.usernameKey], self.usernameAttributeName, @"Attribute name and the key are the same."); 101 | XCTAssertEqualObjects([mapping mappingForKey:self.userInfoMappedUniqueIdentifierKey], self.userInfoUniqueIdentifierKey, @"Mapped unique identifier is the key."); 102 | 103 | XCTAssertNil([mapping mappingForKey:self.imageURLAttributeName], @"Use attribute's name as the key."); 104 | XCTAssertNil([mapping mappingForKey:nil], @"No key is specified."); 105 | } 106 | 107 | - (void)testNestedMapping 108 | { 109 | PGMappingDescription *userInfoMapping = [PGMappingDescription mappingFromDescription:self.userInfoDescriptionArray description:self.userInfoMappingDictionary]; 110 | PGMappingDescription *userListMapping = [PGMappingDescription mappingFromDescription:@[@{@"user_lists": @"PGUserList"}, @{@"list_id": @"listID"}] description:@{@"list_name": @"listName", @"users": userInfoMapping}]; 111 | 112 | XCTAssertEqualObjects(userListMapping.localName, @"PGUserList"); 113 | 114 | XCTAssertEqualObjects([userListMapping mappingForKey:@"users"], userInfoMapping); 115 | XCTAssertEqualObjects([userListMapping mappingForKey:@"list_id"], @"listID"); 116 | 117 | XCTAssertNil([userListMapping mappingForKey:self.usernameKey], @"Use one of user info mapping's key."); 118 | } 119 | 120 | @end 121 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![](https://cloud.githubusercontent.com/assets/3337361/12528689/6b7c5292-c153-11e5-9d61-cef986b7c919.png) 2 | 3 | [![Carthage Compatible](https://img.shields.io/badge/carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) 4 | [![Version](https://img.shields.io/cocoapods/v/PGMappingKit.svg?style=flat)](http://cocoapods.org/pods/PGMappingKit) 5 | [![License](https://img.shields.io/cocoapods/l/PGMappingKit.svg?style=flat)](http://cocoapods.org/pods/PGMappingKit) 6 | [![Platform](https://img.shields.io/cocoapods/p/PGMappingKit.svg?style=flat)](http://cocoapods.org/pods/PGMappingKit) 7 | 8 | **PGMappingKit** helps you parsing a JSON response and getting it into Core Data. It is built on top of [AFNetworking 3](https://github.com/AFNetworking/AFNetworking). 9 | 10 | ## Requirements 11 | 12 | - iOS 8.0+ 13 | - Xcode 7.2+ 14 | 15 | ## Installation 16 | 17 | ### Carthage 18 | 19 | Source is available through [Carthage](https://github.com/Carthage/Carthage). To install it, add the following line to your Cartfile: 20 | 21 | ```ogdl 22 | github "PlotGuru/PGMappingKit" ~> 1.0 23 | ``` 24 | 25 | ### CocoaPods 26 | 27 | Source is available through [CocoaPods](http://cocoapods.org). To install it, add the following line to your Podfile: 28 | 29 | ```ruby 30 | pod 'PGMappingKit', '~> 1.0' 31 | ``` 32 | 33 | ## Example 34 | 35 | Assuming you have the Core Data model shown in the image below: 36 | 37 | ![](https://cloud.githubusercontent.com/assets/3337361/12500157/6a3871ca-c065-11e5-9469-4fa5c62b6925.png) 38 | 39 | Assuming you have the following JSON that can be retrieved from `www.example.com/user`: 40 | 41 | ```json 42 | [ 43 | { 44 | "id": 6, 45 | "name": "Justin Jia", 46 | "posts": [ 47 | { 48 | "id": 0, 49 | "text": "Hello, PGMappingKit!" 50 | } 51 | ] 52 | } 53 | ] 54 | ``` 55 | 56 | You can retrieve, parse the JSON response and get it into Core Data by using the following code: 57 | 58 | ```objc 59 | // Initialize Network Handler 60 | 61 | PGNetworkHandler *networkHandler = [PGNetworkHandler alloc] initWithBaseURL:[NSURL URLWithString:@"www.example.com"]]; 62 | 63 | // Describe Relationship 64 | 65 | PGMappingDescription *postMapping = [PGMappingDescription name:@{@"posts": PGEntity(Post)} 66 | ID:@{@"id": PGAttribute(Post, uniqueID)} 67 | mapping:@{@"text": PGAttribute(Post, text)}]; 68 | PGMappingDescription *userMapping = [PGMappingDescription name:@{@"": PGEntity(User)} 69 | ID:@{@"id": PGAttribute(User, uniqueID)} 70 | mapping:@{@"name": PGAttribute(User, username), 71 | @"posts": postMapping}]; 72 | 73 | // Perform GET Request 74 | 75 | [self.networkHandler GET:@"user" 76 | from:nil 77 | to:context 78 | mapping:userMapping 79 | option:PGSaveOptionUpdate 80 | progress:nil 81 | success:^(NSURLSessionDataTask * _Nonnull task, NSArray * _Nonnull results) { 82 | // Finish Login 83 | } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { 84 | // Show Error 85 | } finish:^(NSURLSessionDataTask * _Nullable task) { 86 | // Refresh UI 87 | }]; 88 | ``` 89 | ## Usage 90 | 91 | Use `PGNetworkHandler.h` like AFNetworking's `AFHTTPSessionManager.h` but with the additional `finish` block that will be called after either `success` or `failure` is finished. 92 | 93 | ```objc 94 | - (nullable NSURLSessionDataTask *)PUT:(NSString *)URLString 95 | from:(nullable NSDictionary *)data 96 | success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success 97 | failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure 98 | finish:(nullable void (^)(NSURLSessionDataTask * _Nullable task))finish; 99 | 100 | - (nullable NSURLSessionDataTask *)POST:(NSString *)URLString 101 | from:(nullable NSDictionary *)data 102 | progress:(nullable void (^)(NSProgress *progress))progress 103 | success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success 104 | failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure 105 | finish:(nullable void (^)(NSURLSessionDataTask * _Nullable task))finish; 106 | 107 | - (nullable NSURLSessionDataTask *)GET:(NSString *)URLString 108 | from:(nullable NSDictionary *)data 109 | progress:(nullable void (^)(NSProgress *progress))progress 110 | success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success 111 | failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure 112 | finish:(nullable void (^)(NSURLSessionDataTask * _Nullable task))finish; 113 | 114 | - (nullable NSURLSessionDataTask *)DELETE:(NSString *)URLString 115 | from:(nullable NSDictionary *)data 116 | success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success 117 | failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure 118 | finish:(nullable void (^)(NSURLSessionDataTask * _Nullable task))finish; 119 | ``` 120 | 121 | Use `PGNetworkHandler+PGCoreData.h` like `PGNetworkHandler.h` but with the ability to save retrieved data to Core Data directly. 122 | 123 | ```objc 124 | - (nullable NSURLSessionDataTask *)PUT:(NSString *)URLString 125 | from:(nullable NSDictionary *)data 126 | to:(NSManagedObjectContext *)context 127 | mapping:(PGMappingDescription *)mapping 128 | option:(PGSaveOption)option 129 | success:(nullable void (^)(NSURLSessionDataTask *task, NSArray *results))success 130 | failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure 131 | finish:(nullable void (^)(NSURLSessionDataTask * _Nullable task))finish; 132 | 133 | - (nullable NSURLSessionDataTask *)POST:(NSString *)URLString 134 | from:(nullable NSDictionary *)data 135 | to:(NSManagedObjectContext *)context 136 | mapping:(PGMappingDescription *)mapping 137 | option:(PGSaveOption)option 138 | progress:(nullable void (^)(NSProgress *progress))progress 139 | success:(nullable void (^)(NSURLSessionDataTask *task, NSArray *results))success 140 | failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure 141 | finish:(nullable void (^)(NSURLSessionDataTask * _Nullable task))finish; 142 | 143 | - (nullable NSURLSessionDataTask *)GET:(NSString *)URLString 144 | from:(nullable NSDictionary *)data 145 | to:(NSManagedObjectContext *)context 146 | mapping:(PGMappingDescription *)mapping 147 | option:(PGSaveOption)option 148 | progress:(nullable void (^)(NSProgress *progress))progress 149 | success:(nullable void (^)(NSURLSessionDataTask *task, NSArray *results))success 150 | failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure 151 | finish:(nullable void (^)(NSURLSessionDataTask * _Nullable task))finish; 152 | 153 | - (nullable NSURLSessionDataTask *)DELETE:(NSString *)URLString 154 | from:(nullable NSDictionary *)data 155 | to:(NSManagedObjectContext *)context 156 | mapping:(PGMappingDescription *)mapping 157 | option:(PGSaveOption)option 158 | success:(nullable void (^)(NSURLSessionDataTask *task, NSArray *results))success 159 | failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure 160 | finish:(nullable void (^)(NSURLSessionDataTask * _Nullable task))finish; 161 | ``` 162 | 163 | Use `PGNetworkHandler+PGData.h` to generate a `NSDictionary` base on your `NSManagedObject` and use it as the request parameter (`from` key in the above APIs). 164 | 165 | ```objc 166 | - (NSMutableDictionary *)dataFromObject:(nullable id)object mapping:(PGMappingDescription *)mapping; 167 | ``` 168 | 169 | Use the underlying `NSManagedObjectContext+PGMapping.h` to save arbitrary `NSDictionary` objects to your Core Data database. 170 | 171 | ```objc 172 | - (id)save:(nullable NSDictionary *)data description:(PGMappingDescription *)mapping error:(NSError **)error; 173 | 174 | - (id)save:(nullable NSDictionary *)data to:(id)object description:(PGMappingDescription *)mapping error:(NSError **)error; 175 | ``` 176 | 177 | ## Credits 178 | 179 | PGMappingKit is owned by [Plot Guru](http://www.plotguru.com). 180 | 181 | PGMappingKit was originally created by [Justin Jia](https://github.com/justinjiadev/) in the development of [Plot Guru for iOS](https://itunes.apple.com/app/id964629606). 182 | 183 | ## Licensing 184 | 185 | PGMappingKit is released under the MIT license. See LICENSE for details. 186 | --------------------------------------------------------------------------------