├── .gitignore ├── LICENSE ├── Objective-C Runtime.pdf ├── README.md └── example code ├── 1. PureC ├── PureC.xcodeproj │ └── project.pbxproj ├── PureC │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Images.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── PureC-Info.plist │ ├── PureC-Prefix.pch │ ├── View.m │ ├── en.lproj │ │ ├── Credits.rtf │ │ └── InfoPlist.strings │ └── main.m ├── PureCTests │ ├── PureCTests-Info.plist │ ├── PureCTests.m │ └── en.lproj │ │ └── InfoPlist.strings └── README.md ├── 2. ObjCSimple ├── ObjCSimple.xcodeproj │ └── project.pbxproj └── ObjCSimple │ └── main.m ├── 3. ObjCDynamicResolve ├── ObjCDynamicResolve.xcodeproj │ └── project.pbxproj └── ObjCDynamicResolve │ └── main.m ├── 4. ObjCForwarding ├── ObjCForwarding.xcodeproj │ └── project.pbxproj └── ObjCForwarding │ ├── http___cocoaheads_be.html │ └── main.m ├── 5. ObjCMethodSwizzling ├── ObjCMethodSwizzling.xcodeproj │ └── project.pbxproj └── ObjCMethodSwizzling │ └── main.m ├── 6. ObjCClassSwizzling ├── ObjCClassSwizzling.xcodeproj │ └── project.pbxproj └── ObjCClassSwizzling │ └── main.m └── 7. ObjCGeneratedProperties ├── ObjCGeneratedProperties.xcodeproj └── project.pbxproj └── ObjCGeneratedProperties └── main.m /.gitignore: -------------------------------------------------------------------------------- 1 | # xcode noise 2 | *.pbxuser 3 | *.mode1v3 4 | *.xcworkspace 5 | xcuserdata 6 | project.xcworkspace/* 7 | xcuserdata/* 8 | builds/* 9 | */DerivedData/* 10 | 11 | # osx noise 12 | .DS_Store 13 | profile 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Tom Adriaenssen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | 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, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /Objective-C Runtime.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Inferis/Objective-C-Runtime/380681269c122fbafadbb78264d06c7d43dfcddd/Objective-C Runtime.pdf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Objective-C-Runtime 2 | 3 | This repo contains the code examples of the Objective-C Runtime in Practice talk I gave for CocoaHeadsBE on 20131203. 4 | 5 | You can also find the presentation on: 6 | * raw (github): https://github.com/Inferis/Objective-C-Runtime/blob/master/Objective-C%20Runtime.pdf?raw=true 7 | * slideshare: http://www.slideshare.net/Inferis/objective-c-runtime 8 | * speakerdeck: https://speakerdeck.com/inferis/objective-c-runtime-in-practice 9 | 10 | Any questions: feel free to contact me (either here or via twitter: I'm @inferis). 11 | 12 | -------------------------------------------------------------------------------- /example code/1. PureC/PureC.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | E2985D8E184E44A60085DC5D /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E2985D8D184E44A60085DC5D /* Cocoa.framework */; }; 11 | E2985D98184E44A60085DC5D /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = E2985D96184E44A60085DC5D /* InfoPlist.strings */; }; 12 | E2985D9A184E44A60085DC5D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = E2985D99184E44A60085DC5D /* main.m */; }; 13 | E2985D9E184E44A60085DC5D /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = E2985D9C184E44A60085DC5D /* Credits.rtf */; }; 14 | E2985DA1184E44A60085DC5D /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = E2985DA0184E44A60085DC5D /* AppDelegate.m */; }; 15 | E2985DA6184E44A60085DC5D /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E2985DA5184E44A60085DC5D /* Images.xcassets */; }; 16 | E2985DAD184E44A60085DC5D /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E2985DAC184E44A60085DC5D /* XCTest.framework */; }; 17 | E2985DAE184E44A60085DC5D /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E2985D8D184E44A60085DC5D /* Cocoa.framework */; }; 18 | E2985DB6184E44A60085DC5D /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = E2985DB4184E44A60085DC5D /* InfoPlist.strings */; }; 19 | E2985DB8184E44A60085DC5D /* PureCTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E2985DB7184E44A60085DC5D /* PureCTests.m */; }; 20 | E2985DC3184E45FF0085DC5D /* View.m in Sources */ = {isa = PBXBuildFile; fileRef = E2985DC2184E45FF0085DC5D /* View.m */; }; 21 | /* End PBXBuildFile section */ 22 | 23 | /* Begin PBXContainerItemProxy section */ 24 | E2985DAF184E44A60085DC5D /* PBXContainerItemProxy */ = { 25 | isa = PBXContainerItemProxy; 26 | containerPortal = E2985D82184E44A60085DC5D /* Project object */; 27 | proxyType = 1; 28 | remoteGlobalIDString = E2985D89184E44A60085DC5D; 29 | remoteInfo = PureC; 30 | }; 31 | /* End PBXContainerItemProxy section */ 32 | 33 | /* Begin PBXFileReference section */ 34 | E2985D8A184E44A60085DC5D /* PureC.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PureC.app; sourceTree = BUILT_PRODUCTS_DIR; }; 35 | E2985D8D184E44A60085DC5D /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; 36 | E2985D90184E44A60085DC5D /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; 37 | E2985D91184E44A60085DC5D /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; 38 | E2985D92184E44A60085DC5D /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 39 | E2985D95184E44A60085DC5D /* PureC-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "PureC-Info.plist"; sourceTree = ""; }; 40 | E2985D97184E44A60085DC5D /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 41 | E2985D99184E44A60085DC5D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 42 | E2985D9B184E44A60085DC5D /* PureC-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "PureC-Prefix.pch"; sourceTree = ""; }; 43 | E2985D9D184E44A60085DC5D /* en */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = en; path = en.lproj/Credits.rtf; sourceTree = ""; }; 44 | E2985D9F184E44A60085DC5D /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 45 | E2985DA0184E44A60085DC5D /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 46 | E2985DA5184E44A60085DC5D /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 47 | E2985DAB184E44A60085DC5D /* PureCTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PureCTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 48 | E2985DAC184E44A60085DC5D /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 49 | E2985DB3184E44A60085DC5D /* PureCTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "PureCTests-Info.plist"; sourceTree = ""; }; 50 | E2985DB5184E44A60085DC5D /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 51 | E2985DB7184E44A60085DC5D /* PureCTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PureCTests.m; sourceTree = ""; }; 52 | E2985DC2184E45FF0085DC5D /* View.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = View.m; sourceTree = ""; }; 53 | /* End PBXFileReference section */ 54 | 55 | /* Begin PBXFrameworksBuildPhase section */ 56 | E2985D87184E44A60085DC5D /* Frameworks */ = { 57 | isa = PBXFrameworksBuildPhase; 58 | buildActionMask = 2147483647; 59 | files = ( 60 | E2985D8E184E44A60085DC5D /* Cocoa.framework in Frameworks */, 61 | ); 62 | runOnlyForDeploymentPostprocessing = 0; 63 | }; 64 | E2985DA8184E44A60085DC5D /* Frameworks */ = { 65 | isa = PBXFrameworksBuildPhase; 66 | buildActionMask = 2147483647; 67 | files = ( 68 | E2985DAE184E44A60085DC5D /* Cocoa.framework in Frameworks */, 69 | E2985DAD184E44A60085DC5D /* XCTest.framework in Frameworks */, 70 | ); 71 | runOnlyForDeploymentPostprocessing = 0; 72 | }; 73 | /* End PBXFrameworksBuildPhase section */ 74 | 75 | /* Begin PBXGroup section */ 76 | E2985D81184E44A60085DC5D = { 77 | isa = PBXGroup; 78 | children = ( 79 | E2985D93184E44A60085DC5D /* PureC */, 80 | E2985DB1184E44A60085DC5D /* PureCTests */, 81 | E2985D8C184E44A60085DC5D /* Frameworks */, 82 | E2985D8B184E44A60085DC5D /* Products */, 83 | ); 84 | sourceTree = ""; 85 | }; 86 | E2985D8B184E44A60085DC5D /* Products */ = { 87 | isa = PBXGroup; 88 | children = ( 89 | E2985D8A184E44A60085DC5D /* PureC.app */, 90 | E2985DAB184E44A60085DC5D /* PureCTests.xctest */, 91 | ); 92 | name = Products; 93 | sourceTree = ""; 94 | }; 95 | E2985D8C184E44A60085DC5D /* Frameworks */ = { 96 | isa = PBXGroup; 97 | children = ( 98 | E2985D8D184E44A60085DC5D /* Cocoa.framework */, 99 | E2985DAC184E44A60085DC5D /* XCTest.framework */, 100 | E2985D8F184E44A60085DC5D /* Other Frameworks */, 101 | ); 102 | name = Frameworks; 103 | sourceTree = ""; 104 | }; 105 | E2985D8F184E44A60085DC5D /* Other Frameworks */ = { 106 | isa = PBXGroup; 107 | children = ( 108 | E2985D90184E44A60085DC5D /* AppKit.framework */, 109 | E2985D91184E44A60085DC5D /* CoreData.framework */, 110 | E2985D92184E44A60085DC5D /* Foundation.framework */, 111 | ); 112 | name = "Other Frameworks"; 113 | sourceTree = ""; 114 | }; 115 | E2985D93184E44A60085DC5D /* PureC */ = { 116 | isa = PBXGroup; 117 | children = ( 118 | E2985D9F184E44A60085DC5D /* AppDelegate.h */, 119 | E2985DA0184E44A60085DC5D /* AppDelegate.m */, 120 | E2985DC2184E45FF0085DC5D /* View.m */, 121 | E2985DA5184E44A60085DC5D /* Images.xcassets */, 122 | E2985D94184E44A60085DC5D /* Supporting Files */, 123 | ); 124 | path = PureC; 125 | sourceTree = ""; 126 | }; 127 | E2985D94184E44A60085DC5D /* Supporting Files */ = { 128 | isa = PBXGroup; 129 | children = ( 130 | E2985D95184E44A60085DC5D /* PureC-Info.plist */, 131 | E2985D96184E44A60085DC5D /* InfoPlist.strings */, 132 | E2985D99184E44A60085DC5D /* main.m */, 133 | E2985D9B184E44A60085DC5D /* PureC-Prefix.pch */, 134 | E2985D9C184E44A60085DC5D /* Credits.rtf */, 135 | ); 136 | name = "Supporting Files"; 137 | sourceTree = ""; 138 | }; 139 | E2985DB1184E44A60085DC5D /* PureCTests */ = { 140 | isa = PBXGroup; 141 | children = ( 142 | E2985DB7184E44A60085DC5D /* PureCTests.m */, 143 | E2985DB2184E44A60085DC5D /* Supporting Files */, 144 | ); 145 | path = PureCTests; 146 | sourceTree = ""; 147 | }; 148 | E2985DB2184E44A60085DC5D /* Supporting Files */ = { 149 | isa = PBXGroup; 150 | children = ( 151 | E2985DB3184E44A60085DC5D /* PureCTests-Info.plist */, 152 | E2985DB4184E44A60085DC5D /* InfoPlist.strings */, 153 | ); 154 | name = "Supporting Files"; 155 | sourceTree = ""; 156 | }; 157 | /* End PBXGroup section */ 158 | 159 | /* Begin PBXNativeTarget section */ 160 | E2985D89184E44A60085DC5D /* PureC */ = { 161 | isa = PBXNativeTarget; 162 | buildConfigurationList = E2985DBB184E44A60085DC5D /* Build configuration list for PBXNativeTarget "PureC" */; 163 | buildPhases = ( 164 | E2985D86184E44A60085DC5D /* Sources */, 165 | E2985D87184E44A60085DC5D /* Frameworks */, 166 | E2985D88184E44A60085DC5D /* Resources */, 167 | ); 168 | buildRules = ( 169 | ); 170 | dependencies = ( 171 | ); 172 | name = PureC; 173 | productName = PureC; 174 | productReference = E2985D8A184E44A60085DC5D /* PureC.app */; 175 | productType = "com.apple.product-type.application"; 176 | }; 177 | E2985DAA184E44A60085DC5D /* PureCTests */ = { 178 | isa = PBXNativeTarget; 179 | buildConfigurationList = E2985DBE184E44A60085DC5D /* Build configuration list for PBXNativeTarget "PureCTests" */; 180 | buildPhases = ( 181 | E2985DA7184E44A60085DC5D /* Sources */, 182 | E2985DA8184E44A60085DC5D /* Frameworks */, 183 | E2985DA9184E44A60085DC5D /* Resources */, 184 | ); 185 | buildRules = ( 186 | ); 187 | dependencies = ( 188 | E2985DB0184E44A60085DC5D /* PBXTargetDependency */, 189 | ); 190 | name = PureCTests; 191 | productName = PureCTests; 192 | productReference = E2985DAB184E44A60085DC5D /* PureCTests.xctest */; 193 | productType = "com.apple.product-type.bundle.unit-test"; 194 | }; 195 | /* End PBXNativeTarget section */ 196 | 197 | /* Begin PBXProject section */ 198 | E2985D82184E44A60085DC5D /* Project object */ = { 199 | isa = PBXProject; 200 | attributes = { 201 | LastUpgradeCheck = 0500; 202 | ORGANIZATIONNAME = "Tom Adriaenssen"; 203 | TargetAttributes = { 204 | E2985DAA184E44A60085DC5D = { 205 | TestTargetID = E2985D89184E44A60085DC5D; 206 | }; 207 | }; 208 | }; 209 | buildConfigurationList = E2985D85184E44A60085DC5D /* Build configuration list for PBXProject "PureC" */; 210 | compatibilityVersion = "Xcode 3.2"; 211 | developmentRegion = English; 212 | hasScannedForEncodings = 0; 213 | knownRegions = ( 214 | en, 215 | Base, 216 | ); 217 | mainGroup = E2985D81184E44A60085DC5D; 218 | productRefGroup = E2985D8B184E44A60085DC5D /* Products */; 219 | projectDirPath = ""; 220 | projectRoot = ""; 221 | targets = ( 222 | E2985D89184E44A60085DC5D /* PureC */, 223 | E2985DAA184E44A60085DC5D /* PureCTests */, 224 | ); 225 | }; 226 | /* End PBXProject section */ 227 | 228 | /* Begin PBXResourcesBuildPhase section */ 229 | E2985D88184E44A60085DC5D /* Resources */ = { 230 | isa = PBXResourcesBuildPhase; 231 | buildActionMask = 2147483647; 232 | files = ( 233 | E2985D98184E44A60085DC5D /* InfoPlist.strings in Resources */, 234 | E2985DA6184E44A60085DC5D /* Images.xcassets in Resources */, 235 | E2985D9E184E44A60085DC5D /* Credits.rtf in Resources */, 236 | ); 237 | runOnlyForDeploymentPostprocessing = 0; 238 | }; 239 | E2985DA9184E44A60085DC5D /* Resources */ = { 240 | isa = PBXResourcesBuildPhase; 241 | buildActionMask = 2147483647; 242 | files = ( 243 | E2985DB6184E44A60085DC5D /* InfoPlist.strings in Resources */, 244 | ); 245 | runOnlyForDeploymentPostprocessing = 0; 246 | }; 247 | /* End PBXResourcesBuildPhase section */ 248 | 249 | /* Begin PBXSourcesBuildPhase section */ 250 | E2985D86184E44A60085DC5D /* Sources */ = { 251 | isa = PBXSourcesBuildPhase; 252 | buildActionMask = 2147483647; 253 | files = ( 254 | E2985DA1184E44A60085DC5D /* AppDelegate.m in Sources */, 255 | E2985D9A184E44A60085DC5D /* main.m in Sources */, 256 | E2985DC3184E45FF0085DC5D /* View.m in Sources */, 257 | ); 258 | runOnlyForDeploymentPostprocessing = 0; 259 | }; 260 | E2985DA7184E44A60085DC5D /* Sources */ = { 261 | isa = PBXSourcesBuildPhase; 262 | buildActionMask = 2147483647; 263 | files = ( 264 | E2985DB8184E44A60085DC5D /* PureCTests.m in Sources */, 265 | ); 266 | runOnlyForDeploymentPostprocessing = 0; 267 | }; 268 | /* End PBXSourcesBuildPhase section */ 269 | 270 | /* Begin PBXTargetDependency section */ 271 | E2985DB0184E44A60085DC5D /* PBXTargetDependency */ = { 272 | isa = PBXTargetDependency; 273 | target = E2985D89184E44A60085DC5D /* PureC */; 274 | targetProxy = E2985DAF184E44A60085DC5D /* PBXContainerItemProxy */; 275 | }; 276 | /* End PBXTargetDependency section */ 277 | 278 | /* Begin PBXVariantGroup section */ 279 | E2985D96184E44A60085DC5D /* InfoPlist.strings */ = { 280 | isa = PBXVariantGroup; 281 | children = ( 282 | E2985D97184E44A60085DC5D /* en */, 283 | ); 284 | name = InfoPlist.strings; 285 | sourceTree = ""; 286 | }; 287 | E2985D9C184E44A60085DC5D /* Credits.rtf */ = { 288 | isa = PBXVariantGroup; 289 | children = ( 290 | E2985D9D184E44A60085DC5D /* en */, 291 | ); 292 | name = Credits.rtf; 293 | sourceTree = ""; 294 | }; 295 | E2985DB4184E44A60085DC5D /* InfoPlist.strings */ = { 296 | isa = PBXVariantGroup; 297 | children = ( 298 | E2985DB5184E44A60085DC5D /* en */, 299 | ); 300 | name = InfoPlist.strings; 301 | sourceTree = ""; 302 | }; 303 | /* End PBXVariantGroup section */ 304 | 305 | /* Begin XCBuildConfiguration section */ 306 | E2985DB9184E44A60085DC5D /* Debug */ = { 307 | isa = XCBuildConfiguration; 308 | buildSettings = { 309 | ALWAYS_SEARCH_USER_PATHS = NO; 310 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 311 | CLANG_CXX_LIBRARY = "libc++"; 312 | CLANG_ENABLE_OBJC_ARC = YES; 313 | CLANG_WARN_BOOL_CONVERSION = YES; 314 | CLANG_WARN_CONSTANT_CONVERSION = YES; 315 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 316 | CLANG_WARN_EMPTY_BODY = YES; 317 | CLANG_WARN_ENUM_CONVERSION = YES; 318 | CLANG_WARN_INT_CONVERSION = YES; 319 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 320 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 321 | COPY_PHASE_STRIP = NO; 322 | GCC_C_LANGUAGE_STANDARD = gnu99; 323 | GCC_DYNAMIC_NO_PIC = NO; 324 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 325 | GCC_OPTIMIZATION_LEVEL = 0; 326 | GCC_PREPROCESSOR_DEFINITIONS = ( 327 | "DEBUG=1", 328 | "$(inherited)", 329 | ); 330 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 331 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 332 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 333 | GCC_WARN_UNDECLARED_SELECTOR = YES; 334 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 335 | GCC_WARN_UNUSED_FUNCTION = YES; 336 | GCC_WARN_UNUSED_VARIABLE = YES; 337 | MACOSX_DEPLOYMENT_TARGET = 10.9; 338 | ONLY_ACTIVE_ARCH = YES; 339 | SDKROOT = macosx; 340 | }; 341 | name = Debug; 342 | }; 343 | E2985DBA184E44A60085DC5D /* Release */ = { 344 | isa = XCBuildConfiguration; 345 | buildSettings = { 346 | ALWAYS_SEARCH_USER_PATHS = NO; 347 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 348 | CLANG_CXX_LIBRARY = "libc++"; 349 | CLANG_ENABLE_OBJC_ARC = YES; 350 | CLANG_WARN_BOOL_CONVERSION = YES; 351 | CLANG_WARN_CONSTANT_CONVERSION = YES; 352 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 353 | CLANG_WARN_EMPTY_BODY = YES; 354 | CLANG_WARN_ENUM_CONVERSION = YES; 355 | CLANG_WARN_INT_CONVERSION = YES; 356 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 357 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 358 | COPY_PHASE_STRIP = YES; 359 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 360 | ENABLE_NS_ASSERTIONS = NO; 361 | GCC_C_LANGUAGE_STANDARD = gnu99; 362 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 363 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 364 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 365 | GCC_WARN_UNDECLARED_SELECTOR = YES; 366 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 367 | GCC_WARN_UNUSED_FUNCTION = YES; 368 | GCC_WARN_UNUSED_VARIABLE = YES; 369 | MACOSX_DEPLOYMENT_TARGET = 10.9; 370 | SDKROOT = macosx; 371 | }; 372 | name = Release; 373 | }; 374 | E2985DBC184E44A60085DC5D /* Debug */ = { 375 | isa = XCBuildConfiguration; 376 | buildSettings = { 377 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 378 | CLANG_ENABLE_OBJC_ARC = NO; 379 | COMBINE_HIDPI_IMAGES = YES; 380 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 381 | GCC_PREFIX_HEADER = "PureC/PureC-Prefix.pch"; 382 | INFOPLIST_FILE = "PureC/PureC-Info.plist"; 383 | PRODUCT_NAME = "$(TARGET_NAME)"; 384 | WRAPPER_EXTENSION = app; 385 | }; 386 | name = Debug; 387 | }; 388 | E2985DBD184E44A60085DC5D /* Release */ = { 389 | isa = XCBuildConfiguration; 390 | buildSettings = { 391 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 392 | CLANG_ENABLE_OBJC_ARC = NO; 393 | COMBINE_HIDPI_IMAGES = YES; 394 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 395 | GCC_PREFIX_HEADER = "PureC/PureC-Prefix.pch"; 396 | INFOPLIST_FILE = "PureC/PureC-Info.plist"; 397 | PRODUCT_NAME = "$(TARGET_NAME)"; 398 | WRAPPER_EXTENSION = app; 399 | }; 400 | name = Release; 401 | }; 402 | E2985DBF184E44A60085DC5D /* Debug */ = { 403 | isa = XCBuildConfiguration; 404 | buildSettings = { 405 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/PureC.app/Contents/MacOS/PureC"; 406 | COMBINE_HIDPI_IMAGES = YES; 407 | FRAMEWORK_SEARCH_PATHS = ( 408 | "$(DEVELOPER_FRAMEWORKS_DIR)", 409 | "$(inherited)", 410 | ); 411 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 412 | GCC_PREFIX_HEADER = "PureC/PureC-Prefix.pch"; 413 | GCC_PREPROCESSOR_DEFINITIONS = ( 414 | "DEBUG=1", 415 | "$(inherited)", 416 | ); 417 | INFOPLIST_FILE = "PureCTests/PureCTests-Info.plist"; 418 | PRODUCT_NAME = "$(TARGET_NAME)"; 419 | TEST_HOST = "$(BUNDLE_LOADER)"; 420 | WRAPPER_EXTENSION = xctest; 421 | }; 422 | name = Debug; 423 | }; 424 | E2985DC0184E44A60085DC5D /* Release */ = { 425 | isa = XCBuildConfiguration; 426 | buildSettings = { 427 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/PureC.app/Contents/MacOS/PureC"; 428 | COMBINE_HIDPI_IMAGES = YES; 429 | FRAMEWORK_SEARCH_PATHS = ( 430 | "$(DEVELOPER_FRAMEWORKS_DIR)", 431 | "$(inherited)", 432 | ); 433 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 434 | GCC_PREFIX_HEADER = "PureC/PureC-Prefix.pch"; 435 | INFOPLIST_FILE = "PureCTests/PureCTests-Info.plist"; 436 | PRODUCT_NAME = "$(TARGET_NAME)"; 437 | TEST_HOST = "$(BUNDLE_LOADER)"; 438 | WRAPPER_EXTENSION = xctest; 439 | }; 440 | name = Release; 441 | }; 442 | /* End XCBuildConfiguration section */ 443 | 444 | /* Begin XCConfigurationList section */ 445 | E2985D85184E44A60085DC5D /* Build configuration list for PBXProject "PureC" */ = { 446 | isa = XCConfigurationList; 447 | buildConfigurations = ( 448 | E2985DB9184E44A60085DC5D /* Debug */, 449 | E2985DBA184E44A60085DC5D /* Release */, 450 | ); 451 | defaultConfigurationIsVisible = 0; 452 | defaultConfigurationName = Release; 453 | }; 454 | E2985DBB184E44A60085DC5D /* Build configuration list for PBXNativeTarget "PureC" */ = { 455 | isa = XCConfigurationList; 456 | buildConfigurations = ( 457 | E2985DBC184E44A60085DC5D /* Debug */, 458 | E2985DBD184E44A60085DC5D /* Release */, 459 | ); 460 | defaultConfigurationIsVisible = 0; 461 | }; 462 | E2985DBE184E44A60085DC5D /* Build configuration list for PBXNativeTarget "PureCTests" */ = { 463 | isa = XCConfigurationList; 464 | buildConfigurations = ( 465 | E2985DBF184E44A60085DC5D /* Debug */, 466 | E2985DC0184E44A60085DC5D /* Release */, 467 | ); 468 | defaultConfigurationIsVisible = 0; 469 | }; 470 | /* End XCConfigurationList section */ 471 | }; 472 | rootObject = E2985D82184E44A60085DC5D /* Project object */; 473 | } 474 | -------------------------------------------------------------------------------- /example code/1. PureC/PureC/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // PureC 4 | // 5 | // Created by Tom Adriaenssen on 03/12/13. 6 | // Copyright (c) 2013 Tom Adriaenssen. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | extern void initAppDel(); 12 | extern void init_app(void); -------------------------------------------------------------------------------- /example code/1. PureC/PureC/AppDelegate.m: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | extern id NSApp; 5 | 6 | struct AppDel 7 | { 8 | Class isa; 9 | 10 | //Will be an NSWindow later, for now, it's id, because we cannot use pointers to ObjC classes 11 | id window; 12 | }; 13 | 14 | 15 | // This is a strong reference to the class of the AppDelegate 16 | // (same as [AppDelegate class]) 17 | Class AppDelClass; 18 | 19 | BOOL AppDel_didFinishLaunching(struct AppDel *self, SEL _cmd, id notification) { 20 | //alloc NSWindow 21 | self->window = objc_msgSend(objc_getClass("NSWindow"), 22 | sel_getUid("alloc")); 23 | 24 | //init NSWindow 25 | //Adjust frame. Window would be about 50*50 px without this 26 | //specify window type. We want a resizeable window that we can close. 27 | //use retained backing because this thing is small anyhow 28 | //return no because this is the main window, and should be shown immediately 29 | self->window = objc_msgSend(self->window, 30 | sel_getUid("initWithContentRect:styleMask:backing:defer:"),(NSRect){0,0,1024,460}, (NSTitledWindowMask|NSClosableWindowMask|NSResizableWindowMask|NSMiniaturizableWindowMask),NSBackingStoreRetained,NO); 31 | 32 | //send alloc and init to our view class. Love the nested objc_msgSends! 33 | id view = objc_msgSend(objc_msgSend(objc_getClass("View"), sel_getUid("alloc")), sel_getUid("initWithFrame:"), (struct CGRect) { 0, 0, 320, 480 }); 34 | 35 | // here we simply add the view to the window. 36 | objc_msgSend(self->window, sel_getUid("setContentView:"), view); 37 | objc_msgSend(self->window, sel_getUid("becomeFirstResponder")); 38 | 39 | //makeKeyOrderFront: NSWindow to show in bottom left corner of the screen 40 | objc_msgSend(self->window, 41 | sel_getUid("makeKeyAndOrderFront:"), 42 | self); 43 | return YES; 44 | } 45 | 46 | void initAppDel() 47 | { 48 | //Our appDelegate should be NSObject, but if you want to go the hard route, make this a class pair of NSApplication and try initing those awful delegate methods! 49 | AppDelClass = objc_allocateClassPair((Class) 50 | objc_getClass("NSObject"), "AppDelegate", 0); 51 | //Change the implementation of applicationDidFinishLaunching: so we don't have to use ObjC when this is called by the system. 52 | class_addMethod(AppDelClass, 53 | sel_getUid("applicationDidFinishLaunching:"), 54 | (IMP) AppDel_didFinishLaunching, "i@:@"); 55 | 56 | objc_registerClassPair(AppDelClass); 57 | } 58 | 59 | void init_app(void) 60 | { 61 | objc_msgSend( 62 | objc_getClass("NSApplication"), 63 | sel_getUid("sharedApplication")); 64 | 65 | if (NSApp == NULL) 66 | { 67 | fprintf(stderr,"Failed to initialized NSApplication... terminating...\n"); 68 | return; 69 | } 70 | 71 | id appDelObj = objc_msgSend( 72 | objc_getClass("AppDelegate"), 73 | sel_getUid("alloc")); 74 | appDelObj = objc_msgSend(appDelObj, sel_getUid("init")); 75 | 76 | objc_msgSend(NSApp, sel_getUid("setDelegate:"), appDelObj); 77 | objc_msgSend(NSApp, sel_getUid("run")); 78 | } 79 | 80 | -------------------------------------------------------------------------------- /example code/1. PureC/PureC/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "mac", 5 | "size" : "16x16", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "mac", 10 | "size" : "16x16", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "mac", 15 | "size" : "32x32", 16 | "scale" : "1x" 17 | }, 18 | { 19 | "idiom" : "mac", 20 | "size" : "32x32", 21 | "scale" : "2x" 22 | }, 23 | { 24 | "idiom" : "mac", 25 | "size" : "128x128", 26 | "scale" : "1x" 27 | }, 28 | { 29 | "idiom" : "mac", 30 | "size" : "128x128", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "idiom" : "mac", 35 | "size" : "256x256", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "mac", 40 | "size" : "256x256", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "mac", 45 | "size" : "512x512", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "mac", 50 | "size" : "512x512", 51 | "scale" : "2x" 52 | } 53 | ], 54 | "info" : { 55 | "version" : 1, 56 | "author" : "xcode" 57 | } 58 | } -------------------------------------------------------------------------------- /example code/1. PureC/PureC/PureC-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | org.inferis.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSMinimumSystemVersion 26 | ${MACOSX_DEPLOYMENT_TARGET} 27 | NSHumanReadableCopyright 28 | Copyright © 2013 Tom Adriaenssen. All rights reserved. 29 | NSMainNibFile 30 | MainMenu 31 | NSPrincipalClass 32 | NSApplication 33 | 34 | 35 | -------------------------------------------------------------------------------- /example code/1. PureC/PureC/PureC-Prefix.pch: -------------------------------------------------------------------------------- 1 | 2 | #ifdef __OBJC__ 3 | #import 4 | #import 5 | #endif -------------------------------------------------------------------------------- /example code/1. PureC/PureC/View.m: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | // This is a strong reference to the class of our custom view, 6 | // In case we need it in the future. 7 | Class ViewClass; 8 | 9 | 10 | // This is a simple -drawRect implementation for our class. We could have 11 | // used a UILabel or something of that sort instead, but I felt that this 12 | // stuck with the C-based mentality of the application. 13 | void View_drawRect(id self, SEL _cmd, CGRect rect) 14 | { 15 | //make a red NSColor object with its convenience method 16 | id red = objc_msgSend(objc_getClass("NSColor"), sel_getUid("redColor")); 17 | 18 | // fill target rect with red, because this is it! 19 | NSRect rect1 = NSMakeRect ( 21,21,210,210 ); 20 | objc_msgSend(red, sel_getUid("set")); 21 | NSRectFill ( rect1 ); 22 | } 23 | 24 | // Once again we use the (constructor) attribute. generally speaking, 25 | // having many of these is a very bad idea, but in a small application 26 | // like this, it really shouldn't be that big of an issue. 27 | __attribute__((constructor)) 28 | static void initView() 29 | { 30 | 31 | // Once again, just like the app delegate, we tell the runtime to 32 | // create a new class, this time a subclass of 'UIView' and named 'View'. 33 | ViewClass = objc_allocateClassPair((Class) objc_getClass("NSView"), "View", 0); 34 | 35 | // and again, we tell the runtime to add a function called -drawRect: 36 | // to our custom view. Note that there is an error in the type-specification 37 | // of this method, as I do not know the @encode sequence of 'CGRect' off 38 | // of the top of my head. As a result, there is a chance that the rect 39 | // parameter of the method may not get passed properly. 40 | class_addMethod(ViewClass, sel_getUid("drawRect:"), (IMP) View_drawRect, "v@:"); 41 | 42 | // And again, we tell the runtime that this class is now valid to be used. 43 | // At this point, the application should run and display the screenshot shown below. 44 | objc_registerClassPair(ViewClass); 45 | } -------------------------------------------------------------------------------- /example code/1. PureC/PureC/en.lproj/Credits.rtf: -------------------------------------------------------------------------------- 1 | {\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;} 2 | {\colortbl;\red255\green255\blue255;} 3 | \paperw9840\paperh8400 4 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural 5 | 6 | \f0\b\fs24 \cf0 Engineering: 7 | \b0 \ 8 | Some people\ 9 | \ 10 | 11 | \b Human Interface Design: 12 | \b0 \ 13 | Some other people\ 14 | \ 15 | 16 | \b Testing: 17 | \b0 \ 18 | Hopefully not nobody\ 19 | \ 20 | 21 | \b Documentation: 22 | \b0 \ 23 | Whoever\ 24 | \ 25 | 26 | \b With special thanks to: 27 | \b0 \ 28 | Mom\ 29 | } 30 | -------------------------------------------------------------------------------- /example code/1. PureC/PureC/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /example code/1. PureC/PureC/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // PureC 4 | // 5 | // Created by Tom Adriaenssen on 03/12/13. 6 | // Copyright (c) 2013 Tom Adriaenssen. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | //there doesn't need to be a main.m because of this little beauty here. 13 | int main(int argc, char** argv) 14 | { 15 | //Initialize a valid app delegate object just like [NSApplication sharedApplication]; 16 | initAppDel(); 17 | //Initialize the run loop, just like [NSApp run]; this function NEVER returns until the app closes successfully. 18 | init_app(); 19 | //We should close acceptably. 20 | return EXIT_SUCCESS; 21 | } -------------------------------------------------------------------------------- /example code/1. PureC/PureCTests/PureCTests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | org.inferis.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /example code/1. PureC/PureCTests/PureCTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // PureCTests.m 3 | // PureCTests 4 | // 5 | // Created by Tom Adriaenssen on 03/12/13. 6 | // Copyright (c) 2013 Tom Adriaenssen. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface PureCTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation PureCTests 16 | 17 | - (void)setUp 18 | { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown 24 | { 25 | // Put teardown code here. This method is called after the invocation of each test method in the class. 26 | [super tearDown]; 27 | } 28 | 29 | - (void)testExample 30 | { 31 | XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__); 32 | } 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /example code/1. PureC/PureCTests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /example code/1. PureC/README.md: -------------------------------------------------------------------------------- 1 | This was taken from a Stackoverflow post: 2 | 3 | http://stackoverflow.com/questions/10289890/how-to-write-ios-app-purely-in-c 4 | 5 | Many thanks to Richard J. Ross III and CodaFi for providing this code. 6 | This code sample is the "mac port". -------------------------------------------------------------------------------- /example code/2. ObjCSimple/ObjCSimple.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | E2985D71184E1A7E0085DC5D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = E2985D70184E1A7E0085DC5D /* main.m */; }; 11 | /* End PBXBuildFile section */ 12 | 13 | /* Begin PBXCopyFilesBuildPhase section */ 14 | E2985D6B184E1A7D0085DC5D /* CopyFiles */ = { 15 | isa = PBXCopyFilesBuildPhase; 16 | buildActionMask = 2147483647; 17 | dstPath = /usr/share/man/man1/; 18 | dstSubfolderSpec = 0; 19 | files = ( 20 | ); 21 | runOnlyForDeploymentPostprocessing = 1; 22 | }; 23 | /* End PBXCopyFilesBuildPhase section */ 24 | 25 | /* Begin PBXFileReference section */ 26 | E2985D6D184E1A7D0085DC5D /* ObjCSimple */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ObjCSimple; sourceTree = BUILT_PRODUCTS_DIR; }; 27 | E2985D70184E1A7E0085DC5D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 28 | /* End PBXFileReference section */ 29 | 30 | /* Begin PBXFrameworksBuildPhase section */ 31 | E2985D6A184E1A7D0085DC5D /* Frameworks */ = { 32 | isa = PBXFrameworksBuildPhase; 33 | buildActionMask = 2147483647; 34 | files = ( 35 | ); 36 | runOnlyForDeploymentPostprocessing = 0; 37 | }; 38 | /* End PBXFrameworksBuildPhase section */ 39 | 40 | /* Begin PBXGroup section */ 41 | E2985D64184E1A7D0085DC5D = { 42 | isa = PBXGroup; 43 | children = ( 44 | E2985D6F184E1A7D0085DC5D /* ObjCSimple */, 45 | E2985D6E184E1A7D0085DC5D /* Products */, 46 | ); 47 | sourceTree = ""; 48 | }; 49 | E2985D6E184E1A7D0085DC5D /* Products */ = { 50 | isa = PBXGroup; 51 | children = ( 52 | E2985D6D184E1A7D0085DC5D /* ObjCSimple */, 53 | ); 54 | name = Products; 55 | sourceTree = ""; 56 | }; 57 | E2985D6F184E1A7D0085DC5D /* ObjCSimple */ = { 58 | isa = PBXGroup; 59 | children = ( 60 | E2985D70184E1A7E0085DC5D /* main.m */, 61 | ); 62 | path = ObjCSimple; 63 | sourceTree = ""; 64 | }; 65 | /* End PBXGroup section */ 66 | 67 | /* Begin PBXNativeTarget section */ 68 | E2985D6C184E1A7D0085DC5D /* ObjCSimple */ = { 69 | isa = PBXNativeTarget; 70 | buildConfigurationList = E2985D76184E1A7E0085DC5D /* Build configuration list for PBXNativeTarget "ObjCSimple" */; 71 | buildPhases = ( 72 | E2985D69184E1A7D0085DC5D /* Sources */, 73 | E2985D6A184E1A7D0085DC5D /* Frameworks */, 74 | E2985D6B184E1A7D0085DC5D /* CopyFiles */, 75 | ); 76 | buildRules = ( 77 | ); 78 | dependencies = ( 79 | ); 80 | name = ObjCSimple; 81 | productName = ObjCSimple; 82 | productReference = E2985D6D184E1A7D0085DC5D /* ObjCSimple */; 83 | productType = "com.apple.product-type.tool"; 84 | }; 85 | /* End PBXNativeTarget section */ 86 | 87 | /* Begin PBXProject section */ 88 | E2985D65184E1A7D0085DC5D /* Project object */ = { 89 | isa = PBXProject; 90 | attributes = { 91 | LastUpgradeCheck = 0500; 92 | ORGANIZATIONNAME = "Tom Adriaenssen"; 93 | }; 94 | buildConfigurationList = E2985D68184E1A7D0085DC5D /* Build configuration list for PBXProject "ObjCSimple" */; 95 | compatibilityVersion = "Xcode 3.2"; 96 | developmentRegion = English; 97 | hasScannedForEncodings = 0; 98 | knownRegions = ( 99 | en, 100 | ); 101 | mainGroup = E2985D64184E1A7D0085DC5D; 102 | productRefGroup = E2985D6E184E1A7D0085DC5D /* Products */; 103 | projectDirPath = ""; 104 | projectRoot = ""; 105 | targets = ( 106 | E2985D6C184E1A7D0085DC5D /* ObjCSimple */, 107 | ); 108 | }; 109 | /* End PBXProject section */ 110 | 111 | /* Begin PBXSourcesBuildPhase section */ 112 | E2985D69184E1A7D0085DC5D /* Sources */ = { 113 | isa = PBXSourcesBuildPhase; 114 | buildActionMask = 2147483647; 115 | files = ( 116 | E2985D71184E1A7E0085DC5D /* main.m in Sources */, 117 | ); 118 | runOnlyForDeploymentPostprocessing = 0; 119 | }; 120 | /* End PBXSourcesBuildPhase section */ 121 | 122 | /* Begin XCBuildConfiguration section */ 123 | E2985D74184E1A7E0085DC5D /* Debug */ = { 124 | isa = XCBuildConfiguration; 125 | buildSettings = { 126 | ALWAYS_SEARCH_USER_PATHS = NO; 127 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 128 | CLANG_CXX_LIBRARY = "libc++"; 129 | CLANG_ENABLE_OBJC_ARC = YES; 130 | CLANG_WARN_BOOL_CONVERSION = YES; 131 | CLANG_WARN_CONSTANT_CONVERSION = YES; 132 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 133 | CLANG_WARN_EMPTY_BODY = YES; 134 | CLANG_WARN_ENUM_CONVERSION = YES; 135 | CLANG_WARN_INT_CONVERSION = YES; 136 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 137 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 138 | COPY_PHASE_STRIP = NO; 139 | GCC_C_LANGUAGE_STANDARD = gnu99; 140 | GCC_DYNAMIC_NO_PIC = NO; 141 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 142 | GCC_OPTIMIZATION_LEVEL = 0; 143 | GCC_PREPROCESSOR_DEFINITIONS = ( 144 | "DEBUG=1", 145 | "$(inherited)", 146 | ); 147 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 148 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 149 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 150 | GCC_WARN_UNDECLARED_SELECTOR = YES; 151 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 152 | GCC_WARN_UNUSED_FUNCTION = YES; 153 | GCC_WARN_UNUSED_VARIABLE = YES; 154 | MACOSX_DEPLOYMENT_TARGET = 10.9; 155 | ONLY_ACTIVE_ARCH = YES; 156 | SDKROOT = macosx; 157 | }; 158 | name = Debug; 159 | }; 160 | E2985D75184E1A7E0085DC5D /* Release */ = { 161 | isa = XCBuildConfiguration; 162 | buildSettings = { 163 | ALWAYS_SEARCH_USER_PATHS = NO; 164 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 165 | CLANG_CXX_LIBRARY = "libc++"; 166 | CLANG_ENABLE_OBJC_ARC = YES; 167 | CLANG_WARN_BOOL_CONVERSION = YES; 168 | CLANG_WARN_CONSTANT_CONVERSION = YES; 169 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 170 | CLANG_WARN_EMPTY_BODY = YES; 171 | CLANG_WARN_ENUM_CONVERSION = YES; 172 | CLANG_WARN_INT_CONVERSION = YES; 173 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 174 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 175 | COPY_PHASE_STRIP = YES; 176 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 177 | ENABLE_NS_ASSERTIONS = NO; 178 | GCC_C_LANGUAGE_STANDARD = gnu99; 179 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 180 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 181 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 182 | GCC_WARN_UNDECLARED_SELECTOR = YES; 183 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 184 | GCC_WARN_UNUSED_FUNCTION = YES; 185 | GCC_WARN_UNUSED_VARIABLE = YES; 186 | MACOSX_DEPLOYMENT_TARGET = 10.9; 187 | SDKROOT = macosx; 188 | }; 189 | name = Release; 190 | }; 191 | E2985D77184E1A7E0085DC5D /* Debug */ = { 192 | isa = XCBuildConfiguration; 193 | buildSettings = { 194 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 195 | CLANG_ENABLE_OBJC_ARC = NO; 196 | PRODUCT_NAME = "$(TARGET_NAME)"; 197 | }; 198 | name = Debug; 199 | }; 200 | E2985D78184E1A7E0085DC5D /* Release */ = { 201 | isa = XCBuildConfiguration; 202 | buildSettings = { 203 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 204 | CLANG_ENABLE_OBJC_ARC = NO; 205 | PRODUCT_NAME = "$(TARGET_NAME)"; 206 | }; 207 | name = Release; 208 | }; 209 | /* End XCBuildConfiguration section */ 210 | 211 | /* Begin XCConfigurationList section */ 212 | E2985D68184E1A7D0085DC5D /* Build configuration list for PBXProject "ObjCSimple" */ = { 213 | isa = XCConfigurationList; 214 | buildConfigurations = ( 215 | E2985D74184E1A7E0085DC5D /* Debug */, 216 | E2985D75184E1A7E0085DC5D /* Release */, 217 | ); 218 | defaultConfigurationIsVisible = 0; 219 | defaultConfigurationName = Release; 220 | }; 221 | E2985D76184E1A7E0085DC5D /* Build configuration list for PBXNativeTarget "ObjCSimple" */ = { 222 | isa = XCConfigurationList; 223 | buildConfigurations = ( 224 | E2985D77184E1A7E0085DC5D /* Debug */, 225 | E2985D78184E1A7E0085DC5D /* Release */, 226 | ); 227 | defaultConfigurationIsVisible = 0; 228 | }; 229 | /* End XCConfigurationList section */ 230 | }; 231 | rootObject = E2985D65184E1A7D0085DC5D /* Project object */; 232 | } 233 | -------------------------------------------------------------------------------- /example code/2. ObjCSimple/ObjCSimple/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.c 3 | // ObjCSimple 4 | // 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | @protocol Ohai 11 | 12 | - (NSString*)ohai; 13 | - (void)kthxbye; 14 | 15 | @end 16 | 17 | @interface A : NSObject { 18 | @public NSUInteger a; 19 | } 20 | @end 21 | @implementation A 22 | @end 23 | 24 | @interface B : A { 25 | @public NSUInteger b; 26 | } 27 | @end 28 | @implementation B 29 | 30 | - (NSString*)ohai { 31 | return @"OHAI"; 32 | } 33 | 34 | @end 35 | 36 | @interface C : B { 37 | @public NSUInteger c; 38 | } @end 39 | @implementation C 40 | 41 | 42 | @end 43 | 44 | 45 | int main(int argc, char **argv) 46 | { 47 | C *cobj = [[C alloc] init]; 48 | cobj->a = 0xaaaaaaaa; 49 | cobj->b = 0xbbbbbbbb; 50 | cobj->c = 0xcccccccc; 51 | 52 | B *bobj = [[B alloc] init]; 53 | 54 | NSData *objData = [NSData dataWithBytes:(__bridge void*)cobj length:malloc_size((__bridge void*)cobj)]; 55 | NSLog(@"cobj contains %@", objData); 56 | [objData release]; 57 | 58 | // class, superclass 59 | NSLog(@"%@ isa %@ isa %@ isa %@", 60 | [C class], 61 | [C superclass], 62 | [[C superclass] superclass], 63 | [[[C superclass] superclass] superclass]); 64 | NSLog(@"%@ is subclass of %@ -> %@", [C class], [A class], [[C class] isSubclassOfClass:[A class]] ? @"YES" : @"NO"); 65 | NSLog(@"%@ is subclass of %@ -> %@", [A class], [C class], [[A class] isSubclassOfClass:[C class]] ? @"YES" : @"NO"); 66 | 67 | // isKindOfClass 68 | NSLog(@"cobj isKindOfClass:A -> %@", [cobj isKindOfClass:[A class]] ? @"YES" : @"NO"); 69 | NSLog(@"cobj isMemberOfClass:A -> %@", [cobj isMemberOfClass:[A class]] ? @"YES" : @"NO"); 70 | NSLog(@"cobj isKindOfClass:C -> %@", [cobj isKindOfClass:[C class]] ? @"YES" : @"NO"); 71 | NSLog(@"cobj isMemberOfClass:C -> %@", [cobj isMemberOfClass:[C class]] ? @"YES" : @"NO"); 72 | 73 | // protocols/selectors 74 | NSLog(@"cobj conformsTo:Greeting -> %@", [cobj conformsToProtocol:@protocol(Ohai)] ? @"YES" : @"NO"); 75 | NSLog(@"cobj respondsToSelector:ohai -> %@", [cobj respondsToSelector:@selector(ohai)] ? @"YES" : @"NO"); 76 | NSLog(@"cobj respondsToSelector:kthxbye -> %@", [cobj respondsToSelector:@selector(kthxbye)] ? @"YES" : @"NO"); 77 | NSLog(@"A instances respondToSelector:ohai -> %@", [[A class] instancesRespondToSelector:@selector(ohai)] ? @"YES" : @"NO"); 78 | NSLog(@"B instances respondToSelector:ohai -> %@", [[B class] instancesRespondToSelector:@selector(ohai)] ? @"YES" : @"NO"); 79 | NSLog(@"B instances respondToSelector:kthxbye -> %@", [[B class] instancesRespondToSelector:@selector(kthxbye)] ? @"YES" : @"NO"); 80 | NSLog(@"cobj performSelector:ohai -> %@", [cobj performSelector:@selector(ohai)]); 81 | 82 | [cobj release]; 83 | 84 | return 0; 85 | } -------------------------------------------------------------------------------- /example code/3. ObjCDynamicResolve/ObjCDynamicResolve.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | E2985D7B184E2EFD0085DC5D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = E2985D7A184E2EFD0085DC5D /* main.m */; }; 11 | /* End PBXBuildFile section */ 12 | 13 | /* Begin PBXCopyFilesBuildPhase section */ 14 | E2985D6B184E1A7D0085DC5D /* CopyFiles */ = { 15 | isa = PBXCopyFilesBuildPhase; 16 | buildActionMask = 2147483647; 17 | dstPath = /usr/share/man/man1/; 18 | dstSubfolderSpec = 0; 19 | files = ( 20 | ); 21 | runOnlyForDeploymentPostprocessing = 1; 22 | }; 23 | /* End PBXCopyFilesBuildPhase section */ 24 | 25 | /* Begin PBXFileReference section */ 26 | E2985D6D184E1A7D0085DC5D /* ObjCDynamicResolve */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ObjCDynamicResolve; sourceTree = BUILT_PRODUCTS_DIR; }; 27 | E2985D7A184E2EFD0085DC5D /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 28 | /* End PBXFileReference section */ 29 | 30 | /* Begin PBXFrameworksBuildPhase section */ 31 | E2985D6A184E1A7D0085DC5D /* Frameworks */ = { 32 | isa = PBXFrameworksBuildPhase; 33 | buildActionMask = 2147483647; 34 | files = ( 35 | ); 36 | runOnlyForDeploymentPostprocessing = 0; 37 | }; 38 | /* End PBXFrameworksBuildPhase section */ 39 | 40 | /* Begin PBXGroup section */ 41 | E2985D64184E1A7D0085DC5D = { 42 | isa = PBXGroup; 43 | children = ( 44 | E2985D79184E2EFD0085DC5D /* ObjCDynamicResolve */, 45 | E2985D6E184E1A7D0085DC5D /* Products */, 46 | ); 47 | sourceTree = ""; 48 | }; 49 | E2985D6E184E1A7D0085DC5D /* Products */ = { 50 | isa = PBXGroup; 51 | children = ( 52 | E2985D6D184E1A7D0085DC5D /* ObjCDynamicResolve */, 53 | ); 54 | name = Products; 55 | sourceTree = ""; 56 | }; 57 | E2985D79184E2EFD0085DC5D /* ObjCDynamicResolve */ = { 58 | isa = PBXGroup; 59 | children = ( 60 | E2985D7A184E2EFD0085DC5D /* main.m */, 61 | ); 62 | path = ObjCDynamicResolve; 63 | sourceTree = ""; 64 | }; 65 | /* End PBXGroup section */ 66 | 67 | /* Begin PBXNativeTarget section */ 68 | E2985D6C184E1A7D0085DC5D /* ObjCDynamicResolve */ = { 69 | isa = PBXNativeTarget; 70 | buildConfigurationList = E2985D76184E1A7E0085DC5D /* Build configuration list for PBXNativeTarget "ObjCDynamicResolve" */; 71 | buildPhases = ( 72 | E2985D69184E1A7D0085DC5D /* Sources */, 73 | E2985D6A184E1A7D0085DC5D /* Frameworks */, 74 | E2985D6B184E1A7D0085DC5D /* CopyFiles */, 75 | ); 76 | buildRules = ( 77 | ); 78 | dependencies = ( 79 | ); 80 | name = ObjCDynamicResolve; 81 | productName = ObjCSimple; 82 | productReference = E2985D6D184E1A7D0085DC5D /* ObjCDynamicResolve */; 83 | productType = "com.apple.product-type.tool"; 84 | }; 85 | /* End PBXNativeTarget section */ 86 | 87 | /* Begin PBXProject section */ 88 | E2985D65184E1A7D0085DC5D /* Project object */ = { 89 | isa = PBXProject; 90 | attributes = { 91 | LastUpgradeCheck = 0500; 92 | ORGANIZATIONNAME = "Tom Adriaenssen"; 93 | }; 94 | buildConfigurationList = E2985D68184E1A7D0085DC5D /* Build configuration list for PBXProject "ObjCDynamicResolve" */; 95 | compatibilityVersion = "Xcode 3.2"; 96 | developmentRegion = English; 97 | hasScannedForEncodings = 0; 98 | knownRegions = ( 99 | en, 100 | ); 101 | mainGroup = E2985D64184E1A7D0085DC5D; 102 | productRefGroup = E2985D6E184E1A7D0085DC5D /* Products */; 103 | projectDirPath = ""; 104 | projectRoot = ""; 105 | targets = ( 106 | E2985D6C184E1A7D0085DC5D /* ObjCDynamicResolve */, 107 | ); 108 | }; 109 | /* End PBXProject section */ 110 | 111 | /* Begin PBXSourcesBuildPhase section */ 112 | E2985D69184E1A7D0085DC5D /* Sources */ = { 113 | isa = PBXSourcesBuildPhase; 114 | buildActionMask = 2147483647; 115 | files = ( 116 | E2985D7B184E2EFD0085DC5D /* main.m in Sources */, 117 | ); 118 | runOnlyForDeploymentPostprocessing = 0; 119 | }; 120 | /* End PBXSourcesBuildPhase section */ 121 | 122 | /* Begin XCBuildConfiguration section */ 123 | E2985D74184E1A7E0085DC5D /* Debug */ = { 124 | isa = XCBuildConfiguration; 125 | buildSettings = { 126 | ALWAYS_SEARCH_USER_PATHS = NO; 127 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 128 | CLANG_CXX_LIBRARY = "libc++"; 129 | CLANG_ENABLE_OBJC_ARC = YES; 130 | CLANG_WARN_BOOL_CONVERSION = YES; 131 | CLANG_WARN_CONSTANT_CONVERSION = YES; 132 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 133 | CLANG_WARN_EMPTY_BODY = YES; 134 | CLANG_WARN_ENUM_CONVERSION = YES; 135 | CLANG_WARN_INT_CONVERSION = YES; 136 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 137 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 138 | COPY_PHASE_STRIP = NO; 139 | GCC_C_LANGUAGE_STANDARD = gnu99; 140 | GCC_DYNAMIC_NO_PIC = NO; 141 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 142 | GCC_OPTIMIZATION_LEVEL = 0; 143 | GCC_PREPROCESSOR_DEFINITIONS = ( 144 | "DEBUG=1", 145 | "$(inherited)", 146 | ); 147 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 148 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 149 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 150 | GCC_WARN_UNDECLARED_SELECTOR = YES; 151 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 152 | GCC_WARN_UNUSED_FUNCTION = YES; 153 | GCC_WARN_UNUSED_VARIABLE = YES; 154 | MACOSX_DEPLOYMENT_TARGET = 10.9; 155 | ONLY_ACTIVE_ARCH = YES; 156 | SDKROOT = macosx; 157 | }; 158 | name = Debug; 159 | }; 160 | E2985D75184E1A7E0085DC5D /* Release */ = { 161 | isa = XCBuildConfiguration; 162 | buildSettings = { 163 | ALWAYS_SEARCH_USER_PATHS = NO; 164 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 165 | CLANG_CXX_LIBRARY = "libc++"; 166 | CLANG_ENABLE_OBJC_ARC = YES; 167 | CLANG_WARN_BOOL_CONVERSION = YES; 168 | CLANG_WARN_CONSTANT_CONVERSION = YES; 169 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 170 | CLANG_WARN_EMPTY_BODY = YES; 171 | CLANG_WARN_ENUM_CONVERSION = YES; 172 | CLANG_WARN_INT_CONVERSION = YES; 173 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 174 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 175 | COPY_PHASE_STRIP = YES; 176 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 177 | ENABLE_NS_ASSERTIONS = NO; 178 | GCC_C_LANGUAGE_STANDARD = gnu99; 179 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 180 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 181 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 182 | GCC_WARN_UNDECLARED_SELECTOR = YES; 183 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 184 | GCC_WARN_UNUSED_FUNCTION = YES; 185 | GCC_WARN_UNUSED_VARIABLE = YES; 186 | MACOSX_DEPLOYMENT_TARGET = 10.9; 187 | SDKROOT = macosx; 188 | }; 189 | name = Release; 190 | }; 191 | E2985D77184E1A7E0085DC5D /* Debug */ = { 192 | isa = XCBuildConfiguration; 193 | buildSettings = { 194 | ARCHS = "$(ARCHS_STANDARD)"; 195 | CLANG_ENABLE_OBJC_ARC = NO; 196 | PRODUCT_NAME = ObjCDynamicResolve; 197 | }; 198 | name = Debug; 199 | }; 200 | E2985D78184E1A7E0085DC5D /* Release */ = { 201 | isa = XCBuildConfiguration; 202 | buildSettings = { 203 | ARCHS = "$(ARCHS_STANDARD)"; 204 | CLANG_ENABLE_OBJC_ARC = NO; 205 | PRODUCT_NAME = ObjCDynamicResolve; 206 | }; 207 | name = Release; 208 | }; 209 | /* End XCBuildConfiguration section */ 210 | 211 | /* Begin XCConfigurationList section */ 212 | E2985D68184E1A7D0085DC5D /* Build configuration list for PBXProject "ObjCDynamicResolve" */ = { 213 | isa = XCConfigurationList; 214 | buildConfigurations = ( 215 | E2985D74184E1A7E0085DC5D /* Debug */, 216 | E2985D75184E1A7E0085DC5D /* Release */, 217 | ); 218 | defaultConfigurationIsVisible = 0; 219 | defaultConfigurationName = Release; 220 | }; 221 | E2985D76184E1A7E0085DC5D /* Build configuration list for PBXNativeTarget "ObjCDynamicResolve" */ = { 222 | isa = XCConfigurationList; 223 | buildConfigurations = ( 224 | E2985D77184E1A7E0085DC5D /* Debug */, 225 | E2985D78184E1A7E0085DC5D /* Release */, 226 | ); 227 | defaultConfigurationIsVisible = 0; 228 | defaultConfigurationName = Release; 229 | }; 230 | /* End XCConfigurationList section */ 231 | }; 232 | rootObject = E2985D65184E1A7D0085DC5D /* Project object */; 233 | } 234 | -------------------------------------------------------------------------------- /example code/3. ObjCDynamicResolve/ObjCDynamicResolve/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.c 3 | // ObjCSimple 4 | // 5 | 6 | #include 7 | #include 8 | 9 | @interface A : NSObject 10 | 11 | - (id)initWithDictionary:(NSDictionary*)dictionary; 12 | 13 | 14 | @end 15 | 16 | @interface A (Beu) 17 | 18 | @property (nonatomic, strong) id cocoaheadsbe; 19 | 20 | @end 21 | 22 | @implementation A { 23 | NSMutableDictionary* _dictionary; 24 | } 25 | 26 | - (id)initWithDictionary:(NSDictionary*)dictionary 27 | { 28 | self = [self init]; 29 | if (self) { 30 | _dictionary = [NSMutableDictionary dictionaryWithDictionary:dictionary]; 31 | } 32 | return self; 33 | } 34 | 35 | id getterImplementation(A* self, SEL _cmd) 36 | { 37 | NSString* selName = NSStringFromSelector(_cmd); 38 | return self->_dictionary[[selName lowercaseString]]; 39 | } 40 | 41 | 42 | //+ (BOOL)resolveInstanceMethod:(SEL)sel { 43 | // class_addMethod([self class], sel, (IMP)getterImplementation, "@@:"); 44 | // return YES; 45 | //} 46 | 47 | + (BOOL)resolveInstanceMethod:(SEL)sel { 48 | NSString* selName = NSStringFromSelector(sel); 49 | 50 | if ([selName rangeOfString:@"set"].location == 0) { 51 | // starts with set 52 | IMP imp = imp_implementationWithBlock(^(A* self, id value) { 53 | NSString* key = [[selName substringWithRange:NSMakeRange(3, selName.length-4)] lowercaseString]; 54 | self->_dictionary[key] = value; 55 | }); 56 | class_addMethod([self class], sel, imp, "v@:@"); 57 | NSLog(@"adding setter method %@ to %@ with a block IMP", selName, self); 58 | } 59 | else { 60 | NSLog(@"adding getter method %@ to %@ with a function IMP", selName, self); 61 | class_addMethod(self, sel, (IMP)getterImplementation, "@@:"); 62 | } 63 | 64 | return YES; 65 | } 66 | 67 | @end 68 | 69 | 70 | int main(int argc, char **argv) 71 | { 72 | A* obj = [[A alloc] initWithDictionary:@{@"cocoaheadsbe": @"represent"}]; 73 | 74 | NSLog(@"cocoaheads value = %@", [obj cocoaheadsbe]); 75 | [obj setCocoaheadsbe:@"where are those little hands"]; 76 | NSLog(@"cocoaheads value = %@", [obj cocoaheadsbe]); 77 | 78 | return 0; 79 | } -------------------------------------------------------------------------------- /example code/4. ObjCForwarding/ObjCForwarding.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | E2985D7E184E38020085DC5D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = E2985D7D184E37050085DC5D /* main.m */; }; 11 | E2985D80184E39BA0085DC5D /* http___cocoaheads_be.html in CopyFiles */ = {isa = PBXBuildFile; fileRef = E2985D7F184E394F0085DC5D /* http___cocoaheads_be.html */; }; 12 | /* End PBXBuildFile section */ 13 | 14 | /* Begin PBXCopyFilesBuildPhase section */ 15 | E2985D6B184E1A7D0085DC5D /* CopyFiles */ = { 16 | isa = PBXCopyFilesBuildPhase; 17 | buildActionMask = 12; 18 | dstPath = ""; 19 | dstSubfolderSpec = 16; 20 | files = ( 21 | E2985D80184E39BA0085DC5D /* http___cocoaheads_be.html in CopyFiles */, 22 | ); 23 | runOnlyForDeploymentPostprocessing = 0; 24 | }; 25 | /* End PBXCopyFilesBuildPhase section */ 26 | 27 | /* Begin PBXFileReference section */ 28 | E2985D6D184E1A7D0085DC5D /* ObjCForwarding */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ObjCForwarding; sourceTree = BUILT_PRODUCTS_DIR; }; 29 | E2985D7D184E37050085DC5D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 30 | E2985D7F184E394F0085DC5D /* http___cocoaheads_be.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "http___cocoaheads_be.html"; sourceTree = ""; }; 31 | /* End PBXFileReference section */ 32 | 33 | /* Begin PBXFrameworksBuildPhase section */ 34 | E2985D6A184E1A7D0085DC5D /* Frameworks */ = { 35 | isa = PBXFrameworksBuildPhase; 36 | buildActionMask = 2147483647; 37 | files = ( 38 | ); 39 | runOnlyForDeploymentPostprocessing = 0; 40 | }; 41 | /* End PBXFrameworksBuildPhase section */ 42 | 43 | /* Begin PBXGroup section */ 44 | E2985D64184E1A7D0085DC5D = { 45 | isa = PBXGroup; 46 | children = ( 47 | E2985D7C184E37050085DC5D /* ObjCForwarding */, 48 | E2985D6E184E1A7D0085DC5D /* Products */, 49 | ); 50 | sourceTree = ""; 51 | }; 52 | E2985D6E184E1A7D0085DC5D /* Products */ = { 53 | isa = PBXGroup; 54 | children = ( 55 | E2985D6D184E1A7D0085DC5D /* ObjCForwarding */, 56 | ); 57 | name = Products; 58 | sourceTree = ""; 59 | }; 60 | E2985D7C184E37050085DC5D /* ObjCForwarding */ = { 61 | isa = PBXGroup; 62 | children = ( 63 | E2985D7D184E37050085DC5D /* main.m */, 64 | E2985D7F184E394F0085DC5D /* http___cocoaheads_be.html */, 65 | ); 66 | path = ObjCForwarding; 67 | sourceTree = ""; 68 | }; 69 | /* End PBXGroup section */ 70 | 71 | /* Begin PBXNativeTarget section */ 72 | E2985D6C184E1A7D0085DC5D /* ObjCForwarding */ = { 73 | isa = PBXNativeTarget; 74 | buildConfigurationList = E2985D76184E1A7E0085DC5D /* Build configuration list for PBXNativeTarget "ObjCForwarding" */; 75 | buildPhases = ( 76 | E2985D69184E1A7D0085DC5D /* Sources */, 77 | E2985D6A184E1A7D0085DC5D /* Frameworks */, 78 | E2985D6B184E1A7D0085DC5D /* CopyFiles */, 79 | ); 80 | buildRules = ( 81 | ); 82 | dependencies = ( 83 | ); 84 | name = ObjCForwarding; 85 | productName = ObjCSimple; 86 | productReference = E2985D6D184E1A7D0085DC5D /* ObjCForwarding */; 87 | productType = "com.apple.product-type.tool"; 88 | }; 89 | /* End PBXNativeTarget section */ 90 | 91 | /* Begin PBXProject section */ 92 | E2985D65184E1A7D0085DC5D /* Project object */ = { 93 | isa = PBXProject; 94 | attributes = { 95 | LastUpgradeCheck = 0500; 96 | ORGANIZATIONNAME = "Tom Adriaenssen"; 97 | }; 98 | buildConfigurationList = E2985D68184E1A7D0085DC5D /* Build configuration list for PBXProject "ObjCForwarding" */; 99 | compatibilityVersion = "Xcode 3.2"; 100 | developmentRegion = English; 101 | hasScannedForEncodings = 0; 102 | knownRegions = ( 103 | en, 104 | ); 105 | mainGroup = E2985D64184E1A7D0085DC5D; 106 | productRefGroup = E2985D6E184E1A7D0085DC5D /* Products */; 107 | projectDirPath = ""; 108 | projectRoot = ""; 109 | targets = ( 110 | E2985D6C184E1A7D0085DC5D /* ObjCForwarding */, 111 | ); 112 | }; 113 | /* End PBXProject section */ 114 | 115 | /* Begin PBXSourcesBuildPhase section */ 116 | E2985D69184E1A7D0085DC5D /* Sources */ = { 117 | isa = PBXSourcesBuildPhase; 118 | buildActionMask = 2147483647; 119 | files = ( 120 | E2985D7E184E38020085DC5D /* main.m in Sources */, 121 | ); 122 | runOnlyForDeploymentPostprocessing = 0; 123 | }; 124 | /* End PBXSourcesBuildPhase section */ 125 | 126 | /* Begin XCBuildConfiguration section */ 127 | E2985D74184E1A7E0085DC5D /* Debug */ = { 128 | isa = XCBuildConfiguration; 129 | buildSettings = { 130 | ALWAYS_SEARCH_USER_PATHS = NO; 131 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 132 | CLANG_CXX_LIBRARY = "libc++"; 133 | CLANG_ENABLE_OBJC_ARC = YES; 134 | CLANG_WARN_BOOL_CONVERSION = YES; 135 | CLANG_WARN_CONSTANT_CONVERSION = YES; 136 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 137 | CLANG_WARN_EMPTY_BODY = YES; 138 | CLANG_WARN_ENUM_CONVERSION = YES; 139 | CLANG_WARN_INT_CONVERSION = YES; 140 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 141 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 142 | COPY_PHASE_STRIP = NO; 143 | GCC_C_LANGUAGE_STANDARD = gnu99; 144 | GCC_DYNAMIC_NO_PIC = NO; 145 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 146 | GCC_OPTIMIZATION_LEVEL = 0; 147 | GCC_PREPROCESSOR_DEFINITIONS = ( 148 | "DEBUG=1", 149 | "$(inherited)", 150 | ); 151 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 152 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 153 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 154 | GCC_WARN_UNDECLARED_SELECTOR = YES; 155 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 156 | GCC_WARN_UNUSED_FUNCTION = YES; 157 | GCC_WARN_UNUSED_VARIABLE = YES; 158 | MACOSX_DEPLOYMENT_TARGET = 10.9; 159 | ONLY_ACTIVE_ARCH = YES; 160 | SDKROOT = macosx; 161 | }; 162 | name = Debug; 163 | }; 164 | E2985D75184E1A7E0085DC5D /* Release */ = { 165 | isa = XCBuildConfiguration; 166 | buildSettings = { 167 | ALWAYS_SEARCH_USER_PATHS = NO; 168 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 169 | CLANG_CXX_LIBRARY = "libc++"; 170 | CLANG_ENABLE_OBJC_ARC = YES; 171 | CLANG_WARN_BOOL_CONVERSION = YES; 172 | CLANG_WARN_CONSTANT_CONVERSION = YES; 173 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 174 | CLANG_WARN_EMPTY_BODY = YES; 175 | CLANG_WARN_ENUM_CONVERSION = YES; 176 | CLANG_WARN_INT_CONVERSION = YES; 177 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 178 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 179 | COPY_PHASE_STRIP = YES; 180 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 181 | ENABLE_NS_ASSERTIONS = NO; 182 | GCC_C_LANGUAGE_STANDARD = gnu99; 183 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 184 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 185 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 186 | GCC_WARN_UNDECLARED_SELECTOR = YES; 187 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 188 | GCC_WARN_UNUSED_FUNCTION = YES; 189 | GCC_WARN_UNUSED_VARIABLE = YES; 190 | MACOSX_DEPLOYMENT_TARGET = 10.9; 191 | SDKROOT = macosx; 192 | }; 193 | name = Release; 194 | }; 195 | E2985D77184E1A7E0085DC5D /* Debug */ = { 196 | isa = XCBuildConfiguration; 197 | buildSettings = { 198 | ARCHS = "$(ARCHS_STANDARD)"; 199 | CLANG_ENABLE_OBJC_ARC = NO; 200 | PRODUCT_NAME = ObjCForwarding; 201 | }; 202 | name = Debug; 203 | }; 204 | E2985D78184E1A7E0085DC5D /* Release */ = { 205 | isa = XCBuildConfiguration; 206 | buildSettings = { 207 | ARCHS = "$(ARCHS_STANDARD)"; 208 | CLANG_ENABLE_OBJC_ARC = NO; 209 | PRODUCT_NAME = ObjCForwarding; 210 | }; 211 | name = Release; 212 | }; 213 | /* End XCBuildConfiguration section */ 214 | 215 | /* Begin XCConfigurationList section */ 216 | E2985D68184E1A7D0085DC5D /* Build configuration list for PBXProject "ObjCForwarding" */ = { 217 | isa = XCConfigurationList; 218 | buildConfigurations = ( 219 | E2985D74184E1A7E0085DC5D /* Debug */, 220 | E2985D75184E1A7E0085DC5D /* Release */, 221 | ); 222 | defaultConfigurationIsVisible = 0; 223 | defaultConfigurationName = Release; 224 | }; 225 | E2985D76184E1A7E0085DC5D /* Build configuration list for PBXNativeTarget "ObjCForwarding" */ = { 226 | isa = XCConfigurationList; 227 | buildConfigurations = ( 228 | E2985D77184E1A7E0085DC5D /* Debug */, 229 | E2985D78184E1A7E0085DC5D /* Release */, 230 | ); 231 | defaultConfigurationIsVisible = 0; 232 | defaultConfigurationName = Release; 233 | }; 234 | /* End XCConfigurationList section */ 235 | }; 236 | rootObject = E2985D65184E1A7D0085DC5D /* Project object */; 237 | } 238 | -------------------------------------------------------------------------------- /example code/4. ObjCForwarding/ObjCForwarding/http___cocoaheads_be.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | YOLO! 4 | 5 | -------------------------------------------------------------------------------- /example code/4. ObjCForwarding/ObjCForwarding/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.c 3 | // ObjCSimple 4 | // 5 | 6 | #include 7 | 8 | @class Curl; 9 | 10 | @interface LocalCurl : NSObject @end 11 | @interface RemoteCurl : NSObject @end 12 | 13 | @interface Curl : NSObject 14 | 15 | @property (nonatomic, assign) BOOL local; 16 | 17 | - (NSString*)fetch:(NSString*)url; 18 | 19 | @end 20 | 21 | @implementation Curl 22 | 23 | - (id)forwardingTargetForSelector:(SEL)aSelector { 24 | return self.local ? (id)[LocalCurl new] : (id)[RemoteCurl new]; 25 | } 26 | 27 | - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector { 28 | NSMethodSignature* signature = [super methodSignatureForSelector:aSelector]; 29 | 30 | if (!signature && aSelector == @selector(fetch:)) { 31 | return [NSMethodSignature signatureWithObjCTypes:"@@:@"]; 32 | } 33 | 34 | return nil; 35 | } 36 | 37 | - (void)forwardInvocation:(NSInvocation *)anInvocation { 38 | id target = self.local ? (id)[LocalCurl new] : (id)[RemoteCurl new]; 39 | [anInvocation invokeWithTarget:target]; 40 | } 41 | 42 | @end 43 | 44 | @implementation LocalCurl 45 | 46 | - (NSString*)fetch:(NSString*)url 47 | { 48 | // sanitize the filename 49 | url = [url stringByReplacingOccurrencesOfString:@":" withString:@"_"]; 50 | url = [url stringByReplacingOccurrencesOfString:@"/" withString:@"_"]; 51 | url = [url stringByReplacingOccurrencesOfString:@"." withString:@"_"]; 52 | 53 | NSString* path = [url stringByAppendingString:@".html"]; 54 | NSLog(@"fetching locally"); 55 | return [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; 56 | } 57 | 58 | @end 59 | 60 | @implementation RemoteCurl 61 | 62 | - (NSString*)fetch:(NSString*)url 63 | { 64 | NSURL* realUrl = [NSURL URLWithString:url]; 65 | NSLog(@"fetching remotely"); 66 | return [NSString stringWithContentsOfURL:realUrl encoding:NSUTF8StringEncoding error:nil]; 67 | } 68 | 69 | @end 70 | 71 | 72 | int main(int argc, char **argv) 73 | { 74 | Curl* curl = [Curl new]; 75 | 76 | curl.local = YES; 77 | NSLog(@"local respondsToSelector:fetch -> %@", [curl respondsToSelector:@selector(fetch:)] ? @"YES" : @"NO"); 78 | NSLog(@"local result = %@", [curl fetch:@"http://cocoaheads.be"]); 79 | 80 | curl.local = NO; 81 | NSLog(@"remote respondsToSelector:fetch -> %@", [curl respondsToSelector:@selector(fetch:)] ? @"YES" : @"NO"); 82 | NSLog(@"remote result = %@", [curl fetch:@"http://cocoaheads.be"]); 83 | 84 | return 0; 85 | } -------------------------------------------------------------------------------- /example code/5. ObjCMethodSwizzling/ObjCMethodSwizzling.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | E2985DC6184E4B630085DC5D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = E2985DC5184E4B600085DC5D /* main.m */; }; 11 | /* End PBXBuildFile section */ 12 | 13 | /* Begin PBXCopyFilesBuildPhase section */ 14 | E2985D6B184E1A7D0085DC5D /* CopyFiles */ = { 15 | isa = PBXCopyFilesBuildPhase; 16 | buildActionMask = 2147483647; 17 | dstPath = /usr/share/man/man1/; 18 | dstSubfolderSpec = 0; 19 | files = ( 20 | ); 21 | runOnlyForDeploymentPostprocessing = 1; 22 | }; 23 | /* End PBXCopyFilesBuildPhase section */ 24 | 25 | /* Begin PBXFileReference section */ 26 | E2985D6D184E1A7D0085DC5D /* ObjCMethodSwizzling */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ObjCMethodSwizzling; sourceTree = BUILT_PRODUCTS_DIR; }; 27 | E2985DC5184E4B600085DC5D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 28 | /* End PBXFileReference section */ 29 | 30 | /* Begin PBXFrameworksBuildPhase section */ 31 | E2985D6A184E1A7D0085DC5D /* Frameworks */ = { 32 | isa = PBXFrameworksBuildPhase; 33 | buildActionMask = 2147483647; 34 | files = ( 35 | ); 36 | runOnlyForDeploymentPostprocessing = 0; 37 | }; 38 | /* End PBXFrameworksBuildPhase section */ 39 | 40 | /* Begin PBXGroup section */ 41 | E2985D64184E1A7D0085DC5D = { 42 | isa = PBXGroup; 43 | children = ( 44 | E2985DC4184E4B600085DC5D /* ObjCMethodSwizzling */, 45 | E2985D6E184E1A7D0085DC5D /* Products */, 46 | ); 47 | sourceTree = ""; 48 | }; 49 | E2985D6E184E1A7D0085DC5D /* Products */ = { 50 | isa = PBXGroup; 51 | children = ( 52 | E2985D6D184E1A7D0085DC5D /* ObjCMethodSwizzling */, 53 | ); 54 | name = Products; 55 | sourceTree = ""; 56 | }; 57 | E2985DC4184E4B600085DC5D /* ObjCMethodSwizzling */ = { 58 | isa = PBXGroup; 59 | children = ( 60 | E2985DC5184E4B600085DC5D /* main.m */, 61 | ); 62 | path = ObjCMethodSwizzling; 63 | sourceTree = ""; 64 | }; 65 | /* End PBXGroup section */ 66 | 67 | /* Begin PBXNativeTarget section */ 68 | E2985D6C184E1A7D0085DC5D /* ObjCMethodSwizzling */ = { 69 | isa = PBXNativeTarget; 70 | buildConfigurationList = E2985D76184E1A7E0085DC5D /* Build configuration list for PBXNativeTarget "ObjCMethodSwizzling" */; 71 | buildPhases = ( 72 | E2985D69184E1A7D0085DC5D /* Sources */, 73 | E2985D6A184E1A7D0085DC5D /* Frameworks */, 74 | E2985D6B184E1A7D0085DC5D /* CopyFiles */, 75 | ); 76 | buildRules = ( 77 | ); 78 | dependencies = ( 79 | ); 80 | name = ObjCMethodSwizzling; 81 | productName = ObjCSimple; 82 | productReference = E2985D6D184E1A7D0085DC5D /* ObjCMethodSwizzling */; 83 | productType = "com.apple.product-type.tool"; 84 | }; 85 | /* End PBXNativeTarget section */ 86 | 87 | /* Begin PBXProject section */ 88 | E2985D65184E1A7D0085DC5D /* Project object */ = { 89 | isa = PBXProject; 90 | attributes = { 91 | LastUpgradeCheck = 0500; 92 | ORGANIZATIONNAME = "Tom Adriaenssen"; 93 | }; 94 | buildConfigurationList = E2985D68184E1A7D0085DC5D /* Build configuration list for PBXProject "ObjCMethodSwizzling" */; 95 | compatibilityVersion = "Xcode 3.2"; 96 | developmentRegion = English; 97 | hasScannedForEncodings = 0; 98 | knownRegions = ( 99 | en, 100 | ); 101 | mainGroup = E2985D64184E1A7D0085DC5D; 102 | productRefGroup = E2985D6E184E1A7D0085DC5D /* Products */; 103 | projectDirPath = ""; 104 | projectRoot = ""; 105 | targets = ( 106 | E2985D6C184E1A7D0085DC5D /* ObjCMethodSwizzling */, 107 | ); 108 | }; 109 | /* End PBXProject section */ 110 | 111 | /* Begin PBXSourcesBuildPhase section */ 112 | E2985D69184E1A7D0085DC5D /* Sources */ = { 113 | isa = PBXSourcesBuildPhase; 114 | buildActionMask = 2147483647; 115 | files = ( 116 | E2985DC6184E4B630085DC5D /* main.m in Sources */, 117 | ); 118 | runOnlyForDeploymentPostprocessing = 0; 119 | }; 120 | /* End PBXSourcesBuildPhase section */ 121 | 122 | /* Begin XCBuildConfiguration section */ 123 | E2985D74184E1A7E0085DC5D /* Debug */ = { 124 | isa = XCBuildConfiguration; 125 | buildSettings = { 126 | ALWAYS_SEARCH_USER_PATHS = NO; 127 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 128 | CLANG_CXX_LIBRARY = "libc++"; 129 | CLANG_ENABLE_OBJC_ARC = YES; 130 | CLANG_WARN_BOOL_CONVERSION = YES; 131 | CLANG_WARN_CONSTANT_CONVERSION = YES; 132 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 133 | CLANG_WARN_EMPTY_BODY = YES; 134 | CLANG_WARN_ENUM_CONVERSION = YES; 135 | CLANG_WARN_INT_CONVERSION = YES; 136 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 137 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 138 | COPY_PHASE_STRIP = NO; 139 | GCC_C_LANGUAGE_STANDARD = gnu99; 140 | GCC_DYNAMIC_NO_PIC = NO; 141 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 142 | GCC_OPTIMIZATION_LEVEL = 0; 143 | GCC_PREPROCESSOR_DEFINITIONS = ( 144 | "DEBUG=1", 145 | "$(inherited)", 146 | ); 147 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 148 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 149 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 150 | GCC_WARN_UNDECLARED_SELECTOR = YES; 151 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 152 | GCC_WARN_UNUSED_FUNCTION = YES; 153 | GCC_WARN_UNUSED_VARIABLE = YES; 154 | MACOSX_DEPLOYMENT_TARGET = 10.9; 155 | ONLY_ACTIVE_ARCH = YES; 156 | SDKROOT = macosx; 157 | }; 158 | name = Debug; 159 | }; 160 | E2985D75184E1A7E0085DC5D /* Release */ = { 161 | isa = XCBuildConfiguration; 162 | buildSettings = { 163 | ALWAYS_SEARCH_USER_PATHS = NO; 164 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 165 | CLANG_CXX_LIBRARY = "libc++"; 166 | CLANG_ENABLE_OBJC_ARC = YES; 167 | CLANG_WARN_BOOL_CONVERSION = YES; 168 | CLANG_WARN_CONSTANT_CONVERSION = YES; 169 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 170 | CLANG_WARN_EMPTY_BODY = YES; 171 | CLANG_WARN_ENUM_CONVERSION = YES; 172 | CLANG_WARN_INT_CONVERSION = YES; 173 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 174 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 175 | COPY_PHASE_STRIP = YES; 176 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 177 | ENABLE_NS_ASSERTIONS = NO; 178 | GCC_C_LANGUAGE_STANDARD = gnu99; 179 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 180 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 181 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 182 | GCC_WARN_UNDECLARED_SELECTOR = YES; 183 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 184 | GCC_WARN_UNUSED_FUNCTION = YES; 185 | GCC_WARN_UNUSED_VARIABLE = YES; 186 | MACOSX_DEPLOYMENT_TARGET = 10.9; 187 | SDKROOT = macosx; 188 | }; 189 | name = Release; 190 | }; 191 | E2985D77184E1A7E0085DC5D /* Debug */ = { 192 | isa = XCBuildConfiguration; 193 | buildSettings = { 194 | ARCHS = "$(ARCHS_STANDARD)"; 195 | CLANG_ENABLE_OBJC_ARC = NO; 196 | PRODUCT_NAME = ObjCMethodSwizzling; 197 | }; 198 | name = Debug; 199 | }; 200 | E2985D78184E1A7E0085DC5D /* Release */ = { 201 | isa = XCBuildConfiguration; 202 | buildSettings = { 203 | ARCHS = "$(ARCHS_STANDARD)"; 204 | CLANG_ENABLE_OBJC_ARC = NO; 205 | PRODUCT_NAME = ObjCMethodSwizzling; 206 | }; 207 | name = Release; 208 | }; 209 | /* End XCBuildConfiguration section */ 210 | 211 | /* Begin XCConfigurationList section */ 212 | E2985D68184E1A7D0085DC5D /* Build configuration list for PBXProject "ObjCMethodSwizzling" */ = { 213 | isa = XCConfigurationList; 214 | buildConfigurations = ( 215 | E2985D74184E1A7E0085DC5D /* Debug */, 216 | E2985D75184E1A7E0085DC5D /* Release */, 217 | ); 218 | defaultConfigurationIsVisible = 0; 219 | defaultConfigurationName = Release; 220 | }; 221 | E2985D76184E1A7E0085DC5D /* Build configuration list for PBXNativeTarget "ObjCMethodSwizzling" */ = { 222 | isa = XCConfigurationList; 223 | buildConfigurations = ( 224 | E2985D77184E1A7E0085DC5D /* Debug */, 225 | E2985D78184E1A7E0085DC5D /* Release */, 226 | ); 227 | defaultConfigurationIsVisible = 0; 228 | defaultConfigurationName = Release; 229 | }; 230 | /* End XCConfigurationList section */ 231 | }; 232 | rootObject = E2985D65184E1A7D0085DC5D /* Project object */; 233 | } 234 | -------------------------------------------------------------------------------- /example code/5. ObjCMethodSwizzling/ObjCMethodSwizzling/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.c 3 | // ObjCSimple 4 | // 5 | 6 | #include 7 | #include 8 | 9 | @interface A : NSObject 10 | 11 | - (NSString*)ohai; 12 | - (NSString *)french_ohai; 13 | - (void)becomeFrenchie; 14 | 15 | @end 16 | 17 | @implementation A 18 | 19 | - (NSString *)ohai { 20 | return @"ohai"; 21 | } 22 | 23 | - (NSString *)french_ohai { 24 | return @"le ohai"; 25 | } 26 | 27 | - (void)becomeFrenchie { 28 | Method orig = class_getInstanceMethod([self class], @selector(ohai)); 29 | Method french = class_getInstanceMethod([self class], @selector(french_ohai)); 30 | method_exchangeImplementations(orig, french); 31 | NSLog(@"Feeling swizzly!"); 32 | } 33 | 34 | @end 35 | 36 | int main(int argc, char **argv) 37 | { 38 | A* obj = [A new]; 39 | NSLog(@"not swizzled: %@ (in french: %@)", [obj ohai], [obj french_ohai]); 40 | [obj becomeFrenchie]; 41 | NSLog(@"swizzled: %@ (in french: %@)", [obj ohai], [obj french_ohai]); 42 | [obj becomeFrenchie]; 43 | NSLog(@"unswizzled: %@ (in french: %@)", [obj ohai], [obj french_ohai]); 44 | } -------------------------------------------------------------------------------- /example code/6. ObjCClassSwizzling/ObjCClassSwizzling.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | E2985DC9184E4CE00085DC5D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = E2985DC8184E4CE00085DC5D /* main.m */; }; 11 | /* End PBXBuildFile section */ 12 | 13 | /* Begin PBXCopyFilesBuildPhase section */ 14 | E2985D6B184E1A7D0085DC5D /* CopyFiles */ = { 15 | isa = PBXCopyFilesBuildPhase; 16 | buildActionMask = 2147483647; 17 | dstPath = /usr/share/man/man1/; 18 | dstSubfolderSpec = 0; 19 | files = ( 20 | ); 21 | runOnlyForDeploymentPostprocessing = 1; 22 | }; 23 | /* End PBXCopyFilesBuildPhase section */ 24 | 25 | /* Begin PBXFileReference section */ 26 | E2985D6D184E1A7D0085DC5D /* ObjCClassSwizzling */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ObjCClassSwizzling; sourceTree = BUILT_PRODUCTS_DIR; }; 27 | E2985DC8184E4CE00085DC5D /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 28 | /* End PBXFileReference section */ 29 | 30 | /* Begin PBXFrameworksBuildPhase section */ 31 | E2985D6A184E1A7D0085DC5D /* Frameworks */ = { 32 | isa = PBXFrameworksBuildPhase; 33 | buildActionMask = 2147483647; 34 | files = ( 35 | ); 36 | runOnlyForDeploymentPostprocessing = 0; 37 | }; 38 | /* End PBXFrameworksBuildPhase section */ 39 | 40 | /* Begin PBXGroup section */ 41 | E2985D64184E1A7D0085DC5D = { 42 | isa = PBXGroup; 43 | children = ( 44 | E2985DC7184E4CE00085DC5D /* ObjCClassSwizzling */, 45 | E2985D6E184E1A7D0085DC5D /* Products */, 46 | ); 47 | sourceTree = ""; 48 | }; 49 | E2985D6E184E1A7D0085DC5D /* Products */ = { 50 | isa = PBXGroup; 51 | children = ( 52 | E2985D6D184E1A7D0085DC5D /* ObjCClassSwizzling */, 53 | ); 54 | name = Products; 55 | sourceTree = ""; 56 | }; 57 | E2985DC7184E4CE00085DC5D /* ObjCClassSwizzling */ = { 58 | isa = PBXGroup; 59 | children = ( 60 | E2985DC8184E4CE00085DC5D /* main.m */, 61 | ); 62 | path = ObjCClassSwizzling; 63 | sourceTree = ""; 64 | }; 65 | /* End PBXGroup section */ 66 | 67 | /* Begin PBXNativeTarget section */ 68 | E2985D6C184E1A7D0085DC5D /* ObjCClassSwizzling */ = { 69 | isa = PBXNativeTarget; 70 | buildConfigurationList = E2985D76184E1A7E0085DC5D /* Build configuration list for PBXNativeTarget "ObjCClassSwizzling" */; 71 | buildPhases = ( 72 | E2985D69184E1A7D0085DC5D /* Sources */, 73 | E2985D6A184E1A7D0085DC5D /* Frameworks */, 74 | E2985D6B184E1A7D0085DC5D /* CopyFiles */, 75 | ); 76 | buildRules = ( 77 | ); 78 | dependencies = ( 79 | ); 80 | name = ObjCClassSwizzling; 81 | productName = ObjCSimple; 82 | productReference = E2985D6D184E1A7D0085DC5D /* ObjCClassSwizzling */; 83 | productType = "com.apple.product-type.tool"; 84 | }; 85 | /* End PBXNativeTarget section */ 86 | 87 | /* Begin PBXProject section */ 88 | E2985D65184E1A7D0085DC5D /* Project object */ = { 89 | isa = PBXProject; 90 | attributes = { 91 | LastUpgradeCheck = 0500; 92 | ORGANIZATIONNAME = "Tom Adriaenssen"; 93 | }; 94 | buildConfigurationList = E2985D68184E1A7D0085DC5D /* Build configuration list for PBXProject "ObjCClassSwizzling" */; 95 | compatibilityVersion = "Xcode 3.2"; 96 | developmentRegion = English; 97 | hasScannedForEncodings = 0; 98 | knownRegions = ( 99 | en, 100 | ); 101 | mainGroup = E2985D64184E1A7D0085DC5D; 102 | productRefGroup = E2985D6E184E1A7D0085DC5D /* Products */; 103 | projectDirPath = ""; 104 | projectRoot = ""; 105 | targets = ( 106 | E2985D6C184E1A7D0085DC5D /* ObjCClassSwizzling */, 107 | ); 108 | }; 109 | /* End PBXProject section */ 110 | 111 | /* Begin PBXSourcesBuildPhase section */ 112 | E2985D69184E1A7D0085DC5D /* Sources */ = { 113 | isa = PBXSourcesBuildPhase; 114 | buildActionMask = 2147483647; 115 | files = ( 116 | E2985DC9184E4CE00085DC5D /* main.m in Sources */, 117 | ); 118 | runOnlyForDeploymentPostprocessing = 0; 119 | }; 120 | /* End PBXSourcesBuildPhase section */ 121 | 122 | /* Begin XCBuildConfiguration section */ 123 | E2985D74184E1A7E0085DC5D /* Debug */ = { 124 | isa = XCBuildConfiguration; 125 | buildSettings = { 126 | ALWAYS_SEARCH_USER_PATHS = NO; 127 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 128 | CLANG_CXX_LIBRARY = "libc++"; 129 | CLANG_ENABLE_OBJC_ARC = YES; 130 | CLANG_WARN_BOOL_CONVERSION = YES; 131 | CLANG_WARN_CONSTANT_CONVERSION = YES; 132 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 133 | CLANG_WARN_EMPTY_BODY = YES; 134 | CLANG_WARN_ENUM_CONVERSION = YES; 135 | CLANG_WARN_INT_CONVERSION = YES; 136 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 137 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 138 | COPY_PHASE_STRIP = NO; 139 | GCC_C_LANGUAGE_STANDARD = gnu99; 140 | GCC_DYNAMIC_NO_PIC = NO; 141 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 142 | GCC_OPTIMIZATION_LEVEL = 0; 143 | GCC_PREPROCESSOR_DEFINITIONS = ( 144 | "DEBUG=1", 145 | "$(inherited)", 146 | ); 147 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 148 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 149 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 150 | GCC_WARN_UNDECLARED_SELECTOR = YES; 151 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 152 | GCC_WARN_UNUSED_FUNCTION = YES; 153 | GCC_WARN_UNUSED_VARIABLE = YES; 154 | MACOSX_DEPLOYMENT_TARGET = 10.9; 155 | ONLY_ACTIVE_ARCH = YES; 156 | SDKROOT = macosx; 157 | }; 158 | name = Debug; 159 | }; 160 | E2985D75184E1A7E0085DC5D /* Release */ = { 161 | isa = XCBuildConfiguration; 162 | buildSettings = { 163 | ALWAYS_SEARCH_USER_PATHS = NO; 164 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 165 | CLANG_CXX_LIBRARY = "libc++"; 166 | CLANG_ENABLE_OBJC_ARC = YES; 167 | CLANG_WARN_BOOL_CONVERSION = YES; 168 | CLANG_WARN_CONSTANT_CONVERSION = YES; 169 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 170 | CLANG_WARN_EMPTY_BODY = YES; 171 | CLANG_WARN_ENUM_CONVERSION = YES; 172 | CLANG_WARN_INT_CONVERSION = YES; 173 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 174 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 175 | COPY_PHASE_STRIP = YES; 176 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 177 | ENABLE_NS_ASSERTIONS = NO; 178 | GCC_C_LANGUAGE_STANDARD = gnu99; 179 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 180 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 181 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 182 | GCC_WARN_UNDECLARED_SELECTOR = YES; 183 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 184 | GCC_WARN_UNUSED_FUNCTION = YES; 185 | GCC_WARN_UNUSED_VARIABLE = YES; 186 | MACOSX_DEPLOYMENT_TARGET = 10.9; 187 | SDKROOT = macosx; 188 | }; 189 | name = Release; 190 | }; 191 | E2985D77184E1A7E0085DC5D /* Debug */ = { 192 | isa = XCBuildConfiguration; 193 | buildSettings = { 194 | ARCHS = "$(ARCHS_STANDARD)"; 195 | CLANG_ENABLE_OBJC_ARC = NO; 196 | PRODUCT_NAME = ObjCClassSwizzling; 197 | }; 198 | name = Debug; 199 | }; 200 | E2985D78184E1A7E0085DC5D /* Release */ = { 201 | isa = XCBuildConfiguration; 202 | buildSettings = { 203 | ARCHS = "$(ARCHS_STANDARD)"; 204 | CLANG_ENABLE_OBJC_ARC = NO; 205 | PRODUCT_NAME = ObjCClassSwizzling; 206 | }; 207 | name = Release; 208 | }; 209 | /* End XCBuildConfiguration section */ 210 | 211 | /* Begin XCConfigurationList section */ 212 | E2985D68184E1A7D0085DC5D /* Build configuration list for PBXProject "ObjCClassSwizzling" */ = { 213 | isa = XCConfigurationList; 214 | buildConfigurations = ( 215 | E2985D74184E1A7E0085DC5D /* Debug */, 216 | E2985D75184E1A7E0085DC5D /* Release */, 217 | ); 218 | defaultConfigurationIsVisible = 0; 219 | defaultConfigurationName = Release; 220 | }; 221 | E2985D76184E1A7E0085DC5D /* Build configuration list for PBXNativeTarget "ObjCClassSwizzling" */ = { 222 | isa = XCConfigurationList; 223 | buildConfigurations = ( 224 | E2985D77184E1A7E0085DC5D /* Debug */, 225 | E2985D78184E1A7E0085DC5D /* Release */, 226 | ); 227 | defaultConfigurationIsVisible = 0; 228 | defaultConfigurationName = Release; 229 | }; 230 | /* End XCConfigurationList section */ 231 | }; 232 | rootObject = E2985D65184E1A7D0085DC5D /* Project object */; 233 | } 234 | -------------------------------------------------------------------------------- /example code/6. ObjCClassSwizzling/ObjCClassSwizzling/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.c 3 | // ObjCSimple 4 | // 5 | 6 | #include 7 | #include 8 | 9 | @interface Person : NSObject 10 | 11 | - (NSString*)ohai; 12 | - (void)becomeFrenchie; 13 | 14 | @end 15 | 16 | @interface FrenchPerson : Person 17 | 18 | - (NSString*)ohai; 19 | 20 | @end 21 | 22 | @implementation Person 23 | 24 | - (NSString *)ohai { 25 | return @"ohai"; 26 | } 27 | 28 | - (void)becomeFrenchie { 29 | object_setClass(self, [FrenchPerson class]); 30 | } 31 | 32 | - (void)becomePolyglot:(NSString*)language { 33 | NSString* subclassName = [NSString stringWithFormat:@"%@_%@", [self class], language]; 34 | Class subclass = NSClassFromString(subclassName); 35 | if (subclass != nil) { 36 | NSLog(@"Already speaks fluently %@", language); 37 | return; 38 | } 39 | 40 | subclass = objc_allocateClassPair([self class], [subclassName UTF8String], 0); 41 | if (subclass == nil) { 42 | NSLog(@"Objective c doesn't want me to speak %@", language); 43 | return; 44 | } 45 | objc_registerClassPair(subclass); 46 | 47 | // now add the custom ohai selector 48 | IMP polyOhai = imp_implementationWithBlock(^(id self) { 49 | return [NSString stringWithFormat:@"%@ %@", language, [self superOhai]]; 50 | }); 51 | class_addMethod(subclass, @selector(ohai), polyOhai, "@@:"); 52 | 53 | // since we want to call the super ohai, we define a new method that will 54 | // call the implementation of the superclass (the class we're in now, effectively) 55 | Method superOhaiMethod = class_getInstanceMethod([self class], @selector(ohai)); 56 | IMP superOhaiImp = method_getImplementation(superOhaiMethod); 57 | class_addMethod(subclass, @selector(superOhai), superOhaiImp, "@@:"); 58 | 59 | object_setClass(self, subclass); 60 | } 61 | 62 | @end 63 | 64 | @implementation FrenchPerson 65 | 66 | - (NSString *)ohai { 67 | return @"le ohai"; 68 | } 69 | 70 | @end 71 | 72 | 73 | int main(int argc, char **argv) 74 | { 75 | Person* obj = [Person new]; 76 | NSLog(@"not swizzled -> %@ (am %@)", [obj ohai], obj); 77 | [obj becomeFrenchie]; 78 | NSLog(@"swizzled -> %@ (am %@)", [obj ohai], obj); 79 | [obj becomeFrenchie]; 80 | NSLog(@"still swizzled -> %@ (am %@)", [obj ohai], obj); 81 | [obj becomePolyglot:@"nou moe"]; 82 | NSLog(@"still swizzled -> %@ (am %@)", [obj ohai], obj); 83 | 84 | Person* greek = [Person new]; 85 | [greek becomePolyglot:@"calimera"]; 86 | NSLog(@"greek -> %@ (am %@)", [greek ohai], greek); 87 | } -------------------------------------------------------------------------------- /example code/7. ObjCGeneratedProperties/ObjCGeneratedProperties.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | E2985DCC184E52B20085DC5D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = E2985DCB184E52B20085DC5D /* main.m */; }; 11 | /* End PBXBuildFile section */ 12 | 13 | /* Begin PBXCopyFilesBuildPhase section */ 14 | E2985D6B184E1A7D0085DC5D /* CopyFiles */ = { 15 | isa = PBXCopyFilesBuildPhase; 16 | buildActionMask = 2147483647; 17 | dstPath = /usr/share/man/man1/; 18 | dstSubfolderSpec = 0; 19 | files = ( 20 | ); 21 | runOnlyForDeploymentPostprocessing = 1; 22 | }; 23 | /* End PBXCopyFilesBuildPhase section */ 24 | 25 | /* Begin PBXFileReference section */ 26 | E2985D6D184E1A7D0085DC5D /* ObjCGeneratedProperties */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ObjCGeneratedProperties; sourceTree = BUILT_PRODUCTS_DIR; }; 27 | E2985DCB184E52B20085DC5D /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 28 | /* End PBXFileReference section */ 29 | 30 | /* Begin PBXFrameworksBuildPhase section */ 31 | E2985D6A184E1A7D0085DC5D /* Frameworks */ = { 32 | isa = PBXFrameworksBuildPhase; 33 | buildActionMask = 2147483647; 34 | files = ( 35 | ); 36 | runOnlyForDeploymentPostprocessing = 0; 37 | }; 38 | /* End PBXFrameworksBuildPhase section */ 39 | 40 | /* Begin PBXGroup section */ 41 | E2985D64184E1A7D0085DC5D = { 42 | isa = PBXGroup; 43 | children = ( 44 | E2985DCA184E52B20085DC5D /* ObjCGeneratedProperties */, 45 | E2985D6E184E1A7D0085DC5D /* Products */, 46 | ); 47 | sourceTree = ""; 48 | }; 49 | E2985D6E184E1A7D0085DC5D /* Products */ = { 50 | isa = PBXGroup; 51 | children = ( 52 | E2985D6D184E1A7D0085DC5D /* ObjCGeneratedProperties */, 53 | ); 54 | name = Products; 55 | sourceTree = ""; 56 | }; 57 | E2985DCA184E52B20085DC5D /* ObjCGeneratedProperties */ = { 58 | isa = PBXGroup; 59 | children = ( 60 | E2985DCB184E52B20085DC5D /* main.m */, 61 | ); 62 | path = ObjCGeneratedProperties; 63 | sourceTree = ""; 64 | }; 65 | /* End PBXGroup section */ 66 | 67 | /* Begin PBXNativeTarget section */ 68 | E2985D6C184E1A7D0085DC5D /* ObjCGeneratedProperties */ = { 69 | isa = PBXNativeTarget; 70 | buildConfigurationList = E2985D76184E1A7E0085DC5D /* Build configuration list for PBXNativeTarget "ObjCGeneratedProperties" */; 71 | buildPhases = ( 72 | E2985D69184E1A7D0085DC5D /* Sources */, 73 | E2985D6A184E1A7D0085DC5D /* Frameworks */, 74 | E2985D6B184E1A7D0085DC5D /* CopyFiles */, 75 | ); 76 | buildRules = ( 77 | ); 78 | dependencies = ( 79 | ); 80 | name = ObjCGeneratedProperties; 81 | productName = ObjCSimple; 82 | productReference = E2985D6D184E1A7D0085DC5D /* ObjCGeneratedProperties */; 83 | productType = "com.apple.product-type.tool"; 84 | }; 85 | /* End PBXNativeTarget section */ 86 | 87 | /* Begin PBXProject section */ 88 | E2985D65184E1A7D0085DC5D /* Project object */ = { 89 | isa = PBXProject; 90 | attributes = { 91 | LastUpgradeCheck = 0500; 92 | ORGANIZATIONNAME = "Tom Adriaenssen"; 93 | }; 94 | buildConfigurationList = E2985D68184E1A7D0085DC5D /* Build configuration list for PBXProject "ObjCGeneratedProperties" */; 95 | compatibilityVersion = "Xcode 3.2"; 96 | developmentRegion = English; 97 | hasScannedForEncodings = 0; 98 | knownRegions = ( 99 | en, 100 | ); 101 | mainGroup = E2985D64184E1A7D0085DC5D; 102 | productRefGroup = E2985D6E184E1A7D0085DC5D /* Products */; 103 | projectDirPath = ""; 104 | projectRoot = ""; 105 | targets = ( 106 | E2985D6C184E1A7D0085DC5D /* ObjCGeneratedProperties */, 107 | ); 108 | }; 109 | /* End PBXProject section */ 110 | 111 | /* Begin PBXSourcesBuildPhase section */ 112 | E2985D69184E1A7D0085DC5D /* Sources */ = { 113 | isa = PBXSourcesBuildPhase; 114 | buildActionMask = 2147483647; 115 | files = ( 116 | E2985DCC184E52B20085DC5D /* main.m in Sources */, 117 | ); 118 | runOnlyForDeploymentPostprocessing = 0; 119 | }; 120 | /* End PBXSourcesBuildPhase section */ 121 | 122 | /* Begin XCBuildConfiguration section */ 123 | E2985D74184E1A7E0085DC5D /* Debug */ = { 124 | isa = XCBuildConfiguration; 125 | buildSettings = { 126 | ALWAYS_SEARCH_USER_PATHS = NO; 127 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 128 | CLANG_CXX_LIBRARY = "libc++"; 129 | CLANG_ENABLE_OBJC_ARC = YES; 130 | CLANG_WARN_BOOL_CONVERSION = YES; 131 | CLANG_WARN_CONSTANT_CONVERSION = YES; 132 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 133 | CLANG_WARN_EMPTY_BODY = YES; 134 | CLANG_WARN_ENUM_CONVERSION = YES; 135 | CLANG_WARN_INT_CONVERSION = YES; 136 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 137 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 138 | COPY_PHASE_STRIP = NO; 139 | GCC_C_LANGUAGE_STANDARD = gnu99; 140 | GCC_DYNAMIC_NO_PIC = NO; 141 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 142 | GCC_OPTIMIZATION_LEVEL = 0; 143 | GCC_PREPROCESSOR_DEFINITIONS = ( 144 | "DEBUG=1", 145 | "$(inherited)", 146 | ); 147 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 148 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 149 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 150 | GCC_WARN_UNDECLARED_SELECTOR = YES; 151 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 152 | GCC_WARN_UNUSED_FUNCTION = YES; 153 | GCC_WARN_UNUSED_VARIABLE = YES; 154 | MACOSX_DEPLOYMENT_TARGET = 10.9; 155 | ONLY_ACTIVE_ARCH = YES; 156 | SDKROOT = macosx; 157 | }; 158 | name = Debug; 159 | }; 160 | E2985D75184E1A7E0085DC5D /* Release */ = { 161 | isa = XCBuildConfiguration; 162 | buildSettings = { 163 | ALWAYS_SEARCH_USER_PATHS = NO; 164 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 165 | CLANG_CXX_LIBRARY = "libc++"; 166 | CLANG_ENABLE_OBJC_ARC = YES; 167 | CLANG_WARN_BOOL_CONVERSION = YES; 168 | CLANG_WARN_CONSTANT_CONVERSION = YES; 169 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 170 | CLANG_WARN_EMPTY_BODY = YES; 171 | CLANG_WARN_ENUM_CONVERSION = YES; 172 | CLANG_WARN_INT_CONVERSION = YES; 173 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 174 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 175 | COPY_PHASE_STRIP = YES; 176 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 177 | ENABLE_NS_ASSERTIONS = NO; 178 | GCC_C_LANGUAGE_STANDARD = gnu99; 179 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 180 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 181 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 182 | GCC_WARN_UNDECLARED_SELECTOR = YES; 183 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 184 | GCC_WARN_UNUSED_FUNCTION = YES; 185 | GCC_WARN_UNUSED_VARIABLE = YES; 186 | MACOSX_DEPLOYMENT_TARGET = 10.9; 187 | SDKROOT = macosx; 188 | }; 189 | name = Release; 190 | }; 191 | E2985D77184E1A7E0085DC5D /* Debug */ = { 192 | isa = XCBuildConfiguration; 193 | buildSettings = { 194 | ARCHS = "$(ARCHS_STANDARD)"; 195 | CLANG_ENABLE_OBJC_ARC = NO; 196 | PRODUCT_NAME = ObjCGeneratedProperties; 197 | }; 198 | name = Debug; 199 | }; 200 | E2985D78184E1A7E0085DC5D /* Release */ = { 201 | isa = XCBuildConfiguration; 202 | buildSettings = { 203 | ARCHS = "$(ARCHS_STANDARD)"; 204 | CLANG_ENABLE_OBJC_ARC = NO; 205 | PRODUCT_NAME = ObjCGeneratedProperties; 206 | }; 207 | name = Release; 208 | }; 209 | /* End XCBuildConfiguration section */ 210 | 211 | /* Begin XCConfigurationList section */ 212 | E2985D68184E1A7D0085DC5D /* Build configuration list for PBXProject "ObjCGeneratedProperties" */ = { 213 | isa = XCConfigurationList; 214 | buildConfigurations = ( 215 | E2985D74184E1A7E0085DC5D /* Debug */, 216 | E2985D75184E1A7E0085DC5D /* Release */, 217 | ); 218 | defaultConfigurationIsVisible = 0; 219 | defaultConfigurationName = Release; 220 | }; 221 | E2985D76184E1A7E0085DC5D /* Build configuration list for PBXNativeTarget "ObjCGeneratedProperties" */ = { 222 | isa = XCConfigurationList; 223 | buildConfigurations = ( 224 | E2985D77184E1A7E0085DC5D /* Debug */, 225 | E2985D78184E1A7E0085DC5D /* Release */, 226 | ); 227 | defaultConfigurationIsVisible = 0; 228 | defaultConfigurationName = Release; 229 | }; 230 | /* End XCConfigurationList section */ 231 | }; 232 | rootObject = E2985D65184E1A7D0085DC5D /* Project object */; 233 | } 234 | -------------------------------------------------------------------------------- /example code/7. ObjCGeneratedProperties/ObjCGeneratedProperties/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.c 3 | // ObjCSimple 4 | // 5 | 6 | #include 7 | #include 8 | 9 | @interface Dynamic : NSObject 10 | 11 | 12 | @end 13 | 14 | @implementation Dynamic 15 | 16 | - (id)initWithProperties:(NSArray*)properties 17 | { 18 | self = [super init]; 19 | if (self) { 20 | for (NSString* property in properties) { 21 | [[self class] makeProperty:property]; 22 | } 23 | } 24 | return self; 25 | } 26 | 27 | + (void)makeProperties:(NSArray*)properties 28 | { 29 | for (NSString* property in properties) { 30 | [self makeProperty:property]; 31 | } 32 | } 33 | 34 | + (void)makeProperty:(NSString*)property { 35 | // getter 36 | NSString* ivarName = [@"_" stringByAppendingString:property]; 37 | const char* c_ivarName = [ivarName cStringUsingEncoding:NSUTF8StringEncoding]; 38 | 39 | IMP getter = imp_implementationWithBlock(^(id obj) { 40 | return objc_getAssociatedObject(obj, c_ivarName); 41 | }); 42 | class_addMethod(self, NSSelectorFromString(property), getter, "@@:"); 43 | 44 | // setter 45 | IMP setter = imp_implementationWithBlock(^(id obj, id value) { 46 | objc_setAssociatedObject(obj, c_ivarName, value, OBJC_ASSOCIATION_RETAIN); 47 | }); 48 | property = [NSString stringWithFormat:@"set%@:", [property capitalizedString]]; 49 | class_addMethod(self, NSSelectorFromString(property), setter, "v@:@"); 50 | } 51 | 52 | @end 53 | 54 | 55 | int main(int argc, char **argv) 56 | { 57 | [Dynamic makeProperties:@[@"foo", @"bar", @"baz"]]; 58 | 59 | Dynamic* dyn = [Dynamic new]; 60 | NSLog(@"dyn foo -> %@", [dyn foo]); 61 | [dyn setFoo:@"this is foo"]; 62 | NSLog(@"dyn foo after setting -> %@", [dyn foo]); 63 | 64 | @try { 65 | NSLog(@"dyn beer -> %@", [dyn beer]); 66 | } 67 | @catch (NSException *exception) { 68 | NSLog(@"OH NOES DEAD %@", exception); 69 | } 70 | 71 | [Dynamic makeProperties:@[@"beer"]]; 72 | 73 | @try { 74 | NSLog(@"dyn beer -> %@", [dyn beer]); 75 | } 76 | @catch (NSException *exception) { 77 | // shouldn't happen 78 | NSLog(@"OH NOES DEAD %@", exception); 79 | } 80 | } --------------------------------------------------------------------------------