├── .gitignore ├── .travis.yml ├── LICENSE.txt ├── ObjcAssociatedObjectHelpers.podspec ├── ObjcAssociatedObjectHelpers.xcodeproj ├── project.pbxproj └── xcshareddata │ └── xcschemes │ ├── ObjcAssociatedObjectHelpers.xcscheme │ ├── ObjcAssociatedObjectHelpersLib.xcscheme │ ├── ObjcAssociatedObjectHelpersLibTests.xcscheme │ └── ObjcAssociatedObjectHelpersTests.xcscheme ├── ObjcAssociatedObjectHelpers.xcworkspace ├── contents.xcworkspacedata └── xcshareddata │ └── ObjcAssociatedObjectHelpers.xccheckout ├── ObjcAssociatedObjectHelpers ├── NSObject+AssociatedDictionary.h ├── NSObject+AssociatedDictionary.m ├── ObjcAssociatedObjectHelpers-Info.plist ├── ObjcAssociatedObjectHelpers.h └── ObjcAssociatedObjectHelpers.m ├── Podfile ├── Podfile.lock ├── README.md └── UnitTests ├── Specs.m ├── TestClass.h ├── TestClass.m └── WeakContainer.m /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | build/* 3 | *.pbxuser 4 | !default.pbxuser 5 | *.mode1v3 6 | !default.mode1v3 7 | *.mode2v3 8 | !default.mode2v3 9 | *.perspectivev3 10 | !default.perspectivev3 11 | xcuserdata 12 | profile 13 | *.moved-aside 14 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | 3 | xcode_workspace: ObjcAssociatedObjectHelpers.xcworkspace 4 | xcode_scheme: ObjcAssociatedObjectHelpersLib 5 | 6 | before_install: 7 | - brew unlink xctool 8 | - brew install xctool --HEAD 9 | - export LC_ALL="en_US.UTF-8" 10 | - gem install cocoapods 11 | 12 | script: xctool -workspace ObjcAssociatedObjectHelpers.xcworkspace -scheme ObjcAssociatedObjectHelpers test 13 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright © 2013 Jonathan Crooke 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 5 | associated documentation files (the “Software”), to deal in the Software without restriction, including 6 | without limitation the rights 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 furnished to do so, subject 8 | to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all copies or substantial 11 | 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 | -------------------------------------------------------------------------------- /ObjcAssociatedObjectHelpers.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "ObjcAssociatedObjectHelpers" 3 | s.version = "2.0.1" 4 | s.summary = "Make working with associated objects much more pleasurable." 5 | s.description = "A header file with macros that synthesize accessors for 6 | associated objects, taking the boilerplate out of your hands. Also, a category 7 | that adds an NSMutableDictionary to NSObject to make adding abitrary key/values 8 | a breeze." 9 | s.homepage = "https://github.com/itsthejb/ObjcAssociatedObjectHelpers" 10 | s.license = { :type => 'MIT', :file => 'LICENSE.txt' } 11 | s.author = { "Jonathan Crooke" => "joncrooke@gmail.com" } 12 | s.source = { :git => "https://github.com/itsthejb/ObjcAssociatedObjectHelpers.git", :tag => "v#{s.version.to_s}" } 13 | s.ios.deployment_target = '5.0' 14 | s.osx.deployment_target = '10.7' 15 | s.frameworks = 'Foundation' 16 | s.requires_arc = true 17 | 18 | s.subspec 'Core' do |c| 19 | c.source_files = 'ObjcAssociatedObjectHelpers/ObjcAssociatedObjectHelpers.{h,m}' 20 | end 21 | 22 | s.subspec 'NSObject+Dictionary' do |d| 23 | d.source_files = 'ObjcAssociatedObjectHelpers/NSObject+AssociatedDictionary.{h,m}' 24 | d.dependency 'ObjcAssociatedObjectHelpers/Core' 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /ObjcAssociatedObjectHelpers.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1B75995371FA4BF5AF00B6D6 /* libPods-ObjcAssociatedObjectHelpersTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 510A0A5EEF4A43AEB1DFC61C /* libPods-ObjcAssociatedObjectHelpersTests.a */; }; 11 | 4918B9B2168498F000D4EAC4 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 49AEF0F61619F565009D9F9B /* Foundation.framework */; }; 12 | 4918B9C11684991B00D4EAC4 /* NSObject+AssociatedDictionary.m in Sources */ = {isa = PBXBuildFile; fileRef = 499C34B1161AF68000BA2AC9 /* NSObject+AssociatedDictionary.m */; }; 13 | 4959D45B1A9F5FF300F414FB /* WeakContainer.m in Sources */ = {isa = PBXBuildFile; fileRef = 49629DD21A9F5EE600BA8910 /* WeakContainer.m */; }; 14 | 495C4D151A59CDDC0039DB95 /* ObjcAssociatedObjectHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = 499E28471A586A68004174F2 /* ObjcAssociatedObjectHelpers.m */; }; 15 | 495C4D161A59D0CE0039DB95 /* ObjcAssociatedObjectHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = 499E28471A586A68004174F2 /* ObjcAssociatedObjectHelpers.m */; }; 16 | 495C4D171A59D0CF0039DB95 /* ObjcAssociatedObjectHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = 499E28471A586A68004174F2 /* ObjcAssociatedObjectHelpers.m */; }; 17 | 49629DD31A9F5EE600BA8910 /* WeakContainer.m in Sources */ = {isa = PBXBuildFile; fileRef = 49629DD21A9F5EE600BA8910 /* WeakContainer.m */; }; 18 | 499C34C7161AFD7200BA2AC9 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 49AEF0F61619F565009D9F9B /* Foundation.framework */; }; 19 | 499E28481A586A68004174F2 /* ObjcAssociatedObjectHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = 499E28471A586A68004174F2 /* ObjcAssociatedObjectHelpers.m */; }; 20 | 49AD1B5716C282A10061BDC1 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 49AEF0F61619F565009D9F9B /* Foundation.framework */; }; 21 | 49BC3AB818B61B7C00679CF8 /* TestClass.m in Sources */ = {isa = PBXBuildFile; fileRef = 49DEFFE918B6172E00E10224 /* TestClass.m */; }; 22 | 49BC3AB918B61B7D00679CF8 /* TestClass.m in Sources */ = {isa = PBXBuildFile; fileRef = 49DEFFE918B6172E00E10224 /* TestClass.m */; }; 23 | 49BF24A8161B0805000B1590 /* NSObject+AssociatedDictionary.m in Sources */ = {isa = PBXBuildFile; fileRef = 499C34B1161AF68000BA2AC9 /* NSObject+AssociatedDictionary.m */; }; 24 | 49DEFFE618B615BC00E10224 /* Specs.m in Sources */ = {isa = PBXBuildFile; fileRef = 49DEFFE518B615BC00E10224 /* Specs.m */; }; 25 | 49DEFFE718B615BC00E10224 /* Specs.m in Sources */ = {isa = PBXBuildFile; fileRef = 49DEFFE518B615BC00E10224 /* Specs.m */; }; 26 | F722B1E555F9485C84EEAD16 /* libPods-ObjcAssociatedObjectHelpersLibTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 933FFC6B1F1A4F19AA34B2F6 /* libPods-ObjcAssociatedObjectHelpersLibTests.a */; }; 27 | /* End PBXBuildFile section */ 28 | 29 | /* Begin PBXCopyFilesBuildPhase section */ 30 | 49AD1B5416C282A10061BDC1 /* CopyFiles */ = { 31 | isa = PBXCopyFilesBuildPhase; 32 | buildActionMask = 2147483647; 33 | dstPath = "include/${PRODUCT_NAME}"; 34 | dstSubfolderSpec = 16; 35 | files = ( 36 | ); 37 | runOnlyForDeploymentPostprocessing = 0; 38 | }; 39 | /* End PBXCopyFilesBuildPhase section */ 40 | 41 | /* Begin PBXFileReference section */ 42 | 0949349ACA81F7E6E831EC8A /* Pods-ObjcAssociatedObjectHelpersTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ObjcAssociatedObjectHelpersTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-ObjcAssociatedObjectHelpersTests/Pods-ObjcAssociatedObjectHelpersTests.release.xcconfig"; sourceTree = ""; }; 43 | 15F57830FA80C0B05DFFC53F /* Pods-ObjcAssociatedObjectHelpersLibTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ObjcAssociatedObjectHelpersLibTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-ObjcAssociatedObjectHelpersLibTests/Pods-ObjcAssociatedObjectHelpersLibTests.debug.xcconfig"; sourceTree = ""; }; 44 | 1CA662592899DE55A0584B20 /* Pods-ObjcAssociatedObjectHelpersLibTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ObjcAssociatedObjectHelpersLibTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-ObjcAssociatedObjectHelpersLibTests/Pods-ObjcAssociatedObjectHelpersLibTests.release.xcconfig"; sourceTree = ""; }; 45 | 4918B9AE168498F000D4EAC4 /* ObjcAssociatedObjectHelpersLibTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ObjcAssociatedObjectHelpersLibTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 46 | 49629DD21A9F5EE600BA8910 /* WeakContainer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WeakContainer.m; sourceTree = ""; }; 47 | 499C34B0161AF68000BA2AC9 /* NSObject+AssociatedDictionary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+AssociatedDictionary.h"; sourceTree = ""; }; 48 | 499C34B1161AF68000BA2AC9 /* NSObject+AssociatedDictionary.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+AssociatedDictionary.m"; sourceTree = ""; }; 49 | 499E28471A586A68004174F2 /* ObjcAssociatedObjectHelpers.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjcAssociatedObjectHelpers.m; sourceTree = ""; }; 50 | 49AD1B5616C282A10061BDC1 /* libObjcAssociatedObjectHelpersLib.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libObjcAssociatedObjectHelpersLib.a; sourceTree = BUILT_PRODUCTS_DIR; }; 51 | 49AD1B6716C2838C0061BDC1 /* ObjcAssociatedObjectHelpers.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ObjcAssociatedObjectHelpers.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 52 | 49AD1B7816C294A60061BDC1 /* LICENSE.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = LICENSE.txt; sourceTree = ""; }; 53 | 49AEF0F61619F565009D9F9B /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 54 | 49AEF10C1619F5E8009D9F9B /* ObjcAssociatedObjectHelpers.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ObjcAssociatedObjectHelpers.h; sourceTree = ""; }; 55 | 49AEF1591619FB2C009D9F9B /* ObjcAssociatedObjectHelpersTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ObjcAssociatedObjectHelpersTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 56 | 49BF24AA161B0903000B1590 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = text; path = README.md; sourceTree = ""; }; 57 | 49DEFFE318B603B200E10224 /* ObjcAssociatedObjectHelpers.podspec */ = {isa = PBXFileReference; lastKnownFileType = text; path = ObjcAssociatedObjectHelpers.podspec; sourceTree = ""; }; 58 | 49DEFFE418B603B200E10224 /* Podfile */ = {isa = PBXFileReference; lastKnownFileType = text; path = Podfile; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 59 | 49DEFFE518B615BC00E10224 /* Specs.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Specs.m; sourceTree = ""; }; 60 | 49DEFFE818B6172E00E10224 /* TestClass.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestClass.h; sourceTree = ""; }; 61 | 49DEFFE918B6172E00E10224 /* TestClass.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TestClass.m; sourceTree = ""; }; 62 | 510A0A5EEF4A43AEB1DFC61C /* libPods-ObjcAssociatedObjectHelpersTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-ObjcAssociatedObjectHelpersTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 63 | 933FFC6B1F1A4F19AA34B2F6 /* libPods-ObjcAssociatedObjectHelpersLibTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-ObjcAssociatedObjectHelpersLibTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 64 | B4E2F7B0969800D62492B95D /* Pods-ObjcAssociatedObjectHelpersTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ObjcAssociatedObjectHelpersTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-ObjcAssociatedObjectHelpersTests/Pods-ObjcAssociatedObjectHelpersTests.debug.xcconfig"; sourceTree = ""; }; 65 | /* End PBXFileReference section */ 66 | 67 | /* Begin PBXFrameworksBuildPhase section */ 68 | 4918B9AA168498F000D4EAC4 /* Frameworks */ = { 69 | isa = PBXFrameworksBuildPhase; 70 | buildActionMask = 2147483647; 71 | files = ( 72 | 4918B9B2168498F000D4EAC4 /* Foundation.framework in Frameworks */, 73 | F722B1E555F9485C84EEAD16 /* libPods-ObjcAssociatedObjectHelpersLibTests.a in Frameworks */, 74 | ); 75 | runOnlyForDeploymentPostprocessing = 0; 76 | }; 77 | 49AD1B5316C282A10061BDC1 /* Frameworks */ = { 78 | isa = PBXFrameworksBuildPhase; 79 | buildActionMask = 2147483647; 80 | files = ( 81 | 49AD1B5716C282A10061BDC1 /* Foundation.framework in Frameworks */, 82 | ); 83 | runOnlyForDeploymentPostprocessing = 0; 84 | }; 85 | 49AD1B6316C2838C0061BDC1 /* Frameworks */ = { 86 | isa = PBXFrameworksBuildPhase; 87 | buildActionMask = 2147483647; 88 | files = ( 89 | ); 90 | runOnlyForDeploymentPostprocessing = 0; 91 | }; 92 | 49AEF1551619FB2C009D9F9B /* Frameworks */ = { 93 | isa = PBXFrameworksBuildPhase; 94 | buildActionMask = 2147483647; 95 | files = ( 96 | 499C34C7161AFD7200BA2AC9 /* Foundation.framework in Frameworks */, 97 | 1B75995371FA4BF5AF00B6D6 /* libPods-ObjcAssociatedObjectHelpersTests.a in Frameworks */, 98 | ); 99 | runOnlyForDeploymentPostprocessing = 0; 100 | }; 101 | /* End PBXFrameworksBuildPhase section */ 102 | 103 | /* Begin PBXGroup section */ 104 | 49AEF0E71619F565009D9F9B = { 105 | isa = PBXGroup; 106 | children = ( 107 | 49AEF0F81619F565009D9F9B /* ObjcAssociatedObjectHelpers */, 108 | 49AEF1621619FB2C009D9F9B /* UnitTests */, 109 | 49AEF0F51619F565009D9F9B /* Frameworks */, 110 | 49AEF0F31619F565009D9F9B /* Products */, 111 | 762678B28CE1E38EC7D36C67 /* Pods */, 112 | 49DEFFE318B603B200E10224 /* ObjcAssociatedObjectHelpers.podspec */, 113 | 49BF24AA161B0903000B1590 /* README.md */, 114 | 49AD1B7816C294A60061BDC1 /* LICENSE.txt */, 115 | ); 116 | sourceTree = ""; 117 | }; 118 | 49AEF0F31619F565009D9F9B /* Products */ = { 119 | isa = PBXGroup; 120 | children = ( 121 | 49AEF1591619FB2C009D9F9B /* ObjcAssociatedObjectHelpersTests.xctest */, 122 | 4918B9AE168498F000D4EAC4 /* ObjcAssociatedObjectHelpersLibTests.xctest */, 123 | 49AD1B5616C282A10061BDC1 /* libObjcAssociatedObjectHelpersLib.a */, 124 | 49AD1B6716C2838C0061BDC1 /* ObjcAssociatedObjectHelpers.framework */, 125 | ); 126 | name = Products; 127 | sourceTree = ""; 128 | }; 129 | 49AEF0F51619F565009D9F9B /* Frameworks */ = { 130 | isa = PBXGroup; 131 | children = ( 132 | 49AEF0F61619F565009D9F9B /* Foundation.framework */, 133 | 933FFC6B1F1A4F19AA34B2F6 /* libPods-ObjcAssociatedObjectHelpersLibTests.a */, 134 | 510A0A5EEF4A43AEB1DFC61C /* libPods-ObjcAssociatedObjectHelpersTests.a */, 135 | ); 136 | name = Frameworks; 137 | sourceTree = ""; 138 | }; 139 | 49AEF0F81619F565009D9F9B /* ObjcAssociatedObjectHelpers */ = { 140 | isa = PBXGroup; 141 | children = ( 142 | 49AEF10C1619F5E8009D9F9B /* ObjcAssociatedObjectHelpers.h */, 143 | 499E28471A586A68004174F2 /* ObjcAssociatedObjectHelpers.m */, 144 | 499C34B0161AF68000BA2AC9 /* NSObject+AssociatedDictionary.h */, 145 | 499C34B1161AF68000BA2AC9 /* NSObject+AssociatedDictionary.m */, 146 | ); 147 | path = ObjcAssociatedObjectHelpers; 148 | sourceTree = ""; 149 | }; 150 | 49AEF1621619FB2C009D9F9B /* UnitTests */ = { 151 | isa = PBXGroup; 152 | children = ( 153 | 49DEFFE518B615BC00E10224 /* Specs.m */, 154 | 49629DD21A9F5EE600BA8910 /* WeakContainer.m */, 155 | 49DEFFE818B6172E00E10224 /* TestClass.h */, 156 | 49DEFFE918B6172E00E10224 /* TestClass.m */, 157 | ); 158 | path = UnitTests; 159 | sourceTree = ""; 160 | }; 161 | 762678B28CE1E38EC7D36C67 /* Pods */ = { 162 | isa = PBXGroup; 163 | children = ( 164 | 49DEFFE418B603B200E10224 /* Podfile */, 165 | 15F57830FA80C0B05DFFC53F /* Pods-ObjcAssociatedObjectHelpersLibTests.debug.xcconfig */, 166 | 1CA662592899DE55A0584B20 /* Pods-ObjcAssociatedObjectHelpersLibTests.release.xcconfig */, 167 | B4E2F7B0969800D62492B95D /* Pods-ObjcAssociatedObjectHelpersTests.debug.xcconfig */, 168 | 0949349ACA81F7E6E831EC8A /* Pods-ObjcAssociatedObjectHelpersTests.release.xcconfig */, 169 | ); 170 | name = Pods; 171 | sourceTree = ""; 172 | }; 173 | /* End PBXGroup section */ 174 | 175 | /* Begin PBXHeadersBuildPhase section */ 176 | 49AD1B6416C2838C0061BDC1 /* Headers */ = { 177 | isa = PBXHeadersBuildPhase; 178 | buildActionMask = 2147483647; 179 | files = ( 180 | ); 181 | runOnlyForDeploymentPostprocessing = 0; 182 | }; 183 | /* End PBXHeadersBuildPhase section */ 184 | 185 | /* Begin PBXNativeTarget section */ 186 | 4918B9AD168498F000D4EAC4 /* ObjcAssociatedObjectHelpersLibTests */ = { 187 | isa = PBXNativeTarget; 188 | buildConfigurationList = 4918B9BF168498F000D4EAC4 /* Build configuration list for PBXNativeTarget "ObjcAssociatedObjectHelpersLibTests" */; 189 | buildPhases = ( 190 | FD8A5C19211C488095781D47 /* Check Pods Manifest.lock */, 191 | 4918B9A9168498F000D4EAC4 /* Sources */, 192 | 4918B9AA168498F000D4EAC4 /* Frameworks */, 193 | 4918B9AB168498F000D4EAC4 /* Resources */, 194 | 611607D142E84A119575E1B3 /* Copy Pods Resources */, 195 | 4918B9AC168498F000D4EAC4 /* ShellScript */, 196 | ); 197 | buildRules = ( 198 | ); 199 | dependencies = ( 200 | ); 201 | name = ObjcAssociatedObjectHelpersLibTests; 202 | productName = ObjcAssociatedObjectHelpersTestsiOS; 203 | productReference = 4918B9AE168498F000D4EAC4 /* ObjcAssociatedObjectHelpersLibTests.xctest */; 204 | productType = "com.apple.product-type.bundle.unit-test"; 205 | }; 206 | 49AD1B5516C282A10061BDC1 /* ObjcAssociatedObjectHelpersLib */ = { 207 | isa = PBXNativeTarget; 208 | buildConfigurationList = 49AD1B6116C282A10061BDC1 /* Build configuration list for PBXNativeTarget "ObjcAssociatedObjectHelpersLib" */; 209 | buildPhases = ( 210 | 49AD1B5216C282A10061BDC1 /* Sources */, 211 | 49AD1B5316C282A10061BDC1 /* Frameworks */, 212 | 49AD1B5416C282A10061BDC1 /* CopyFiles */, 213 | ); 214 | buildRules = ( 215 | ); 216 | dependencies = ( 217 | ); 218 | name = ObjcAssociatedObjectHelpersLib; 219 | productName = ObjcAssociatedObjectHelpers; 220 | productReference = 49AD1B5616C282A10061BDC1 /* libObjcAssociatedObjectHelpersLib.a */; 221 | productType = "com.apple.product-type.library.static"; 222 | }; 223 | 49AD1B6616C2838C0061BDC1 /* ObjcAssociatedObjectHelpers */ = { 224 | isa = PBXNativeTarget; 225 | buildConfigurationList = 49AD1B7316C2838C0061BDC1 /* Build configuration list for PBXNativeTarget "ObjcAssociatedObjectHelpers" */; 226 | buildPhases = ( 227 | 49AD1B6216C2838C0061BDC1 /* Sources */, 228 | 49AD1B6316C2838C0061BDC1 /* Frameworks */, 229 | 49AD1B6416C2838C0061BDC1 /* Headers */, 230 | 49AD1B6516C2838C0061BDC1 /* Resources */, 231 | ); 232 | buildRules = ( 233 | ); 234 | dependencies = ( 235 | ); 236 | name = ObjcAssociatedObjectHelpers; 237 | productName = ObjcAssociatedObjectHelpers; 238 | productReference = 49AD1B6716C2838C0061BDC1 /* ObjcAssociatedObjectHelpers.framework */; 239 | productType = "com.apple.product-type.framework"; 240 | }; 241 | 49AEF1581619FB2C009D9F9B /* ObjcAssociatedObjectHelpersTests */ = { 242 | isa = PBXNativeTarget; 243 | buildConfigurationList = 49AEF16E1619FB2C009D9F9B /* Build configuration list for PBXNativeTarget "ObjcAssociatedObjectHelpersTests" */; 244 | buildPhases = ( 245 | E167EB9E514845CB9776CDC3 /* Check Pods Manifest.lock */, 246 | 49AEF1541619FB2C009D9F9B /* Sources */, 247 | 49AEF1551619FB2C009D9F9B /* Frameworks */, 248 | 49AEF1561619FB2C009D9F9B /* Resources */, 249 | 4CF42B5509C247958EE47C87 /* Copy Pods Resources */, 250 | 49AEF1571619FB2C009D9F9B /* ShellScript */, 251 | ); 252 | buildRules = ( 253 | ); 254 | dependencies = ( 255 | ); 256 | name = ObjcAssociatedObjectHelpersTests; 257 | productName = UnitTests; 258 | productReference = 49AEF1591619FB2C009D9F9B /* ObjcAssociatedObjectHelpersTests.xctest */; 259 | productType = "com.apple.product-type.bundle.unit-test"; 260 | }; 261 | /* End PBXNativeTarget section */ 262 | 263 | /* Begin PBXProject section */ 264 | 49AEF0E91619F565009D9F9B /* Project object */ = { 265 | isa = PBXProject; 266 | attributes = { 267 | LastTestingUpgradeCheck = 0510; 268 | LastUpgradeCheck = 0510; 269 | ORGANIZATIONNAME = jbsoft; 270 | }; 271 | buildConfigurationList = 49AEF0EC1619F565009D9F9B /* Build configuration list for PBXProject "ObjcAssociatedObjectHelpers" */; 272 | compatibilityVersion = "Xcode 3.2"; 273 | developmentRegion = English; 274 | hasScannedForEncodings = 0; 275 | knownRegions = ( 276 | en, 277 | ); 278 | mainGroup = 49AEF0E71619F565009D9F9B; 279 | productRefGroup = 49AEF0F31619F565009D9F9B /* Products */; 280 | projectDirPath = ""; 281 | projectRoot = ""; 282 | targets = ( 283 | 49AD1B5516C282A10061BDC1 /* ObjcAssociatedObjectHelpersLib */, 284 | 4918B9AD168498F000D4EAC4 /* ObjcAssociatedObjectHelpersLibTests */, 285 | 49AD1B6616C2838C0061BDC1 /* ObjcAssociatedObjectHelpers */, 286 | 49AEF1581619FB2C009D9F9B /* ObjcAssociatedObjectHelpersTests */, 287 | ); 288 | }; 289 | /* End PBXProject section */ 290 | 291 | /* Begin PBXResourcesBuildPhase section */ 292 | 4918B9AB168498F000D4EAC4 /* Resources */ = { 293 | isa = PBXResourcesBuildPhase; 294 | buildActionMask = 2147483647; 295 | files = ( 296 | ); 297 | runOnlyForDeploymentPostprocessing = 0; 298 | }; 299 | 49AD1B6516C2838C0061BDC1 /* Resources */ = { 300 | isa = PBXResourcesBuildPhase; 301 | buildActionMask = 2147483647; 302 | files = ( 303 | ); 304 | runOnlyForDeploymentPostprocessing = 0; 305 | }; 306 | 49AEF1561619FB2C009D9F9B /* Resources */ = { 307 | isa = PBXResourcesBuildPhase; 308 | buildActionMask = 2147483647; 309 | files = ( 310 | ); 311 | runOnlyForDeploymentPostprocessing = 0; 312 | }; 313 | /* End PBXResourcesBuildPhase section */ 314 | 315 | /* Begin PBXShellScriptBuildPhase section */ 316 | 4918B9AC168498F000D4EAC4 /* ShellScript */ = { 317 | isa = PBXShellScriptBuildPhase; 318 | buildActionMask = 2147483647; 319 | files = ( 320 | ); 321 | inputPaths = ( 322 | ); 323 | outputPaths = ( 324 | ); 325 | runOnlyForDeploymentPostprocessing = 0; 326 | shellPath = /bin/sh; 327 | shellScript = "# Run the unit tests in this test bundle.\n\"${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests\"\n"; 328 | }; 329 | 49AEF1571619FB2C009D9F9B /* ShellScript */ = { 330 | isa = PBXShellScriptBuildPhase; 331 | buildActionMask = 2147483647; 332 | files = ( 333 | ); 334 | inputPaths = ( 335 | ); 336 | outputPaths = ( 337 | ); 338 | runOnlyForDeploymentPostprocessing = 0; 339 | shellPath = /bin/sh; 340 | shellScript = "# Run the unit tests in this test bundle.\n\"${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests\"\n"; 341 | }; 342 | 4CF42B5509C247958EE47C87 /* Copy Pods Resources */ = { 343 | isa = PBXShellScriptBuildPhase; 344 | buildActionMask = 2147483647; 345 | files = ( 346 | ); 347 | inputPaths = ( 348 | ); 349 | name = "Copy Pods Resources"; 350 | outputPaths = ( 351 | ); 352 | runOnlyForDeploymentPostprocessing = 0; 353 | shellPath = /bin/sh; 354 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-ObjcAssociatedObjectHelpersTests/Pods-ObjcAssociatedObjectHelpersTests-resources.sh\"\n"; 355 | showEnvVarsInLog = 0; 356 | }; 357 | 611607D142E84A119575E1B3 /* Copy Pods Resources */ = { 358 | isa = PBXShellScriptBuildPhase; 359 | buildActionMask = 2147483647; 360 | files = ( 361 | ); 362 | inputPaths = ( 363 | ); 364 | name = "Copy Pods Resources"; 365 | outputPaths = ( 366 | ); 367 | runOnlyForDeploymentPostprocessing = 0; 368 | shellPath = /bin/sh; 369 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-ObjcAssociatedObjectHelpersLibTests/Pods-ObjcAssociatedObjectHelpersLibTests-resources.sh\"\n"; 370 | showEnvVarsInLog = 0; 371 | }; 372 | E167EB9E514845CB9776CDC3 /* Check Pods Manifest.lock */ = { 373 | isa = PBXShellScriptBuildPhase; 374 | buildActionMask = 2147483647; 375 | files = ( 376 | ); 377 | inputPaths = ( 378 | ); 379 | name = "Check Pods Manifest.lock"; 380 | outputPaths = ( 381 | ); 382 | runOnlyForDeploymentPostprocessing = 0; 383 | shellPath = /bin/sh; 384 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; 385 | showEnvVarsInLog = 0; 386 | }; 387 | FD8A5C19211C488095781D47 /* Check Pods Manifest.lock */ = { 388 | isa = PBXShellScriptBuildPhase; 389 | buildActionMask = 2147483647; 390 | files = ( 391 | ); 392 | inputPaths = ( 393 | ); 394 | name = "Check Pods Manifest.lock"; 395 | outputPaths = ( 396 | ); 397 | runOnlyForDeploymentPostprocessing = 0; 398 | shellPath = /bin/sh; 399 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; 400 | showEnvVarsInLog = 0; 401 | }; 402 | /* End PBXShellScriptBuildPhase section */ 403 | 404 | /* Begin PBXSourcesBuildPhase section */ 405 | 4918B9A9168498F000D4EAC4 /* Sources */ = { 406 | isa = PBXSourcesBuildPhase; 407 | buildActionMask = 2147483647; 408 | files = ( 409 | 495C4D161A59D0CE0039DB95 /* ObjcAssociatedObjectHelpers.m in Sources */, 410 | 49BC3AB818B61B7C00679CF8 /* TestClass.m in Sources */, 411 | 49629DD31A9F5EE600BA8910 /* WeakContainer.m in Sources */, 412 | 49DEFFE618B615BC00E10224 /* Specs.m in Sources */, 413 | 4918B9C11684991B00D4EAC4 /* NSObject+AssociatedDictionary.m in Sources */, 414 | ); 415 | runOnlyForDeploymentPostprocessing = 0; 416 | }; 417 | 49AD1B5216C282A10061BDC1 /* Sources */ = { 418 | isa = PBXSourcesBuildPhase; 419 | buildActionMask = 2147483647; 420 | files = ( 421 | 495C4D151A59CDDC0039DB95 /* ObjcAssociatedObjectHelpers.m in Sources */, 422 | ); 423 | runOnlyForDeploymentPostprocessing = 0; 424 | }; 425 | 49AD1B6216C2838C0061BDC1 /* Sources */ = { 426 | isa = PBXSourcesBuildPhase; 427 | buildActionMask = 2147483647; 428 | files = ( 429 | 499E28481A586A68004174F2 /* ObjcAssociatedObjectHelpers.m in Sources */, 430 | ); 431 | runOnlyForDeploymentPostprocessing = 0; 432 | }; 433 | 49AEF1541619FB2C009D9F9B /* Sources */ = { 434 | isa = PBXSourcesBuildPhase; 435 | buildActionMask = 2147483647; 436 | files = ( 437 | 495C4D171A59D0CF0039DB95 /* ObjcAssociatedObjectHelpers.m in Sources */, 438 | 49BC3AB918B61B7D00679CF8 /* TestClass.m in Sources */, 439 | 4959D45B1A9F5FF300F414FB /* WeakContainer.m in Sources */, 440 | 49DEFFE718B615BC00E10224 /* Specs.m in Sources */, 441 | 49BF24A8161B0805000B1590 /* NSObject+AssociatedDictionary.m in Sources */, 442 | ); 443 | runOnlyForDeploymentPostprocessing = 0; 444 | }; 445 | /* End PBXSourcesBuildPhase section */ 446 | 447 | /* Begin XCBuildConfiguration section */ 448 | 4918B9BD168498F000D4EAC4 /* Debug */ = { 449 | isa = XCBuildConfiguration; 450 | baseConfigurationReference = 15F57830FA80C0B05DFFC53F /* Pods-ObjcAssociatedObjectHelpersLibTests.debug.xcconfig */; 451 | buildSettings = { 452 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 453 | IPHONEOS_DEPLOYMENT_TARGET = 5.0; 454 | ONLY_ACTIVE_ARCH = YES; 455 | PRODUCT_NAME = "$(TARGET_NAME)"; 456 | SDKROOT = iphoneos; 457 | WRAPPER_EXTENSION = xctest; 458 | }; 459 | name = Debug; 460 | }; 461 | 4918B9BE168498F000D4EAC4 /* Release */ = { 462 | isa = XCBuildConfiguration; 463 | baseConfigurationReference = 1CA662592899DE55A0584B20 /* Pods-ObjcAssociatedObjectHelpersLibTests.release.xcconfig */; 464 | buildSettings = { 465 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 466 | IPHONEOS_DEPLOYMENT_TARGET = 5.0; 467 | PRODUCT_NAME = "$(TARGET_NAME)"; 468 | SDKROOT = iphoneos; 469 | VALIDATE_PRODUCT = YES; 470 | WRAPPER_EXTENSION = xctest; 471 | }; 472 | name = Release; 473 | }; 474 | 49AD1B5F16C282A10061BDC1 /* Debug */ = { 475 | isa = XCBuildConfiguration; 476 | buildSettings = { 477 | CLANG_WARN_CONSTANT_CONVERSION = YES; 478 | CLANG_WARN_ENUM_CONVERSION = YES; 479 | CLANG_WARN_INT_CONVERSION = YES; 480 | DSTROOT = /tmp/ObjcAssociatedObjectHelpers.dst; 481 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 482 | ONLY_ACTIVE_ARCH = YES; 483 | PRODUCT_NAME = "$(TARGET_NAME)"; 484 | SDKROOT = iphoneos; 485 | SKIP_INSTALL = YES; 486 | }; 487 | name = Debug; 488 | }; 489 | 49AD1B6016C282A10061BDC1 /* Release */ = { 490 | isa = XCBuildConfiguration; 491 | buildSettings = { 492 | CLANG_WARN_CONSTANT_CONVERSION = YES; 493 | CLANG_WARN_ENUM_CONVERSION = YES; 494 | CLANG_WARN_INT_CONVERSION = YES; 495 | DSTROOT = /tmp/ObjcAssociatedObjectHelpers.dst; 496 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 497 | PRODUCT_NAME = "$(TARGET_NAME)"; 498 | SDKROOT = iphoneos; 499 | SKIP_INSTALL = YES; 500 | VALIDATE_PRODUCT = YES; 501 | }; 502 | name = Release; 503 | }; 504 | 49AD1B7416C2838C0061BDC1 /* Debug */ = { 505 | isa = XCBuildConfiguration; 506 | buildSettings = { 507 | CLANG_WARN_CONSTANT_CONVERSION = YES; 508 | CLANG_WARN_ENUM_CONVERSION = YES; 509 | CLANG_WARN_INT_CONVERSION = YES; 510 | COMBINE_HIDPI_IMAGES = YES; 511 | DYLIB_COMPATIBILITY_VERSION = 1; 512 | DYLIB_CURRENT_VERSION = 1; 513 | FRAMEWORK_VERSION = A; 514 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 515 | ONLY_ACTIVE_ARCH = YES; 516 | PRODUCT_NAME = "$(TARGET_NAME)"; 517 | SDKROOT = macosx; 518 | WRAPPER_EXTENSION = framework; 519 | }; 520 | name = Debug; 521 | }; 522 | 49AD1B7516C2838C0061BDC1 /* Release */ = { 523 | isa = XCBuildConfiguration; 524 | buildSettings = { 525 | CLANG_WARN_CONSTANT_CONVERSION = YES; 526 | CLANG_WARN_ENUM_CONVERSION = YES; 527 | CLANG_WARN_INT_CONVERSION = YES; 528 | COMBINE_HIDPI_IMAGES = YES; 529 | DYLIB_COMPATIBILITY_VERSION = 1; 530 | DYLIB_CURRENT_VERSION = 1; 531 | FRAMEWORK_VERSION = A; 532 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 533 | PRODUCT_NAME = "$(TARGET_NAME)"; 534 | SDKROOT = macosx; 535 | WRAPPER_EXTENSION = framework; 536 | }; 537 | name = Release; 538 | }; 539 | 49AEF0FF1619F565009D9F9B /* Debug */ = { 540 | isa = XCBuildConfiguration; 541 | buildSettings = { 542 | ALWAYS_SEARCH_USER_PATHS = NO; 543 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 544 | CLANG_CXX_LIBRARY = "libc++"; 545 | CLANG_ENABLE_OBJC_ARC = YES; 546 | CLANG_WARN_EMPTY_BODY = YES; 547 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 548 | COPY_PHASE_STRIP = NO; 549 | GCC_C_LANGUAGE_STANDARD = gnu99; 550 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 551 | GCC_GENERATE_TEST_COVERAGE_FILES = YES; 552 | GCC_OPTIMIZATION_LEVEL = 0; 553 | GCC_PREPROCESSOR_DEFINITIONS = ( 554 | "DEBUG=1", 555 | "$(inherited)", 556 | ); 557 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 558 | GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; 559 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 560 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; 561 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 562 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 563 | GCC_WARN_UNUSED_VARIABLE = YES; 564 | IPHONEOS_DEPLOYMENT_TARGET = 5.0; 565 | MACOSX_DEPLOYMENT_TARGET = 10.7; 566 | ONLY_ACTIVE_ARCH = YES; 567 | }; 568 | name = Debug; 569 | }; 570 | 49AEF1001619F565009D9F9B /* Release */ = { 571 | isa = XCBuildConfiguration; 572 | buildSettings = { 573 | ALWAYS_SEARCH_USER_PATHS = NO; 574 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 575 | CLANG_CXX_LIBRARY = "libc++"; 576 | CLANG_ENABLE_OBJC_ARC = YES; 577 | CLANG_WARN_EMPTY_BODY = YES; 578 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 579 | COPY_PHASE_STRIP = YES; 580 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 581 | GCC_C_LANGUAGE_STANDARD = gnu99; 582 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 583 | GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; 584 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 585 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; 586 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 587 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 588 | GCC_WARN_UNUSED_VARIABLE = YES; 589 | IPHONEOS_DEPLOYMENT_TARGET = 5.0; 590 | MACOSX_DEPLOYMENT_TARGET = 10.7; 591 | }; 592 | name = Release; 593 | }; 594 | 49AEF16C1619FB2C009D9F9B /* Debug */ = { 595 | isa = XCBuildConfiguration; 596 | baseConfigurationReference = B4E2F7B0969800D62492B95D /* Pods-ObjcAssociatedObjectHelpersTests.debug.xcconfig */; 597 | buildSettings = { 598 | COMBINE_HIDPI_IMAGES = YES; 599 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 600 | PRODUCT_NAME = "$(TARGET_NAME)"; 601 | SDKROOT = macosx; 602 | WRAPPER_EXTENSION = xctest; 603 | }; 604 | name = Debug; 605 | }; 606 | 49AEF16D1619FB2C009D9F9B /* Release */ = { 607 | isa = XCBuildConfiguration; 608 | baseConfigurationReference = 0949349ACA81F7E6E831EC8A /* Pods-ObjcAssociatedObjectHelpersTests.release.xcconfig */; 609 | buildSettings = { 610 | COMBINE_HIDPI_IMAGES = YES; 611 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 612 | PRODUCT_NAME = "$(TARGET_NAME)"; 613 | SDKROOT = macosx; 614 | WRAPPER_EXTENSION = xctest; 615 | }; 616 | name = Release; 617 | }; 618 | /* End XCBuildConfiguration section */ 619 | 620 | /* Begin XCConfigurationList section */ 621 | 4918B9BF168498F000D4EAC4 /* Build configuration list for PBXNativeTarget "ObjcAssociatedObjectHelpersLibTests" */ = { 622 | isa = XCConfigurationList; 623 | buildConfigurations = ( 624 | 4918B9BD168498F000D4EAC4 /* Debug */, 625 | 4918B9BE168498F000D4EAC4 /* Release */, 626 | ); 627 | defaultConfigurationIsVisible = 0; 628 | defaultConfigurationName = Release; 629 | }; 630 | 49AD1B6116C282A10061BDC1 /* Build configuration list for PBXNativeTarget "ObjcAssociatedObjectHelpersLib" */ = { 631 | isa = XCConfigurationList; 632 | buildConfigurations = ( 633 | 49AD1B5F16C282A10061BDC1 /* Debug */, 634 | 49AD1B6016C282A10061BDC1 /* Release */, 635 | ); 636 | defaultConfigurationIsVisible = 0; 637 | defaultConfigurationName = Release; 638 | }; 639 | 49AD1B7316C2838C0061BDC1 /* Build configuration list for PBXNativeTarget "ObjcAssociatedObjectHelpers" */ = { 640 | isa = XCConfigurationList; 641 | buildConfigurations = ( 642 | 49AD1B7416C2838C0061BDC1 /* Debug */, 643 | 49AD1B7516C2838C0061BDC1 /* Release */, 644 | ); 645 | defaultConfigurationIsVisible = 0; 646 | defaultConfigurationName = Release; 647 | }; 648 | 49AEF0EC1619F565009D9F9B /* Build configuration list for PBXProject "ObjcAssociatedObjectHelpers" */ = { 649 | isa = XCConfigurationList; 650 | buildConfigurations = ( 651 | 49AEF0FF1619F565009D9F9B /* Debug */, 652 | 49AEF1001619F565009D9F9B /* Release */, 653 | ); 654 | defaultConfigurationIsVisible = 0; 655 | defaultConfigurationName = Release; 656 | }; 657 | 49AEF16E1619FB2C009D9F9B /* Build configuration list for PBXNativeTarget "ObjcAssociatedObjectHelpersTests" */ = { 658 | isa = XCConfigurationList; 659 | buildConfigurations = ( 660 | 49AEF16C1619FB2C009D9F9B /* Debug */, 661 | 49AEF16D1619FB2C009D9F9B /* Release */, 662 | ); 663 | defaultConfigurationIsVisible = 0; 664 | defaultConfigurationName = Release; 665 | }; 666 | /* End XCConfigurationList section */ 667 | }; 668 | rootObject = 49AEF0E91619F565009D9F9B /* Project object */; 669 | } 670 | -------------------------------------------------------------------------------- /ObjcAssociatedObjectHelpers.xcodeproj/xcshareddata/xcschemes/ObjcAssociatedObjectHelpers.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 52 | 53 | 54 | 55 | 61 | 62 | 64 | 65 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /ObjcAssociatedObjectHelpers.xcodeproj/xcshareddata/xcschemes/ObjcAssociatedObjectHelpersLib.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 52 | 53 | 54 | 55 | 61 | 62 | 64 | 65 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /ObjcAssociatedObjectHelpers.xcodeproj/xcshareddata/xcschemes/ObjcAssociatedObjectHelpersLibTests.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 14 | 15 | 17 | 23 | 24 | 25 | 26 | 27 | 36 | 37 | 38 | 39 | 45 | 46 | 48 | 49 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /ObjcAssociatedObjectHelpers.xcodeproj/xcshareddata/xcschemes/ObjcAssociatedObjectHelpersTests.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 14 | 15 | 17 | 23 | 24 | 25 | 26 | 27 | 36 | 37 | 38 | 39 | 45 | 46 | 48 | 49 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /ObjcAssociatedObjectHelpers.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ObjcAssociatedObjectHelpers.xcworkspace/xcshareddata/ObjcAssociatedObjectHelpers.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | 3ADF255E-C2AF-46BC-8375-849F24369A81 9 | IDESourceControlProjectName 10 | ObjcAssociatedObjectHelpers 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | E442C8E0BC25456537E7E8CB9EB3893106F5AE72 14 | https://github.com/itsthejb/ObjcAssociatedObjectHelpers.git 15 | 16 | IDESourceControlProjectPath 17 | ObjcAssociatedObjectHelpers.xcworkspace 18 | IDESourceControlProjectRelativeInstallPathDictionary 19 | 20 | E442C8E0BC25456537E7E8CB9EB3893106F5AE72 21 | .. 22 | 23 | IDESourceControlProjectURL 24 | https://github.com/itsthejb/ObjcAssociatedObjectHelpers.git 25 | IDESourceControlProjectVersion 26 | 111 27 | IDESourceControlProjectWCCIdentifier 28 | E442C8E0BC25456537E7E8CB9EB3893106F5AE72 29 | IDESourceControlProjectWCConfigurations 30 | 31 | 32 | IDESourceControlRepositoryExtensionIdentifierKey 33 | public.vcs.git 34 | IDESourceControlWCCIdentifierKey 35 | E442C8E0BC25456537E7E8CB9EB3893106F5AE72 36 | IDESourceControlWCCName 37 | ObjcAssociatedObjectHelpers 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /ObjcAssociatedObjectHelpers/NSObject+AssociatedDictionary.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+AssociatedDictionary.h 3 | // ObjcAssociatedObjectHelpers 4 | // 5 | // Created by Jon Crooke on 02/10/2012. 6 | // Copyright (c) 2012 Jonathan Crooke. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | // SOFTWARE. 25 | 26 | #import 27 | 28 | /** 29 | * Category to add a lazily-instantiated `NSMutableDictionary` instance 30 | * to `NSObject`. 31 | */ 32 | @interface NSObject (AssociatedDictionary) 33 | /** 34 | * Lazily instantiated mutable dictionary 35 | */ 36 | @property (readonly) NSMutableDictionary *ascObj_dictionary; 37 | @end 38 | -------------------------------------------------------------------------------- /ObjcAssociatedObjectHelpers/NSObject+AssociatedDictionary.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+AssociatedDictionary.m 3 | // ObjcAssociatedObjectHelpers 4 | // 5 | // Created by Jon Crooke on 02/10/2012. 6 | // Copyright (c) 2012 Jonathan Crooke. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | // SOFTWARE. 25 | 26 | #import "NSObject+AssociatedDictionary.h" 27 | #import "ObjcAssociatedObjectHelpers.h" 28 | 29 | @implementation NSObject (AssociatedDictionary) 30 | SYNTHESIZE_ASC_OBJ_LAZY(ascObj_dictionary, NSMutableDictionary); 31 | @end 32 | -------------------------------------------------------------------------------- /ObjcAssociatedObjectHelpers/ObjcAssociatedObjectHelpers-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | com.jc.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | FMWK 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | NSHumanReadableCopyright 26 | Copyright © 2013 jbsoft. All rights reserved. 27 | NSPrincipalClass 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /ObjcAssociatedObjectHelpers/ObjcAssociatedObjectHelpers.h: -------------------------------------------------------------------------------- 1 | // 2 | // ObjcAssociatedObjectHelpers.h 3 | // ObjcAssociatedObjectHelpers 4 | // 5 | // Created by Jon Crooke on 01/10/2012. 6 | // Copyright (c) 2012 Jonathan Crooke. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | // SOFTWARE. 25 | 26 | #import 27 | #import 28 | #import 29 | #import 30 | 31 | /** Platform minimum requirements (associated object availability) */ 32 | #if ( TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR ) && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_4_0 33 | #error Associated references available from iOS 4.0 34 | #elif TARGET_OS_MAC && !( TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR ) && __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_6 35 | #error Associated references available from OS X 10.6 36 | #endif 37 | 38 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 39 | #pragma mark Weak reference containers 40 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 41 | #if __has_feature(objc_arc) 42 | @interface __ObjCAscWeakContainer : NSObject 43 | + (instancetype)wrapObject:(id)object; 44 | @property (weak) id _object; 45 | @end 46 | #endif 47 | 48 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 49 | #pragma mark Quotation helper 50 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 51 | #define __OBJC_ASC_QUOTE(x) #x 52 | #define _OBJC_ASC_QUOTE(x) __OBJC_ASC_QUOTE(x) 53 | 54 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 55 | #pragma mark Dynamic perform selector helper 56 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 57 | #define _OBJC_ASC_CHECK_AND_PERFORM(selectorName, value) {\ 58 | SEL __checkSel = NSSelectorFromString(selectorName); \ 59 | if ([self respondsToSelector:__checkSel]) { \ 60 | _Pragma ("clang diagnostic push") \ 61 | _Pragma ("clang diagnostic ignored \"-Warc-performSelector-leaks\"") \ 62 | [self performSelector:__checkSel withObject: value]; \ 63 | _Pragma ("clang diagnostic pop") \ 64 | } \ 65 | } 66 | 67 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 68 | #pragma mark KVO helper 69 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 70 | #define _OBJC_ASC_WRAP_KVO_SETTER(getterName, expression) \ 71 | _OBJC_ASC_CHECK_AND_PERFORM(@"willChangeValueForKey:", @_OBJC_ASC_QUOTE(getterName)) \ 72 | expression; \ 73 | _OBJC_ASC_CHECK_AND_PERFORM(@"didChangeValueForKey:", @_OBJC_ASC_QUOTE(getterName)) 74 | 75 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 76 | #pragma mark Assign readwrite 77 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 78 | #define SYNTHESIZE_ASC_OBJ_ASSIGN(getterName, setterName) \ 79 | SYNTHESIZE_ASC_OBJ_ASSIGN_BLOCK(getterName, setterName, ^(id v){ return v; }, ^(id v){ return v; }) 80 | 81 | #define SYNTHESIZE_ASC_OBJ_ASSIGN_BLOCK(getterName, setterName, getterBlock, setterBlock) \ 82 | static void* getterName##Key = _OBJC_ASC_QUOTE(getterName); \ 83 | - (void)setterName:(id)value { \ 84 | value = setterBlock(value); \ 85 | objc_AssociationPolicy policy = OBJC_ASSOCIATION_ASSIGN; \ 86 | @synchronized(self) { \ 87 | _OBJC_ASC_WRAP_KVO_SETTER(getterName, objc_setAssociatedObject(self, getterName##Key, value, policy)); \ 88 | } \ 89 | } \ 90 | - (id) getterName { \ 91 | id value = nil; \ 92 | @synchronized(self) { \ 93 | value = objc_getAssociatedObject(self, getterName##Key); \ 94 | }; \ 95 | return getterBlock(value); \ 96 | } 97 | 98 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 99 | #pragma mark Readwrite Object 100 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 101 | #define SYNTHESIZE_ASC_OBJ(getterName, setterName) \ 102 | SYNTHESIZE_ASC_OBJ_BLOCK(getterName, setterName, ^(id v){ return v; }, ^(id v){ return v; }) 103 | 104 | #define SYNTHESIZE_ASC_OBJ_BLOCK(getterName, setterName, getterBlock, setterBlock) \ 105 | static void* getterName##Key = _OBJC_ASC_QUOTE(getterName); \ 106 | - (void)setterName:(id)value { \ 107 | value = setterBlock(value); \ 108 | objc_AssociationPolicy policy = \ 109 | [value conformsToProtocol:@protocol(NSCopying)] ? OBJC_ASSOCIATION_COPY : OBJC_ASSOCIATION_RETAIN; \ 110 | @synchronized(self) { \ 111 | _OBJC_ASC_WRAP_KVO_SETTER(getterName, objc_setAssociatedObject(self, getterName##Key, value, policy)); \ 112 | } \ 113 | } \ 114 | - (id) getterName { \ 115 | id value = nil; \ 116 | @synchronized(self) { \ 117 | value = objc_getAssociatedObject(self, getterName##Key); \ 118 | }; \ 119 | return getterBlock(value); \ 120 | } 121 | 122 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 123 | #pragma mark Readwrite Weak Object 124 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 125 | #if __has_feature(objc_arc) 126 | #define SYNTHESIZE_ASC_OBJ_WEAK(getterName, setterName) \ 127 | SYNTHESIZE_ASC_OBJ_WEAK_BLOCK(getterName, setterName, ^(id v){ return v; }, ^(id v){ return v; }) 128 | 129 | #define SYNTHESIZE_ASC_OBJ_WEAK_BLOCK(getterName, setterName, getterBlock, setterBlock) \ 130 | static void* getterName##Key = _OBJC_ASC_QUOTE(getterName); \ 131 | - (void)setterName:(id)value { \ 132 | id wrapped = [__ObjCAscWeakContainer wrapObject:setterBlock(value)]; \ 133 | @synchronized(self) { \ 134 | _OBJC_ASC_WRAP_KVO_SETTER(getterName, objc_setAssociatedObject(self, getterName##Key, wrapped, OBJC_ASSOCIATION_RETAIN)); \ 135 | } \ 136 | } \ 137 | - (id) getterName { \ 138 | __ObjCAscWeakContainer *wrapped = nil; \ 139 | @synchronized(self) { \ 140 | wrapped = objc_getAssociatedObject(self, getterName##Key); \ 141 | }; \ 142 | return getterBlock(wrapped._object); \ 143 | } 144 | #endif 145 | 146 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 147 | #pragma mark Lazy readonly object 148 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 149 | #define SYNTHESIZE_ASC_OBJ_LAZY_EXP(getterName, initExpression) \ 150 | SYNTHESIZE_ASC_OBJ_LAZY_EXP_BLOCK(getterName, initExpression, ^(id v){ return v; }) 151 | 152 | #define SYNTHESIZE_ASC_OBJ_LAZY_EXP_BLOCK(getterName, initExpression, block) \ 153 | static void* getterName##Key = _OBJC_ASC_QUOTE(getterName); \ 154 | - (id)getterName { \ 155 | id value = nil; \ 156 | @synchronized(self) { \ 157 | value = objc_getAssociatedObject(self, getterName##Key); \ 158 | if (!value) { \ 159 | value = initExpression; \ 160 | objc_setAssociatedObject(self, getterName##Key, value, OBJC_ASSOCIATION_RETAIN); \ 161 | } \ 162 | } \ 163 | value = block(value); \ 164 | return value; \ 165 | } 166 | 167 | // Use default initialiser 168 | #define SYNTHESIZE_ASC_OBJ_LAZY(getterName, class) \ 169 | SYNTHESIZE_ASC_OBJ_LAZY_EXP_BLOCK(getterName, [[class alloc] init], ^(id v){ return v; }) 170 | #define SYNTHESIZE_ASC_OBJ_LAZY_BLOCK(getterName, class, block) \ 171 | SYNTHESIZE_ASC_OBJ_LAZY_EXP_BLOCK(getterName, [[class alloc] init], block) 172 | 173 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 174 | #pragma mark Primitive 175 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 176 | #define SYNTHESIZE_ASC_PRIMITIVE(getterName, setterName, type) \ 177 | SYNTHESIZE_ASC_PRIMITIVE_BLOCK(getterName, setterName, type, ^(type v){ return v; }, ^(type v){ return v; }) 178 | 179 | #define SYNTHESIZE_ASC_PRIMITIVE_BLOCK(getterName, setterName, type, getterBlock, setterBlock) \ 180 | static void* getterName##Key = _OBJC_ASC_QUOTE(getterName); \ 181 | - (void)setterName:(type)value { \ 182 | value = setterBlock(value); \ 183 | @synchronized(self) { \ 184 | NSValue *nsValue = [NSValue value:&value withObjCType:@encode(type)]; \ 185 | _OBJC_ASC_WRAP_KVO_SETTER(getterName, objc_setAssociatedObject(self, getterName##Key, nsValue, OBJC_ASSOCIATION_RETAIN)); \ 186 | } \ 187 | } \ 188 | - (type) getterName { \ 189 | type value; \ 190 | memset(&value, 0, sizeof(type)); \ 191 | @synchronized(self) { \ 192 | [objc_getAssociatedObject(self, getterName##Key) getValue:&value]; \ 193 | } \ 194 | return getterBlock(value); \ 195 | } 196 | -------------------------------------------------------------------------------- /ObjcAssociatedObjectHelpers/ObjcAssociatedObjectHelpers.m: -------------------------------------------------------------------------------- 1 | // 2 | // ObjcAssociatedObjectHelpers.m 3 | // ObjcAssociatedObjectHelpers 4 | // 5 | // Created by Jon Crooke on 01/10/2012. 6 | // Copyright (c) 2012 Jonathan Crooke. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | // SOFTWARE. 25 | 26 | #import "ObjcAssociatedObjectHelpers.h" 27 | 28 | #if __has_feature(objc_arc) 29 | @implementation __ObjCAscWeakContainer 30 | + (instancetype)wrapObject:(id)object { 31 | __ObjCAscWeakContainer *wrapper = [[self alloc] init]; 32 | wrapper._object = object; 33 | return wrapper; 34 | } 35 | @end 36 | #endif 37 | -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | target :ObjcAssociatedObjectHelpers, :exclusive => true do 2 | end 3 | 4 | def test_pods 5 | pod 'ReactiveCocoa', '2.2.3' 6 | pod 'Expecta', :head 7 | pod 'Specta', :head 8 | end 9 | 10 | target :ObjcAssociatedObjectHelpersTests, :exclusive => true do 11 | platform :osx, '10.7' 12 | test_pods 13 | end 14 | 15 | target :ObjcAssociatedObjectHelpersLibTests, :exclusive => true do 16 | platform :ios, '5.1.1' 17 | test_pods 18 | end 19 | 20 | inhibit_all_warnings! 21 | -------------------------------------------------------------------------------- /Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Expecta (HEAD based on 0.3.2) 3 | - ReactiveCocoa (2.2.3): 4 | - ReactiveCocoa/Core (= 2.2.3) 5 | - ReactiveCocoa/no-arc (= 2.2.3) 6 | - ReactiveCocoa/Core (2.2.3): 7 | - ReactiveCocoa/no-arc 8 | - ReactiveCocoa/no-arc (2.2.3) 9 | - Specta (HEAD based on 0.3.2) 10 | 11 | DEPENDENCIES: 12 | - Expecta (HEAD) 13 | - ReactiveCocoa (= 2.2.3) 14 | - Specta (HEAD) 15 | 16 | SPEC CHECKSUMS: 17 | Expecta: ee641011fe10aa1855d487b40e4976dac50ec342 18 | ReactiveCocoa: b751b6d1df73688da1040a3cd5b068765ec118d4 19 | Specta: 698a58ffa5ec948327d3b92eab50ca58d7f4fbe8 20 | 21 | COCOAPODS: 0.35.0 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Master Status](https://travis-ci.org/itsthejb/ObjcAssociatedObjectHelpers.png?branch=master)](https://travis-ci.org/itsthejb/ObjcAssociatedObjectHelpers) 2 | [![Develop Status](https://travis-ci.org/itsthejb/ObjcAssociatedObjectHelpers.png?branch=develop)](https://travis-ci.org/itsthejb/ObjcAssociatedObjectHelpers) 3 | [![Pod Status](https://img.shields.io/cocoapods/v/ObjcAssociatedObjectHelpers.svg)](http://www.cocoapods.org/?q=ObjcAssociatedObjectHelpers) 4 | [![Pod License](https://img.shields.io/cocoapods/l/ObjcAssociatedObjectHelpers.svg)](http://www.cocoapods.org/?q=ObjcAssociatedObjectHelpers) 5 | [![Pod Platform](https://img.shields.io/cocoapods/p/ObjcAssociatedObjectHelpers.svg)](http://www.cocoapods.org/?q=ObjcAssociatedObjectHelpers) 6 | 7 | ObjcAssociatedObjectHelpers 8 | =========================== 9 | 10 | Introduction 11 | ------------ 12 | 13 | [Associated Objects, or Associated References](http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/objectivec/Chapters/ocAssociativeReferences.html) were introduced in OS X 10.6 and iOS 4.0. This feature gives class instances a dictionary of sorts within which to store arbitrary objects using the runtime functions `objc_setAssociatedObject()` and `objc_getAssociatedObject()`. This project aims to make their use more convenient in a light-weight and thoroughly tested fashion. 14 | 15 | 1. **Adding ivars to categories** - An unfortunate drawback of Obj-C categories in the inability to add or synthesize ivars, even though properties can be added. Associated objects can be used to provide storage and overcome this limitation: 16 | 17 | @interface NSObject (MyCategory) 18 | @property (strong) id myCategoryObject; 19 | @end 20 | 21 | @implementation NSObject (MyCategory) 22 | SYNTHESIZE_ASC_OBJ(myCategoryObject, setMyCategoryObject); 23 | @end 24 | 25 | 2. **Arbitrary dictionary for NSObject** - The `NSObject` category adds a lazily-initialized `NSMutableDictionary` to `NSObject`, allowing key-value pairs to be more conveniently associated with any `NSObject` subclass instance: 26 | 27 | [self.associatedDictionary setValue:@"value" forKey:@"myKey"]; 28 | 29 | Notes 30 | ----- 31 | 1. **getter / setter names** - There is no way to manipulate strings in the preprocessor so that standard getter and setter names can easily be generated from a single token. As such, the read/write macros require both names to be provided manually. 32 | 2. **Memory Management** - Works identically under ARC and manually reference counted code. 33 | 3. **Property memory management semantics** - Since properties use associated objects for storage, any property setter semantics can be used: 34 | 35 | @property () id myProperty; 36 | @property (strong) id myProperty; 37 | @property (retain) id myProperty; 38 | @property (assign) id myProperty; 39 | @property (copy) id myProperty; 40 | 41 | Currently, the macros check at runtime for `NSCopying` protocol compliance and use `OBJC_ASSOCIATION_COPY` if found and `OBJC_ASSOCIATION_RETAIN` otherwise. The test `-[UnitTests testMutableObject]` confirms that a copy is made. I think this is The Right Way™. It's probably best to use normal semantics with these setters, however. 42 | 43 | 4. As of version `2.0.0` weak properties are supported, and behave in the same way as regular `weak` properties. 44 | 45 | Usage 46 | ----- 47 | Static library provided for the `NSObject` category, or just use the header file for basic usage. Prefered installation by using [CocoaPods](http://cocoapods.org/). 48 | 49 | pod 'ObjcAssociatedObjectHelpers' 50 | 51 | Testing 52 | ------- 53 | Thorough test cases provided with near 100% coverage. 54 | 55 | 56 | Macros 57 | ------ 58 | 1. `SYNTHESIZE_ASC_OBJ(getterName, setterName)` - The most basic usage. Synthesize a getter and setter for a read/write object property. If you would like to generate a read-only property with a private or protected setter then you can define this in another category: 59 | 60 | @interface MyClass : NSObject 61 | @property (readonly) id readWriteObject; 62 | @end 63 | 64 | @interface MyClass (PrivateOrProtectedOrAnonymous) 65 | @property (readwrite) id readWriteObject; 66 | @end 67 | 68 | @implementaton MyClass 69 | 70 | - (id) init { 71 | if ((self = [super init])) { 72 | self.readWriteObject = @"foo"; 73 | } 74 | return self; 75 | } 76 | 77 | 2. `SYNTHESIZE_ASC_PRIMITIVE(getterName, setterName, type)` - Synthesize for any kind of primitive object. Any type supported by the `@encode()` operator is supported. So that *should* be everything…? 78 | 3. `SYNTHESIZE_ASC_OBJ_LAZY(getterName, class)` - Synthesize a read-only object that in initialized lazily. The object's class must be provided so that an object can be initialized (with `alloc/init`) on first access. 79 | 4. `SYNTHESIZE_ASC_OBJ_LAZY_EXP(getterName, initExpression)` - Synthesize a read-only object that in initialized lazily, with the provided initialiser Expression. For example; 80 | 81 | SYNTHESIZE_ASC_OBJ_LAZY_EXP(nonDefaultLazyObject, [NSString stringWithFormat:@"foo"]) 82 | Uses the expression `[NSString stringWithFormat:@"foo"]` to initialise the object. Note that `SYNTHESIZE_ASC_OBJ_LAZY` uses this macro with `[[class alloc] init]`. 83 | 5. All the macros have a `_BLOCK` suffix companion which (to borrow generic programming syntax) takes a block of type `T (^block)(T value)` for the getter, and setter (if available). This allows additional code to be run in the accessors, similar to overriding an accessor. The value passed to the accessor will be the argument. This value can be returned, or a modified value can also be returned. This replaces the syntax used until `v1.2.1`, and I think is clearer. For example: 84 | 85 | SYNTHESIZE_ASC_PRIMITIVE_BLOCK(myProperty, 86 | setMyProperty, 87 | CGSize, 88 | ^(CGSize s){ return CGSizeZero; }, 89 | ^(CGSize s){ s.width = 10; return s; }) 90 | 91 | Defines a read/write property of type `CGSize`, and overrides the getter and setter to always set `CGSizeZero`, and always get a size with a width of 10. 92 | 93 | If you like this, you might also like... 94 | ---------------------------------------- 95 | 96 | * **libextobjc** - The excellent [libextobjc](https://github.com/jspahrsummers/libextobjc) library also has a similar single macro implementation of this concept. However primitives are not supported, as well as the wider range of features provided here. However, for its other features, please check it out ;) 97 | * [FTGPropertyMaestro](https://github.com/onmyway133/FTGPropertyMaestro) is a runtime-based implementation with the same goal. 98 | * [Mattt Thompson has written an article on the subject of associated objects](http://nshipster.com/associated-objects/). He seems to find them a little controversial. Be your own judge. 99 | 100 | What's New 101 | ---------- 102 | 103 | **v2.0.1** 104 | 105 | * Made ARC a requirement in the podspec, since this is necessary to use the `weak` functionality with Cocoapods. 106 | 107 | **v2.0.0** 108 | 109 | * New format for the block accessor macros. Values are passed directly and must be returned. This is a breaking change. 110 | * New feature for `weak` properties, using the wrapper method suggested [here](http://nshipster.com/new-years-2015/). 111 | * The `NSObject` category is now prefixed and split into a subspec for Cocoapods. 112 | 113 | **v1.2.1** 114 | 115 | * ARC no longer a requirement (it never really was). 116 | * A bit of spring cleaning. 117 | 118 | **v1.2.0** 119 | 120 | * Now sends KVO notifications for all macros. Oversight on previous releases. 121 | 122 | **v1.1.2** 123 | 124 | * Improved block macro value handling. See details below. 125 | 126 | **v1.1.1** 127 | 128 | * Moved the execution order of setter blocks so the block can potential operate on the existing value. In the context of the block, `self.property` will be the existing value, *before* the new value is set. 129 | 130 | **v1.1** 131 | 132 | * Pass a block to the macros in order to modify setter values or getter return values in some way, as well as other custom code. 133 | 134 | **v1.0** 135 | 136 | * Static library target for iOS, and framework target for OS X. 137 | * [MIT Licensed](http://jc.mit-license.org/) 138 | 139 | 140 | Have fun! 141 | --------- 142 | 143 | [MIT Licensed](http://jc.mit-license.org/) >> [joncrooke@gmail.com](mailto:joncrooke@gmail.com) 144 | 145 | -------------------------------------------------------------------------------- /UnitTests/Specs.m: -------------------------------------------------------------------------------- 1 | // 2 | // Specs.m 3 | // ObjcAssociatedObjectHelpers 4 | // 5 | // Created by Jonathan Crooke on 20/02/2014. 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | // SOFTWARE. 24 | 25 | #import "TestClass.h" 26 | #import "ReactiveCocoa.h" 27 | 28 | #import "ObjcAssociatedObjectHelpers.h" 29 | #import "NSObject+AssociatedDictionary.h" 30 | 31 | #define EXP_SHORTHAND 32 | #import 33 | #import 34 | 35 | SpecBegin(Specs) 36 | 37 | __block TestClass *testObject; 38 | __block NSObject *dictionaryObject; 39 | 40 | NSString *const CONSTANT_STRING = @"ConstString"; 41 | 42 | before(^{ 43 | testObject = [[TestClass alloc] init]; 44 | dictionaryObject = [[NSObject alloc] init]; 45 | }); 46 | 47 | after(^{ 48 | testObject = nil; 49 | dictionaryObject = nil; 50 | }); 51 | 52 | describe(@"basic set / get", ^{ 53 | 54 | it(@"should set a simple retained object", ^{ 55 | NSBundle *bundle = [[NSBundle alloc] init]; 56 | testObject.object = bundle; 57 | expect(testObject.object).to.equal(bundle); 58 | }); 59 | 60 | it(@"should set a primitive", ^{ 61 | NSUInteger value = 99; 62 | testObject.primitive = value; 63 | expect(testObject.primitive).to.equal(value); 64 | }); 65 | 66 | it(@"should set a structure", ^{ 67 | TestStruct struct1 = { 1, 2.0 }; 68 | testObject.structure = struct1; 69 | TestStruct struct2 = testObject.structure; 70 | expect(memcmp(&struct1, &struct2, sizeof(TestStruct))).to.equal(NSOrderedSame); 71 | }); 72 | 73 | it(@"should assign a simple object", ^{ 74 | testObject.assignObj = CONSTANT_STRING; 75 | expect(testObject.assignObj).to.equal(CONSTANT_STRING); 76 | }); 77 | }); 78 | 79 | describe(@"mutable object", ^{ 80 | 81 | NSString *string = @"mutableString"; 82 | __block NSMutableString *mutableString = nil; 83 | 84 | before(^{ 85 | mutableString = string.mutableCopy; 86 | testObject.object = mutableString; 87 | }); 88 | 89 | it(@"should make a copy of the mutable object", ^{ 90 | expect(testObject.object == mutableString).to.beFalsy(); 91 | expect(testObject.object).to.equal(mutableString); 92 | expect(testObject.object).to.equal(string); 93 | expect(testObject.object).notTo.beInstanceOf([NSMutableString class]); 94 | }); 95 | 96 | it(@"should not modify the original", ^{ 97 | [mutableString appendString:@"Foo"]; 98 | expect(mutableString).to.equal(@"mutableStringFoo"); 99 | expect(testObject.object).to.equal(@"mutableString"); 100 | }); 101 | }); 102 | 103 | describe(@"read/write object with category", ^{ 104 | it(@"should be created", ^{ 105 | expect(testObject.readWriteObject).notTo.beNil(); 106 | expect(testObject.readWriteObject).to.beInstanceOf([NSObject class]); 107 | }); 108 | }); 109 | 110 | describe(@"lazy objects", ^{ 111 | 112 | specify(@"a simple case should be created", ^{ 113 | expect(testObject.lazyObject).to.beKindOf([NSString class]); 114 | }); 115 | 116 | specify(@"non-default lazy object should use specified initialization expression", ^{ 117 | expect(testObject.nonDefaultLazyObject).to.equal(@"foo"); 118 | }); 119 | 120 | }); 121 | 122 | describe(@"non-initialized primitive", ^{ 123 | 124 | it(@"should default to zero", ^{ 125 | expect(testObject.primitive).to.equal(0); 126 | }); 127 | 128 | }); 129 | 130 | describe(@"associated dictionary", ^{ 131 | 132 | it(@"should be initialized lazily", ^{ 133 | expect(dictionaryObject.ascObj_dictionary).to.beKindOf([NSMutableDictionary class]); 134 | }); 135 | 136 | it(@"should correctly get/set", ^{ 137 | NSString *key = @"bar"; NSString *value = @"foo"; 138 | dictionaryObject.ascObj_dictionary[key] = value; 139 | expect(dictionaryObject.ascObj_dictionary[key]).to.equal(value); 140 | }); 141 | 142 | }); 143 | 144 | describe(@"block feature", ^{ 145 | 146 | __block id object = nil; 147 | __block NSUInteger primitive = 0; 148 | 149 | describe(@"assign", ^{ 150 | it(@"should execute the block with setter", ^{ 151 | expect(^{ 152 | testObject.overrideAssignObj = CONSTANT_STRING; 153 | }).to.raise(@"setOverrideAssignObj:"); 154 | }); 155 | 156 | it(@"should execute the block with getter", ^{ 157 | expect(^{ 158 | object = testObject.overrideAssignObj; 159 | }).to.raise(@"overrideAssignObj"); 160 | }); 161 | }); 162 | 163 | describe(@"retain", ^{ 164 | it(@"should execute the block with setter", ^{ 165 | expect(^{ 166 | testObject.overrideObj = CONSTANT_STRING; 167 | }).to.raise(@"setOverrideObj:"); 168 | }); 169 | 170 | it(@"should execute the block with getter", ^{ 171 | expect(^{ 172 | object = testObject.overrideObj; 173 | }).to.raise(@"overrideObj"); 174 | }); 175 | }); 176 | 177 | describe(@"lazy getter", ^{ 178 | it(@"should execute the block with getter", ^{ 179 | expect(^{ 180 | object = testObject.overrideObjLazy; 181 | }).to.raise(@"overrideObjLazy"); 182 | }); 183 | }); 184 | 185 | describe(@"lazy getter with custom init", ^{ 186 | it(@"should execute the block with getter", ^{ 187 | expect(^{ 188 | object = testObject.overrideObjLazyWithExpression; 189 | }).to.raise(@"overrideObjLazyWithExpression"); 190 | }); 191 | }); 192 | 193 | describe(@"primitive", ^{ 194 | it(@"should execute the block with setter", ^{ 195 | expect(^{ 196 | testObject.overridePrimitive = 100; 197 | }).to.raise(@"setOverridePrimitive:"); 198 | }); 199 | 200 | it(@"should execute the block with getter", ^{ 201 | expect(^{ 202 | primitive = testObject.overridePrimitive; 203 | }).to.raise(@"overridePrimitive"); 204 | }); 205 | }); 206 | 207 | describe(@"modify values", ^{ 208 | 209 | describe(@"primtives", ^{ 210 | it(@"getter block should modify the value parameter", ^{ 211 | testObject.overrideBlockPrimitiveGetter = 99; 212 | expect(testObject.overrideBlockPrimitiveGetter).to.equal(100); 213 | }); 214 | 215 | it(@"setter block should modify the value parameter", ^{ 216 | testObject.overrideBlockPrimitiveSetter = 50; 217 | expect(testObject.overrideBlockPrimitiveSetter).to.equal(49); 218 | }); 219 | }); 220 | 221 | describe(@"objects", ^{ 222 | it(@"getter block should modify the value parameter", ^{ 223 | testObject.overrideObjBlockGetter = @"bar"; 224 | expect(testObject.overrideObjBlockGetter).to.equal(@"foo"); 225 | }); 226 | 227 | it(@"setter block should modify the value parameter", ^{ 228 | testObject.overrideObjBlockSetter = @"cat"; 229 | expect(testObject.overrideObjBlockSetter).to.equal(@"foo"); 230 | }); 231 | }); 232 | }); 233 | }); 234 | 235 | describe(@"KVO notifications", ^{ 236 | 237 | it(@"should send kvo notifications with object retain", ^{ 238 | waitUntil(^(DoneCallback done) { 239 | [[[RACObserve(testObject, readWriteObject) skip:1] take:1] subscribeNext:^(id x) { 240 | expect(x).to.equal(@"1234"); 241 | done(); 242 | }]; 243 | testObject.readWriteObject = @"1234"; 244 | }); 245 | }); 246 | 247 | it(@"should send notifications with object assign", ^{ 248 | waitUntil(^(DoneCallback done) { 249 | [[[RACObserve(testObject, assignObj) skip:1] take:1] subscribeNext:^(id x) { 250 | expect(x).to.equal(@"asdf"); 251 | done(); 252 | }]; 253 | testObject.assignObj = @"asdf"; 254 | }); 255 | }); 256 | 257 | it(@"should send notifications with primitive", ^{ 258 | waitUntil(^(DoneCallback done) { 259 | [[[RACObserve(testObject, primitive) skip:1] take:1] subscribeNext:^(id x) { 260 | expect(x).to.equal(9675); 261 | done(); 262 | }]; 263 | testObject.primitive = 9675; 264 | }); 265 | }); 266 | }); 267 | 268 | SpecEnd 269 | 270 | -------------------------------------------------------------------------------- /UnitTests/TestClass.h: -------------------------------------------------------------------------------- 1 | // 2 | // TestClass.h 3 | // ObjcAssociatedObjectHelpers 4 | // 5 | // Created by Jonathan Crooke on 20/02/2014. 6 | // Copyright (c) 2014 jbsoft. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef struct _testStruct { 12 | int member1; 13 | float member2; 14 | } TestStruct; 15 | 16 | @interface TestClass : NSObject 17 | @property (retain) id object; 18 | @property (assign) id assignObj; 19 | @property (readonly) id lazyObject; 20 | @property (readonly) id nonDefaultLazyObject; 21 | @property (readwrite, retain) id readWriteObject; 22 | @property (assign) NSUInteger primitive; 23 | @property (assign) TestStruct structure; 24 | // overrides 25 | @property (assign) id overrideAssignObj; 26 | @property (retain) id overrideObj; 27 | @property (readonly) id overrideObjLazy; 28 | @property (readonly) id overrideObjLazyWithExpression; 29 | @property (assign) NSUInteger overridePrimitive; 30 | // Override value 31 | @property (retain) NSString *overrideObjBlockGetter; 32 | @property (retain) NSString *overrideObjBlockSetter; 33 | @property (assign) NSUInteger overrideBlockPrimitiveGetter; 34 | @property (assign) NSUInteger overrideBlockPrimitiveSetter; 35 | // Weak container 36 | #if __has_feature(objc_arc) 37 | @property (weak) id weakObject; 38 | @property (weak) id weakObject2; 39 | #endif 40 | @end 41 | -------------------------------------------------------------------------------- /UnitTests/TestClass.m: -------------------------------------------------------------------------------- 1 | // 2 | // TestClass.m 3 | // ObjcAssociatedObjectHelpers 4 | // 5 | // Created by Jonathan Crooke on 20/02/2014. 6 | // Copyright (c) 2014 jbsoft. All rights reserved. 7 | // 8 | 9 | #import "TestClass.h" 10 | #import "ObjcAssociatedObjectHelpers.h" 11 | 12 | static NSString *_strongString = @"StrongString"; 13 | 14 | #define TEST_EXCEPTION \ 15 | [[NSException exceptionWithName:NSStringFromSelector(_cmd) \ 16 | reason:NSStringFromSelector(_cmd) \ 17 | userInfo:nil] raise] 18 | 19 | @implementation TestClass 20 | 21 | SYNTHESIZE_ASC_OBJ(object, setObject); 22 | SYNTHESIZE_ASC_OBJ_LAZY(lazyObject, [NSString class]) 23 | SYNTHESIZE_ASC_OBJ_ASSIGN(assignObj, setAssignObj); 24 | SYNTHESIZE_ASC_OBJ_LAZY_EXP(nonDefaultLazyObject, [NSString stringWithFormat:@"foo"]) 25 | SYNTHESIZE_ASC_OBJ(readWriteObject, setReadWriteObject); 26 | SYNTHESIZE_ASC_PRIMITIVE(primitive, setPrimitive, NSUInteger); 27 | SYNTHESIZE_ASC_PRIMITIVE(structure, setStructure, TestStruct); 28 | 29 | // Weak 30 | #if __has_feature(objc_arc) 31 | SYNTHESIZE_ASC_OBJ_WEAK(weakObject, setWeakObject) 32 | SYNTHESIZE_ASC_OBJ_WEAK_BLOCK(weakObject2, 33 | setWeakObject2, 34 | ^(NSString *object) { return [object stringByAppendingString:object]; }, 35 | ^(NSObject *object) { return _strongString; }); 36 | #endif 37 | 38 | // overrides 39 | SYNTHESIZE_ASC_OBJ_ASSIGN_BLOCK(overrideAssignObj, 40 | setOverrideAssignObj, 41 | ^(id v){ TEST_EXCEPTION; return v; }, 42 | ^(id v){ TEST_EXCEPTION; return v; }); 43 | SYNTHESIZE_ASC_OBJ_BLOCK(overrideObj, 44 | setOverrideObj, 45 | ^(id v){ TEST_EXCEPTION; return v; }, 46 | ^(id v){ TEST_EXCEPTION; return v; }); 47 | SYNTHESIZE_ASC_OBJ_LAZY_BLOCK(overrideObjLazy, 48 | [NSString class], 49 | ^(NSString *v){ TEST_EXCEPTION; return v; }) 50 | SYNTHESIZE_ASC_OBJ_LAZY_EXP_BLOCK(overrideObjLazyWithExpression, 51 | [NSDate date], 52 | ^(NSDate *v){ TEST_EXCEPTION; return v; }) 53 | SYNTHESIZE_ASC_PRIMITIVE_BLOCK(overridePrimitive, 54 | setOverridePrimitive, 55 | NSUInteger, 56 | ^(NSUInteger v){ TEST_EXCEPTION; return v; }, 57 | ^(NSUInteger v){ TEST_EXCEPTION; return v; }) 58 | SYNTHESIZE_ASC_OBJ_BLOCK(overrideObjBlockGetter, 59 | setOverrideObjBlockGetter, 60 | ^(id v){ return @"foo"; }, 61 | ^(id v){ return v; }) 62 | SYNTHESIZE_ASC_OBJ_BLOCK(overrideObjBlockSetter, 63 | setOverrideObjBlockSetter, 64 | ^(id v){ return v; }, 65 | ^(id v){ return @"foo"; }) 66 | SYNTHESIZE_ASC_PRIMITIVE_BLOCK(overrideBlockPrimitiveGetter, 67 | setOverrideBlockPrimitiveGetter, 68 | NSUInteger, 69 | ^(NSUInteger v){ return v+1; }, 70 | ^(NSUInteger v){ return v; }) 71 | SYNTHESIZE_ASC_PRIMITIVE_BLOCK(overrideBlockPrimitiveSetter, 72 | setOverrideBlockPrimitiveSetter, 73 | NSUInteger, 74 | ^(NSUInteger v){ return v; }, 75 | ^(NSUInteger v){ return v-1; }) 76 | 77 | - (id)init { 78 | if ((self = [super init])) { 79 | self.readWriteObject = [[NSObject alloc] init]; 80 | } 81 | return self; 82 | } 83 | 84 | @end 85 | -------------------------------------------------------------------------------- /UnitTests/WeakContainer.m: -------------------------------------------------------------------------------- 1 | // 2 | // WeakContainer.m 3 | // ObjcAssociatedObjectHelpers 4 | // 5 | // Created by Jonathan Crooke on 26/02/2015. 6 | // Copyright (c) 2015 jbsoft. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "ObjcAssociatedObjectHelpers.h" 11 | #import "TestClass.h" 12 | 13 | #if __has_feature(objc_arc) 14 | @interface WeakContainer : XCTestCase 15 | @property (nonatomic, strong) TestClass *testObject; 16 | @property (nonatomic, strong) NSArray *strongContainer; 17 | @end 18 | 19 | @implementation WeakContainer 20 | 21 | - (void)testGetAndSetAValueAsNormal { 22 | XCTAssertNotNil(self.testObject.weakObject); 23 | XCTAssertEqual(self.testObject.weakObject, self.strongContainer.firstObject); 24 | } 25 | 26 | - (void)testNilOfWeakProperty { 27 | XCTestExpectation *expectation = [self expectationWithDescription:@"Weak property becomes nil"]; 28 | self.strongContainer = nil; 29 | dispatch_async(dispatch_get_main_queue(), ^{ 30 | XCTAssertNil(self.testObject.weakObject); 31 | [expectation fulfill]; 32 | }); 33 | [self waitForExpectationsWithTimeout:1 handler:nil]; 34 | } 35 | 36 | - (void) testWeakBlock { 37 | XCTAssertEqualObjects(self.testObject.weakObject2, @"StrongStringStrongString"); 38 | } 39 | 40 | #pragma mark - 41 | 42 | - (void)setUp { 43 | [super setUp]; 44 | self.testObject = [[TestClass alloc] init]; 45 | self.strongContainer = @[[[NSObject alloc] init]]; 46 | self.testObject.weakObject = self.strongContainer.firstObject; 47 | self.testObject.weakObject2 = self.strongContainer.firstObject; 48 | } 49 | 50 | @end 51 | #endif 52 | --------------------------------------------------------------------------------