├── README.md ├── SwiftIvarTypeDetector.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── SwiftIvarTypeDetector ├── Detector.h ├── Detector.m ├── Info.plist ├── IvarAccess.h └── SwiftIvarTypeDetector.h └── SwiftIvarTypeDetectorTests ├── Info.plist └── SwiftIvarTypeDetectorTests.swift /README.md: -------------------------------------------------------------------------------- 1 | # SwiftIvarTypeDetector 2 | 3 | This is a very simple project that wraps `ivar_getTypeEncodingSwift` from @johnno1962's [XprobePlugin](https://github.com/johnno1962/Xprobe) to easily print out the type encoding for properties in a Swift class. 4 | 5 | ## Usage 6 | 7 | Modify `SwiftIvarTypeDetectorTests.swift` and run the tests (`⌘+U`) to print out the properties on any Swift class. 8 | 9 | This project requires Xcode 6 (only betas 5 & 6 work as of 21/08/2014). 10 | 11 | ## MIT License 12 | 13 | Copyright (c) 2015 John Holdsworth 14 | 15 | Permission is hereby granted, free of charge, to any person obtaining a copy 16 | of this software and associated documentation files (the "Software"), to deal 17 | in the Software without restriction, including without limitation the rights 18 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 19 | copies of the Software, and to permit persons to whom the Software is 20 | furnished to do so, subject to the following conditions: 21 | 22 | The above copyright notice and this permission notice shall be included in all 23 | copies or substantial portions of the Software. 24 | 25 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31 | SOFTWARE. 32 | -------------------------------------------------------------------------------- /SwiftIvarTypeDetector.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | BB103F1F1B07BE2D00F280F2 /* README.md in Sources */ = {isa = PBXBuildFile; fileRef = BB103F1E1B07BE2D00F280F2 /* README.md */; }; 11 | BB103F221B07C74A00F280F2 /* IvarAccess.h in Headers */ = {isa = PBXBuildFile; fileRef = BB103F211B07C74A00F280F2 /* IvarAccess.h */; }; 12 | E87C2CFF196F9AED009783E4 /* SwiftIvarTypeDetector.h in Headers */ = {isa = PBXBuildFile; fileRef = E87C2CFE196F9AED009783E4 /* SwiftIvarTypeDetector.h */; settings = {ATTRIBUTES = (Public, ); }; }; 13 | E87C2D05196F9AED009783E4 /* SwiftIvarTypeDetector.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E87C2CF9196F9AED009783E4 /* SwiftIvarTypeDetector.framework */; }; 14 | E87C2D17196F9B09009783E4 /* Detector.h in Headers */ = {isa = PBXBuildFile; fileRef = E87C2D15196F9B09009783E4 /* Detector.h */; settings = {ATTRIBUTES = (Public, ); }; }; 15 | E87C2D18196F9B09009783E4 /* Detector.m in Sources */ = {isa = PBXBuildFile; fileRef = E87C2D16196F9B09009783E4 /* Detector.m */; }; 16 | E87C2D1C196F9BE6009783E4 /* SwiftIvarTypeDetectorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E87C2D1B196F9BE6009783E4 /* SwiftIvarTypeDetectorTests.swift */; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXContainerItemProxy section */ 20 | E87C2D06196F9AED009783E4 /* PBXContainerItemProxy */ = { 21 | isa = PBXContainerItemProxy; 22 | containerPortal = E87C2CF0196F9AED009783E4 /* Project object */; 23 | proxyType = 1; 24 | remoteGlobalIDString = E87C2CF8196F9AED009783E4; 25 | remoteInfo = SwiftIvarTypeDetector; 26 | }; 27 | /* End PBXContainerItemProxy section */ 28 | 29 | /* Begin PBXFileReference section */ 30 | BB103F1E1B07BE2D00F280F2 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; 31 | BB103F211B07C74A00F280F2 /* IvarAccess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IvarAccess.h; sourceTree = ""; }; 32 | E87C2CF9196F9AED009783E4 /* SwiftIvarTypeDetector.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SwiftIvarTypeDetector.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 33 | E87C2CFD196F9AED009783E4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 34 | E87C2CFE196F9AED009783E4 /* SwiftIvarTypeDetector.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SwiftIvarTypeDetector.h; sourceTree = ""; }; 35 | E87C2D04196F9AED009783E4 /* SwiftIvarTypeDetectorTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SwiftIvarTypeDetectorTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 36 | E87C2D0A196F9AED009783E4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 37 | E87C2D15196F9B09009783E4 /* Detector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Detector.h; sourceTree = ""; }; 38 | E87C2D16196F9B09009783E4 /* Detector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Detector.m; sourceTree = ""; }; 39 | E87C2D1B196F9BE6009783E4 /* SwiftIvarTypeDetectorTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftIvarTypeDetectorTests.swift; sourceTree = ""; }; 40 | /* End PBXFileReference section */ 41 | 42 | /* Begin PBXFrameworksBuildPhase section */ 43 | E87C2CF5196F9AED009783E4 /* Frameworks */ = { 44 | isa = PBXFrameworksBuildPhase; 45 | buildActionMask = 2147483647; 46 | files = ( 47 | ); 48 | runOnlyForDeploymentPostprocessing = 0; 49 | }; 50 | E87C2D01196F9AED009783E4 /* Frameworks */ = { 51 | isa = PBXFrameworksBuildPhase; 52 | buildActionMask = 2147483647; 53 | files = ( 54 | E87C2D05196F9AED009783E4 /* SwiftIvarTypeDetector.framework in Frameworks */, 55 | ); 56 | runOnlyForDeploymentPostprocessing = 0; 57 | }; 58 | /* End PBXFrameworksBuildPhase section */ 59 | 60 | /* Begin PBXGroup section */ 61 | E87C2CEF196F9AED009783E4 = { 62 | isa = PBXGroup; 63 | children = ( 64 | BB103F1E1B07BE2D00F280F2 /* README.md */, 65 | E87C2CFB196F9AED009783E4 /* SwiftIvarTypeDetector */, 66 | E87C2D08196F9AED009783E4 /* SwiftIvarTypeDetectorTests */, 67 | E87C2CFA196F9AED009783E4 /* Products */, 68 | ); 69 | sourceTree = ""; 70 | }; 71 | E87C2CFA196F9AED009783E4 /* Products */ = { 72 | isa = PBXGroup; 73 | children = ( 74 | E87C2CF9196F9AED009783E4 /* SwiftIvarTypeDetector.framework */, 75 | E87C2D04196F9AED009783E4 /* SwiftIvarTypeDetectorTests.xctest */, 76 | ); 77 | name = Products; 78 | sourceTree = ""; 79 | }; 80 | E87C2CFB196F9AED009783E4 /* SwiftIvarTypeDetector */ = { 81 | isa = PBXGroup; 82 | children = ( 83 | E87C2CFE196F9AED009783E4 /* SwiftIvarTypeDetector.h */, 84 | BB103F211B07C74A00F280F2 /* IvarAccess.h */, 85 | E87C2D15196F9B09009783E4 /* Detector.h */, 86 | E87C2D16196F9B09009783E4 /* Detector.m */, 87 | E87C2CFC196F9AED009783E4 /* Supporting Files */, 88 | ); 89 | path = SwiftIvarTypeDetector; 90 | sourceTree = ""; 91 | }; 92 | E87C2CFC196F9AED009783E4 /* Supporting Files */ = { 93 | isa = PBXGroup; 94 | children = ( 95 | E87C2CFD196F9AED009783E4 /* Info.plist */, 96 | ); 97 | name = "Supporting Files"; 98 | sourceTree = ""; 99 | }; 100 | E87C2D08196F9AED009783E4 /* SwiftIvarTypeDetectorTests */ = { 101 | isa = PBXGroup; 102 | children = ( 103 | E87C2D1B196F9BE6009783E4 /* SwiftIvarTypeDetectorTests.swift */, 104 | E87C2D09196F9AED009783E4 /* Supporting Files */, 105 | ); 106 | path = SwiftIvarTypeDetectorTests; 107 | sourceTree = ""; 108 | }; 109 | E87C2D09196F9AED009783E4 /* Supporting Files */ = { 110 | isa = PBXGroup; 111 | children = ( 112 | E87C2D0A196F9AED009783E4 /* Info.plist */, 113 | ); 114 | name = "Supporting Files"; 115 | sourceTree = ""; 116 | }; 117 | /* End PBXGroup section */ 118 | 119 | /* Begin PBXHeadersBuildPhase section */ 120 | E87C2CF6196F9AED009783E4 /* Headers */ = { 121 | isa = PBXHeadersBuildPhase; 122 | buildActionMask = 2147483647; 123 | files = ( 124 | E87C2D17196F9B09009783E4 /* Detector.h in Headers */, 125 | BB103F221B07C74A00F280F2 /* IvarAccess.h in Headers */, 126 | E87C2CFF196F9AED009783E4 /* SwiftIvarTypeDetector.h in Headers */, 127 | ); 128 | runOnlyForDeploymentPostprocessing = 0; 129 | }; 130 | /* End PBXHeadersBuildPhase section */ 131 | 132 | /* Begin PBXNativeTarget section */ 133 | E87C2CF8196F9AED009783E4 /* SwiftIvarTypeDetector */ = { 134 | isa = PBXNativeTarget; 135 | buildConfigurationList = E87C2D0F196F9AED009783E4 /* Build configuration list for PBXNativeTarget "SwiftIvarTypeDetector" */; 136 | buildPhases = ( 137 | E87C2CF4196F9AED009783E4 /* Sources */, 138 | E87C2CF5196F9AED009783E4 /* Frameworks */, 139 | E87C2CF6196F9AED009783E4 /* Headers */, 140 | E87C2CF7196F9AED009783E4 /* Resources */, 141 | ); 142 | buildRules = ( 143 | ); 144 | dependencies = ( 145 | ); 146 | name = SwiftIvarTypeDetector; 147 | productName = SwiftIvarTypeDetector; 148 | productReference = E87C2CF9196F9AED009783E4 /* SwiftIvarTypeDetector.framework */; 149 | productType = "com.apple.product-type.framework"; 150 | }; 151 | E87C2D03196F9AED009783E4 /* SwiftIvarTypeDetectorTests */ = { 152 | isa = PBXNativeTarget; 153 | buildConfigurationList = E87C2D12196F9AED009783E4 /* Build configuration list for PBXNativeTarget "SwiftIvarTypeDetectorTests" */; 154 | buildPhases = ( 155 | E87C2D00196F9AED009783E4 /* Sources */, 156 | E87C2D01196F9AED009783E4 /* Frameworks */, 157 | E87C2D02196F9AED009783E4 /* Resources */, 158 | ); 159 | buildRules = ( 160 | ); 161 | dependencies = ( 162 | E87C2D07196F9AED009783E4 /* PBXTargetDependency */, 163 | ); 164 | name = SwiftIvarTypeDetectorTests; 165 | productName = SwiftIvarTypeDetectorTests; 166 | productReference = E87C2D04196F9AED009783E4 /* SwiftIvarTypeDetectorTests.xctest */; 167 | productType = "com.apple.product-type.bundle.unit-test"; 168 | }; 169 | /* End PBXNativeTarget section */ 170 | 171 | /* Begin PBXProject section */ 172 | E87C2CF0196F9AED009783E4 /* Project object */ = { 173 | isa = PBXProject; 174 | attributes = { 175 | LastUpgradeCheck = 0600; 176 | ORGANIZATIONNAME = Realm; 177 | TargetAttributes = { 178 | E87C2CF8196F9AED009783E4 = { 179 | CreatedOnToolsVersion = 6.0; 180 | }; 181 | E87C2D03196F9AED009783E4 = { 182 | CreatedOnToolsVersion = 6.0; 183 | TestTargetID = E87C2CF8196F9AED009783E4; 184 | }; 185 | }; 186 | }; 187 | buildConfigurationList = E87C2CF3196F9AED009783E4 /* Build configuration list for PBXProject "SwiftIvarTypeDetector" */; 188 | compatibilityVersion = "Xcode 3.2"; 189 | developmentRegion = English; 190 | hasScannedForEncodings = 0; 191 | knownRegions = ( 192 | en, 193 | ); 194 | mainGroup = E87C2CEF196F9AED009783E4; 195 | productRefGroup = E87C2CFA196F9AED009783E4 /* Products */; 196 | projectDirPath = ""; 197 | projectRoot = ""; 198 | targets = ( 199 | E87C2CF8196F9AED009783E4 /* SwiftIvarTypeDetector */, 200 | E87C2D03196F9AED009783E4 /* SwiftIvarTypeDetectorTests */, 201 | ); 202 | }; 203 | /* End PBXProject section */ 204 | 205 | /* Begin PBXResourcesBuildPhase section */ 206 | E87C2CF7196F9AED009783E4 /* Resources */ = { 207 | isa = PBXResourcesBuildPhase; 208 | buildActionMask = 2147483647; 209 | files = ( 210 | ); 211 | runOnlyForDeploymentPostprocessing = 0; 212 | }; 213 | E87C2D02196F9AED009783E4 /* Resources */ = { 214 | isa = PBXResourcesBuildPhase; 215 | buildActionMask = 2147483647; 216 | files = ( 217 | ); 218 | runOnlyForDeploymentPostprocessing = 0; 219 | }; 220 | /* End PBXResourcesBuildPhase section */ 221 | 222 | /* Begin PBXSourcesBuildPhase section */ 223 | E87C2CF4196F9AED009783E4 /* Sources */ = { 224 | isa = PBXSourcesBuildPhase; 225 | buildActionMask = 2147483647; 226 | files = ( 227 | BB103F1F1B07BE2D00F280F2 /* README.md in Sources */, 228 | E87C2D18196F9B09009783E4 /* Detector.m in Sources */, 229 | ); 230 | runOnlyForDeploymentPostprocessing = 0; 231 | }; 232 | E87C2D00196F9AED009783E4 /* Sources */ = { 233 | isa = PBXSourcesBuildPhase; 234 | buildActionMask = 2147483647; 235 | files = ( 236 | E87C2D1C196F9BE6009783E4 /* SwiftIvarTypeDetectorTests.swift in Sources */, 237 | ); 238 | runOnlyForDeploymentPostprocessing = 0; 239 | }; 240 | /* End PBXSourcesBuildPhase section */ 241 | 242 | /* Begin PBXTargetDependency section */ 243 | E87C2D07196F9AED009783E4 /* PBXTargetDependency */ = { 244 | isa = PBXTargetDependency; 245 | target = E87C2CF8196F9AED009783E4 /* SwiftIvarTypeDetector */; 246 | targetProxy = E87C2D06196F9AED009783E4 /* PBXContainerItemProxy */; 247 | }; 248 | /* End PBXTargetDependency section */ 249 | 250 | /* Begin XCBuildConfiguration section */ 251 | E87C2D0D196F9AED009783E4 /* Debug */ = { 252 | isa = XCBuildConfiguration; 253 | buildSettings = { 254 | ALWAYS_SEARCH_USER_PATHS = NO; 255 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 256 | CLANG_CXX_LIBRARY = "libc++"; 257 | CLANG_ENABLE_MODULES = YES; 258 | CLANG_ENABLE_OBJC_ARC = YES; 259 | CLANG_WARN_BOOL_CONVERSION = YES; 260 | CLANG_WARN_CONSTANT_CONVERSION = YES; 261 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 262 | CLANG_WARN_EMPTY_BODY = YES; 263 | CLANG_WARN_ENUM_CONVERSION = YES; 264 | CLANG_WARN_INT_CONVERSION = YES; 265 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 266 | CLANG_WARN_UNREACHABLE_CODE = YES; 267 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 268 | COPY_PHASE_STRIP = NO; 269 | CURRENT_PROJECT_VERSION = 1; 270 | ENABLE_STRICT_OBJC_MSGSEND = YES; 271 | GCC_C_LANGUAGE_STANDARD = gnu99; 272 | GCC_DYNAMIC_NO_PIC = NO; 273 | GCC_OPTIMIZATION_LEVEL = 0; 274 | GCC_PREPROCESSOR_DEFINITIONS = ( 275 | "DEBUG=1", 276 | "$(inherited)", 277 | ); 278 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 279 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 280 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 281 | GCC_WARN_UNDECLARED_SELECTOR = YES; 282 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 283 | GCC_WARN_UNUSED_FUNCTION = YES; 284 | GCC_WARN_UNUSED_VARIABLE = YES; 285 | MACOSX_DEPLOYMENT_TARGET = 10.10; 286 | METAL_ENABLE_DEBUG_INFO = YES; 287 | ONLY_ACTIVE_ARCH = YES; 288 | SDKROOT = macosx; 289 | VERSIONING_SYSTEM = "apple-generic"; 290 | VERSION_INFO_PREFIX = ""; 291 | }; 292 | name = Debug; 293 | }; 294 | E87C2D0E196F9AED009783E4 /* Release */ = { 295 | isa = XCBuildConfiguration; 296 | buildSettings = { 297 | ALWAYS_SEARCH_USER_PATHS = NO; 298 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 299 | CLANG_CXX_LIBRARY = "libc++"; 300 | CLANG_ENABLE_MODULES = YES; 301 | CLANG_ENABLE_OBJC_ARC = YES; 302 | CLANG_WARN_BOOL_CONVERSION = YES; 303 | CLANG_WARN_CONSTANT_CONVERSION = YES; 304 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 305 | CLANG_WARN_EMPTY_BODY = YES; 306 | CLANG_WARN_ENUM_CONVERSION = YES; 307 | CLANG_WARN_INT_CONVERSION = YES; 308 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 309 | CLANG_WARN_UNREACHABLE_CODE = YES; 310 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 311 | COPY_PHASE_STRIP = YES; 312 | CURRENT_PROJECT_VERSION = 1; 313 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 314 | ENABLE_NS_ASSERTIONS = NO; 315 | ENABLE_STRICT_OBJC_MSGSEND = YES; 316 | GCC_C_LANGUAGE_STANDARD = gnu99; 317 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 318 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 319 | GCC_WARN_UNDECLARED_SELECTOR = YES; 320 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 321 | GCC_WARN_UNUSED_FUNCTION = YES; 322 | GCC_WARN_UNUSED_VARIABLE = YES; 323 | MACOSX_DEPLOYMENT_TARGET = 10.10; 324 | METAL_ENABLE_DEBUG_INFO = NO; 325 | SDKROOT = macosx; 326 | VERSIONING_SYSTEM = "apple-generic"; 327 | VERSION_INFO_PREFIX = ""; 328 | }; 329 | name = Release; 330 | }; 331 | E87C2D10196F9AED009783E4 /* Debug */ = { 332 | isa = XCBuildConfiguration; 333 | buildSettings = { 334 | COMBINE_HIDPI_IMAGES = YES; 335 | DEFINES_MODULE = YES; 336 | DYLIB_COMPATIBILITY_VERSION = 1; 337 | DYLIB_CURRENT_VERSION = 1; 338 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 339 | FRAMEWORK_VERSION = A; 340 | INFOPLIST_FILE = SwiftIvarTypeDetector/Info.plist; 341 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 342 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 343 | PRODUCT_NAME = "$(TARGET_NAME)"; 344 | SKIP_INSTALL = YES; 345 | }; 346 | name = Debug; 347 | }; 348 | E87C2D11196F9AED009783E4 /* Release */ = { 349 | isa = XCBuildConfiguration; 350 | buildSettings = { 351 | COMBINE_HIDPI_IMAGES = YES; 352 | DEFINES_MODULE = YES; 353 | DYLIB_COMPATIBILITY_VERSION = 1; 354 | DYLIB_CURRENT_VERSION = 1; 355 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 356 | FRAMEWORK_VERSION = A; 357 | INFOPLIST_FILE = SwiftIvarTypeDetector/Info.plist; 358 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 359 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 360 | PRODUCT_NAME = "$(TARGET_NAME)"; 361 | SKIP_INSTALL = YES; 362 | }; 363 | name = Release; 364 | }; 365 | E87C2D13196F9AED009783E4 /* Debug */ = { 366 | isa = XCBuildConfiguration; 367 | buildSettings = { 368 | CLANG_ENABLE_MODULES = YES; 369 | COMBINE_HIDPI_IMAGES = YES; 370 | FRAMEWORK_SEARCH_PATHS = ( 371 | "$(DEVELOPER_FRAMEWORKS_DIR)", 372 | "$(inherited)", 373 | ); 374 | GCC_PREPROCESSOR_DEFINITIONS = ( 375 | "DEBUG=1", 376 | "$(inherited)", 377 | ); 378 | INFOPLIST_FILE = SwiftIvarTypeDetectorTests/Info.plist; 379 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 380 | METAL_ENABLE_DEBUG_INFO = YES; 381 | PRODUCT_NAME = "$(TARGET_NAME)"; 382 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 383 | }; 384 | name = Debug; 385 | }; 386 | E87C2D14196F9AED009783E4 /* Release */ = { 387 | isa = XCBuildConfiguration; 388 | buildSettings = { 389 | CLANG_ENABLE_MODULES = YES; 390 | COMBINE_HIDPI_IMAGES = YES; 391 | FRAMEWORK_SEARCH_PATHS = ( 392 | "$(DEVELOPER_FRAMEWORKS_DIR)", 393 | "$(inherited)", 394 | ); 395 | INFOPLIST_FILE = SwiftIvarTypeDetectorTests/Info.plist; 396 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 397 | METAL_ENABLE_DEBUG_INFO = NO; 398 | PRODUCT_NAME = "$(TARGET_NAME)"; 399 | }; 400 | name = Release; 401 | }; 402 | /* End XCBuildConfiguration section */ 403 | 404 | /* Begin XCConfigurationList section */ 405 | E87C2CF3196F9AED009783E4 /* Build configuration list for PBXProject "SwiftIvarTypeDetector" */ = { 406 | isa = XCConfigurationList; 407 | buildConfigurations = ( 408 | E87C2D0D196F9AED009783E4 /* Debug */, 409 | E87C2D0E196F9AED009783E4 /* Release */, 410 | ); 411 | defaultConfigurationIsVisible = 0; 412 | defaultConfigurationName = Release; 413 | }; 414 | E87C2D0F196F9AED009783E4 /* Build configuration list for PBXNativeTarget "SwiftIvarTypeDetector" */ = { 415 | isa = XCConfigurationList; 416 | buildConfigurations = ( 417 | E87C2D10196F9AED009783E4 /* Debug */, 418 | E87C2D11196F9AED009783E4 /* Release */, 419 | ); 420 | defaultConfigurationIsVisible = 0; 421 | defaultConfigurationName = Release; 422 | }; 423 | E87C2D12196F9AED009783E4 /* Build configuration list for PBXNativeTarget "SwiftIvarTypeDetectorTests" */ = { 424 | isa = XCConfigurationList; 425 | buildConfigurations = ( 426 | E87C2D13196F9AED009783E4 /* Debug */, 427 | E87C2D14196F9AED009783E4 /* Release */, 428 | ); 429 | defaultConfigurationIsVisible = 0; 430 | defaultConfigurationName = Release; 431 | }; 432 | /* End XCConfigurationList section */ 433 | }; 434 | rootObject = E87C2CF0196F9AED009783E4 /* Project object */; 435 | } 436 | -------------------------------------------------------------------------------- /SwiftIvarTypeDetector.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SwiftIvarTypeDetector/Detector.h: -------------------------------------------------------------------------------- 1 | // 2 | // Detector.h 3 | // SwiftIvarTypeDetector 4 | // 5 | // Created by JP Simard on 7/10/14. 6 | // Copyright (c) 2014 Realm. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface Detector : NSObject 12 | 13 | + (NSArray *)propertiesForClass:(Class)aClass; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /SwiftIvarTypeDetector/Detector.m: -------------------------------------------------------------------------------- 1 | // 2 | // Detector.m 3 | // SwiftIvarTypeDetector 4 | // 5 | // Created by JP Simard on 7/10/14. 6 | // Copyright (c) 2014 Realm. All rights reserved. 7 | // 8 | 9 | #import "Detector.h" 10 | #import 11 | 12 | #pragma mark - Swift ivar encoding detection 13 | 14 | #import "IvarAccess.h" 15 | 16 | @implementation Detector 17 | 18 | + (NSArray *)propertiesForClass:(Class)aClass { 19 | NSMutableArray *properties = [NSMutableArray array]; 20 | unsigned int ivarCount; 21 | Ivar *ivars = class_copyIvarList(aClass, &ivarCount); 22 | for (unsigned int i = 0; i < ivarCount; i++) { 23 | NSString *name = [NSString stringWithUTF8String:ivar_getName(ivars[i])]; 24 | NSString *typeEncoding = [NSString stringWithCString:ivar_getTypeEncodingSwift(ivars[i], aClass) encoding:NSUTF8StringEncoding]; 25 | [properties addObject:@{@"name": name, @"typeEncoding": typeEncoding}]; 26 | } 27 | return properties; 28 | } 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /SwiftIvarTypeDetector/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | io.realm.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSHumanReadableCopyright 24 | Copyright © 2014 Realm. All rights reserved. 25 | NSPrincipalClass 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /SwiftIvarTypeDetector/IvarAccess.h: -------------------------------------------------------------------------------- 1 | // 2 | // IvarAccess.h 3 | // XprobePlugin 4 | // 5 | // Generic access to get/set ivars - functions so they work with Swift. 6 | // 7 | // $Id: //depot/XprobePlugin/Classes/IvarAccess.h#5 $ 8 | // 9 | // Source Repo: 10 | // https://github.com/johnno1962/Xprobe/blob/master/Classes/IvarAccess.h 11 | // 12 | // Created by John Holdsworth on 16/05/2015. 13 | // Copyright (c) 2015 John Holdsworth. All rights reserved. 14 | // 15 | 16 | /* 17 | 18 | This file has the MIT License (MIT) 19 | 20 | Copyright (c) 2015 John Holdsworth 21 | 22 | Permission is hereby granted, free of charge, to any person obtaining a copy 23 | of this software and associated documentation files (the "Software"), to deal 24 | in the Software without restriction, including without limitation the rights 25 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 26 | copies of the Software, and to permit persons to whom the Software is 27 | furnished to do so, subject to the following conditions: 28 | 29 | The above copyright notice and this permission notice shall be included in all 30 | copies or substantial portions of the Software. 31 | 32 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 33 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 34 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 35 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 36 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 37 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 38 | SOFTWARE. 39 | 40 | */ 41 | 42 | #ifndef _IvarAccess_h 43 | #define _IvarAccess_h 44 | 45 | #import 46 | 47 | #if TARGET_OS_IPHONE 48 | #import 49 | #else 50 | #import 51 | #endif 52 | 53 | @interface XprobeSwift : NSObject 54 | + (NSString *)convert:(void *)stringPtr; 55 | @end 56 | 57 | NSString *utf8String( const char *chars ) { 58 | return chars ? [NSString stringWithUTF8String:chars] : @""; 59 | } 60 | 61 | static const char *isOOType( const char *type ) { 62 | return strncmp( type, "{OO", 3 ) == 0 ? strstr( type, "\"ref\"" ) : NULL; 63 | } 64 | 65 | static BOOL isCFType( const char *type ) { 66 | return type && strncmp( type, "^{__CF", 6 ) == 0; 67 | } 68 | 69 | #pragma mark ivar_getTypeEncoding() for swift 70 | 71 | // From Jay Freeman's https://www.youtube.com/watch?v=Ii-02vhsdVk 72 | 73 | struct _swift_data { 74 | unsigned long flags; 75 | const char *className; 76 | int fieldcount, flags2; 77 | const char *ivarNames; 78 | struct _swift_field **(*get_field_data)(); 79 | }; 80 | 81 | struct _swift_class { 82 | union { 83 | Class meta; 84 | unsigned long flags; 85 | }; 86 | Class supr; 87 | void *buckets, *vtable, *pdata; 88 | int f1, f2; // added for Beta5 89 | int size, tos, mdsize, eight; 90 | struct _swift_data *swiftData; 91 | IMP dispatch[1]; 92 | }; 93 | 94 | struct _swift_field { 95 | union { 96 | Class meta; 97 | unsigned long flags; 98 | }; 99 | union { 100 | struct _swift_field *typeInfo; 101 | const char *typeIdent; 102 | Class objcClass; 103 | }; 104 | void *unknown; 105 | struct _swift_field *optional; 106 | }; 107 | 108 | static struct _swift_class *isSwift( Class aClass ) { 109 | struct _swift_class *swiftClass = (__bridge struct _swift_class *)aClass; 110 | return (uintptr_t)swiftClass->pdata & 0x1 ? swiftClass : NULL; 111 | } 112 | 113 | static const char *strfmt( NSString *fmt, ... ) NS_FORMAT_FUNCTION(1,2); 114 | static const char *strfmt( NSString *fmt, ... ) { 115 | va_list argp; 116 | va_start(argp, fmt); 117 | return strdup( [[[NSString alloc] initWithFormat:fmt arguments:argp] UTF8String] ); 118 | } 119 | 120 | static const char *typeInfoForClass( Class aClass, const char *optionals ) { 121 | return strfmt( @"@\"%@\"%s", NSStringFromClass(aClass), optionals ); 122 | } 123 | 124 | static const char *skipSwift( const char *typeIdent ) { 125 | while ( isalpha( *typeIdent ) ) 126 | typeIdent++; 127 | while ( isnumber( *typeIdent ) ) 128 | typeIdent++; 129 | return typeIdent; 130 | } 131 | 132 | const char *ivar_getTypeEncodingSwift( Ivar ivar, Class aClass ) { 133 | struct _swift_class *swiftClass = isSwift( aClass ); 134 | if ( !swiftClass ) 135 | return ivar_getTypeEncoding( ivar ); 136 | 137 | struct _swift_data *swiftData = swiftClass->swiftData; 138 | const char *nameptr = swiftData->ivarNames; 139 | const char *name = ivar_getName(ivar); 140 | int ivarIndex; 141 | 142 | for ( ivarIndex=0 ; ivarIndex < swiftData->fieldcount ; ivarIndex++ ) 143 | if ( strcmp(name,nameptr) == 0 ) 144 | break; 145 | else 146 | nameptr += strlen(nameptr)+1; 147 | 148 | if ( ivarIndex == swiftData->fieldcount ) 149 | return NULL; 150 | 151 | struct _swift_field *field0 = swiftData->get_field_data()[ivarIndex], *field = field0; 152 | char optionals[100] = "", *optr = optionals; 153 | 154 | // unpack any optionals 155 | while ( field->flags == 0x2 ) { 156 | if ( field->optional ) { 157 | field = field->optional; 158 | *optr++ = '?'; 159 | *optr = '\000'; 160 | } 161 | else 162 | return strfmt( @"%s%s", field->typeInfo->typeIdent, optionals ); 163 | } 164 | 165 | if ( field->flags == 0x1 ) { // rawtype 166 | const char *typeIdent = field->typeInfo->typeIdent; 167 | if ( typeIdent[0] == 'V' ) { 168 | if ( typeIdent[2] == 'C' ) 169 | return strfmt(@"{%@}%s", utf8String( skipSwift( typeIdent ) ), optionals ); 170 | else 171 | return strfmt(@"{%@}%s", utf8String( skipSwift( skipSwift( typeIdent ) ) ), optionals ); 172 | } 173 | else 174 | return field->typeInfo->typeIdent+1; 175 | } 176 | else if ( field->flags == 0xa ) // function 177 | return strfmt( @"^{Block}%s", optionals ); 178 | else if ( field->flags == 0xc ) // protocol 179 | return strfmt( @"@\"<%@>\"%s", utf8String( field->optional->typeIdent ), optionals ); 180 | else if ( field->flags == 0xe ) // objc class 181 | return typeInfoForClass( field->objcClass, optionals ); 182 | else if ( field->flags == 0x10 ) // pointer 183 | return strfmt( @"^{%@}%s", utf8String( skipSwift( field->typeIdent ?: "??" ) ), optionals ); 184 | else if ( (field->flags & 0xff) == 0x55 ) // enum? 185 | return strfmt( @"e%s", optionals ); 186 | else if ( field->flags < 0x100 || field->flags & 0x3 ) // unknown/bad isa 187 | return strfmt( @"?FLAGS#%lx(%p)%s", field->flags, field, optionals ); 188 | else // swift class 189 | return typeInfoForClass( (__bridge Class)field, optionals ); 190 | } 191 | 192 | #pragma mark generic ivar/method access 193 | 194 | static NSString *trapped = @"#INVALID", *notype = @"#TYPE"; 195 | 196 | NSString *xswiftString( void *iptr ) { 197 | static Class xprobeSwift; 198 | if ( !xprobeSwift && !(xprobeSwift = objc_getClass("XprobeSwift")) ) { 199 | #ifdef XPROBE_MAGIC 200 | NSBundle *thisBundle = [NSBundle bundleForClass:[Xprobe class]]; 201 | NSString *bundlePath = [[thisBundle bundlePath] stringByAppendingPathComponent:@"XprobeSwift.loader"]; 202 | if ( ![[NSBundle bundleWithPath:bundlePath] load] ) 203 | NSLog( @"Xprobe: Could not load XprobeSwift bundle: %@", bundlePath ); 204 | xprobeSwift = objc_getClass("XprobeSwift"); 205 | #endif 206 | } 207 | return xprobeSwift ? [NSString stringWithFormat:@"\"%@\"", [xprobeSwift convert:iptr]] : @"unavailable"; 208 | } 209 | 210 | static jmp_buf jmp_env; 211 | 212 | static void handler( int sig ) { 213 | longjmp( jmp_env, sig ); 214 | } 215 | 216 | int xprotect( void (^blockToProtect)() ) { 217 | void (*savetrap)(int) = signal( SIGTRAP, handler ); 218 | void (*savesegv)(int) = signal( SIGSEGV, handler ); 219 | void (*savebus )(int) = signal( SIGBUS, handler ); 220 | 221 | int signum; 222 | switch ( signum = setjmp( jmp_env ) ) { 223 | case 0: 224 | blockToProtect(); 225 | break; 226 | default: 227 | #ifdef XPROBE_MAGIC 228 | [Xprobe writeString:[NSString stringWithFormat:@"SIGNAL: %d", signum]]; 229 | #else 230 | NSLog( @"SIGNAL: %d", signum ); 231 | #endif 232 | } 233 | 234 | signal( SIGBUS, savebus ); 235 | signal( SIGSEGV, savesegv ); 236 | signal( SIGTRAP, savetrap ); 237 | return signum; 238 | } 239 | 240 | id xvalueForPointer( id self, void *iptr, const char *type ) { 241 | if ( !type ) 242 | return notype; 243 | switch ( type[0] ) { 244 | case 'V': 245 | case 'v': return @"void"; 246 | 247 | case 'b': // for now, for swift 248 | case 'B': return @(*(bool *)iptr);// ? @"true" : @"false"; 249 | 250 | case 'c': return @(*(char *)iptr); 251 | case 'C': return [NSString stringWithFormat:@"0x%x", *(unsigned char *)iptr]; 252 | 253 | case 's': return @(*(short *)iptr); 254 | case 'S': return isSwift( [self class] ) ? xswiftString( iptr ) : 255 | [NSString stringWithFormat:@"0x%x", *(unsigned short *)iptr]; 256 | 257 | case 'e': return @(*(int *)iptr); 258 | case 'f': return @(*(float *)iptr); 259 | case 'd': return @(*(double *)iptr); 260 | 261 | case 'I': return [NSString stringWithFormat:@"0x%x", *(unsigned *)iptr]; 262 | case 'i': 263 | #ifdef __LP64__ 264 | if ( !isSwift( [self class] ) ) 265 | #endif 266 | return @(*(int *)iptr); 267 | 268 | #ifndef __LP64__ 269 | case 'q': return @(*(long long *)iptr); 270 | #else 271 | case 'q': 272 | #endif 273 | case 'l': return @(*(long *)iptr); 274 | #ifndef __LP64__ 275 | case 'Q': return @(*(unsigned long long *)iptr); 276 | #else 277 | case 'Q': 278 | #endif 279 | case 'L': return @(*(unsigned long *)iptr); 280 | 281 | case '@': { 282 | __block id out = trapped; 283 | 284 | xprotect( ^{ 285 | uintptr_t uptr = *(uintptr_t *)iptr; 286 | if ( !uptr ) 287 | out = nil; 288 | else if ( uptr & 0xffffffff ) { 289 | id obj = *(const id *)iptr; 290 | #ifdef XPROBE_MAGIC 291 | [obj description]; 292 | #endif 293 | out = obj; 294 | } 295 | } ); 296 | 297 | return out; 298 | } 299 | case ':': return [NSString stringWithFormat:@"@selector(%@)", 300 | NSStringFromSelector(*(SEL *)iptr)]; 301 | case '#': { 302 | Class aClass = *(const Class *)iptr; 303 | return aClass ? [NSString stringWithFormat:@"[%@ class]", 304 | NSStringFromClass(aClass)] : @"Nil"; 305 | } 306 | case '^': 307 | if ( isCFType( type ) ) { 308 | char buff[100]; 309 | strcpy(buff, "@\"NS" ); 310 | strcat(buff,type+6); 311 | strcpy(strchr(buff,'='),"\""); 312 | return xvalueForPointer( self, iptr, buff ); 313 | } 314 | return [NSValue valueWithPointer:*(void **)iptr]; 315 | 316 | case '{': @try { 317 | const char *ooType = isOOType( type ); 318 | if ( ooType ) 319 | return xvalueForPointer( self, iptr, ooType+5 ); 320 | if ( type[1] == '?' ) 321 | return xvalueForPointer( self, iptr, "I" ); 322 | 323 | // remove names for valueWithBytes:objCType: 324 | char cleanType[1000], *tptr = cleanType; 325 | while ( *type ) 326 | if ( *type == '"' ) { 327 | while ( *++type != '"' ) 328 | ; 329 | type++; 330 | } 331 | else 332 | *tptr++ = *type++; 333 | *tptr = '\000'; 334 | 335 | // for incomplete Swift encodings 336 | if ( strchr( cleanType, '=' ) ) 337 | ; 338 | else if ( strcmp(cleanType,"{CGFloat}") == 0 ) 339 | return @(*(CGFloat *)iptr); 340 | else if ( strcmp(cleanType,"{CGPoint}") == 0 ) 341 | strcpy( cleanType, @encode(CGPoint) ); 342 | else if ( strcmp(cleanType,"{CGSize}") == 0 ) 343 | strcpy( cleanType, @encode(CGSize) ); 344 | else if ( strcmp(cleanType,"{CGRect}") == 0 ) 345 | strcpy( cleanType, @encode(CGRect) ); 346 | #if TARGET_OS_IPHONE 347 | else if ( strcmp(cleanType,"{UIOffset}") == 0 ) 348 | strcpy( cleanType, @encode(UIOffset) ); 349 | else if ( strcmp(cleanType,"{UIEdgeInsets}") == 0 ) 350 | strcpy( cleanType, @encode(UIEdgeInsets) ); 351 | #else 352 | else if ( strcmp(cleanType,"{NSPoint}") == 0 ) 353 | strcpy( cleanType, @encode(NSPoint) ); 354 | else if ( strcmp(cleanType,"{NSSize}") == 0 ) 355 | strcpy( cleanType, @encode(NSSize) ); 356 | else if ( strcmp(cleanType,"{NSRect}") == 0 ) 357 | strcpy( cleanType, @encode(NSRect) ); 358 | #endif 359 | else if ( strcmp(cleanType,"{CGAffineTransform}") == 0 ) 360 | strcpy( cleanType, @encode(CGAffineTransform) ); 361 | 362 | return [NSValue valueWithBytes:iptr objCType:cleanType]; 363 | } 364 | @catch ( NSException *e ) { 365 | return @"raised exception"; 366 | } 367 | case '*': { 368 | const char *ptr = *(const char **)iptr; 369 | return ptr ? utf8String( ptr ) : @"NULL"; 370 | } 371 | #if 0 372 | case 'b': 373 | return [NSString stringWithFormat:@"0x%08x", *(int *)iptr]; 374 | #endif 375 | default: 376 | return @"unknown"; 377 | } 378 | } 379 | 380 | id xvalueForIvarType( id self, Ivar ivar, const char *type, Class aClass ) { 381 | void *iptr = (char *)(__bridge void *)self + ivar_getOffset(ivar); 382 | return xvalueForPointer( self, iptr, type ); 383 | } 384 | 385 | id xvalueForIvar( id self, Ivar ivar, Class aClass ) { 386 | //NSLog( @"%p %p %p %s %s %s", aClass, ivar, isSwift(aClass), ivar_getName(ivar), ivar_getTypeEncoding(ivar), ivar_getTypeEncodingSwift(ivar, aClass) ); 387 | return xvalueForIvarType( self, ivar, ivar_getTypeEncodingSwift(ivar, aClass), aClass ); 388 | } 389 | 390 | static NSString *invocationException; 391 | 392 | id xvalueForMethod( id self, Method method ) { 393 | @try { 394 | const char *type = method_getTypeEncoding(method); 395 | NSMethodSignature *sig = [NSMethodSignature signatureWithObjCTypes:type]; 396 | NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:sig]; 397 | [invocation setSelector:method_getName(method)]; 398 | [invocation invokeWithTarget:self]; 399 | 400 | NSUInteger size = 0, align; 401 | const char *returnType = [sig methodReturnType]; 402 | NSGetSizeAndAlignment(returnType, &size, &align); 403 | 404 | char buffer[size]; 405 | if ( returnType[0] != 'v' ) 406 | [invocation getReturnValue:buffer]; 407 | return xvalueForPointer( self, buffer, returnType ); 408 | } 409 | @catch ( NSException *e ) { 410 | NSLog( @"Xprobe: exception on invoke: %@", e ); 411 | return invocationException = [e description]; 412 | } 413 | } 414 | 415 | BOOL xvalueUpdateIvar( id self, Ivar ivar, NSString *value ) { 416 | const char *iptr = (char *)(__bridge void *)self + ivar_getOffset(ivar); 417 | const char *type = ivar_getTypeEncodingSwift(ivar,[self class]); 418 | switch ( type[0] ) { 419 | case 'b': // Swift 420 | case 'B': *(bool *)iptr = [value boolValue]; break; 421 | case 'c': *(char *)iptr = [value intValue]; break; 422 | case 'C': *(unsigned char *)iptr = [value intValue]; break; 423 | case 's': *(short *)iptr = [value intValue]; break; 424 | case 'S': *(unsigned short *)iptr = [value intValue]; break; 425 | case 'e': 426 | case 'i': *(int *)iptr = [value intValue]; break; 427 | case 'I': *(unsigned *)iptr = [value intValue]; break; 428 | case 'f': *(float *)iptr = [value floatValue]; break; 429 | case 'd': *(double *)iptr = [value doubleValue]; break; 430 | #ifndef __LP64__ 431 | case 'q': *(long long *)iptr = [value longLongValue]; break; 432 | #else 433 | case 'q': 434 | #endif 435 | case 'l': *(long *)iptr = (long)[value longLongValue]; break; 436 | #ifndef __LP64__ 437 | case 'Q': *(unsigned long long *)iptr = [value longLongValue]; break; 438 | #else 439 | case 'Q': 440 | #endif 441 | case 'L': *(unsigned long *)iptr = (unsigned long)[value longLongValue]; break; 442 | case ':': *(SEL *)iptr = NSSelectorFromString(value); break; 443 | default: 444 | NSLog( @"Xprobe: update of unknown type: %s", type ); 445 | return FALSE; 446 | } 447 | 448 | return TRUE; 449 | } 450 | 451 | #pragma mark HTML representation of type 452 | 453 | NSString *xlinkForProtocol( NSString *protocolName ) { 454 | return [NSString stringWithFormat:@"%@", 456 | protocolName, protocolName, protocolName]; 457 | } 458 | 459 | NSString *xtype( const char *type ); 460 | 461 | NSString *xtypeStar( const char *type, const char *star ) { 462 | if ( type[-1] == '@' ) { 463 | if ( type[0] != '"' ) 464 | return @"id"; 465 | else if ( type[1] == '<' ) 466 | type++; 467 | } 468 | if ( type[-1] == '^' && type[0] != '{' ) 469 | return [xtype( type ) stringByAppendingString:@" *"]; 470 | 471 | const char *end = ++type; 472 | if ( *end == '?' ) 473 | end = end+strlen(end); 474 | else 475 | while ( isalnum(*end) || *end == '_' || *end == ',' || *end == '.' || *end < 0 ) 476 | end++; 477 | NSData *data = [NSData dataWithBytesNoCopy:(void *)type length:end-type freeWhenDone:NO]; 478 | NSString *typeName = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 479 | if ( type[-1] == '<' ) 480 | return [NSString stringWithFormat:@"id<%@>", 481 | xlinkForProtocol( typeName )]; 482 | else { 483 | return [NSString stringWithFormat:@"%@%s", 485 | typeName, typeName, typeName, star]; 486 | } 487 | } 488 | 489 | NSString *xtype_( const char *type ) { 490 | if ( !type ) 491 | return @"notype"; 492 | switch ( type[0] ) { 493 | case 'V': return @"oneway void"; 494 | case 'v': return @"void"; 495 | case 'a': return @"Array<?>"; 496 | case 'b': return @"Bool"; 497 | case 'B': return @"bool"; 498 | case 'c': return @"char"; 499 | case 'C': return @"unsigned char"; 500 | case 's': return @"short"; 501 | case 'S': return type[-1] != 'S' ? @"unsigned short" : @"String"; 502 | case 'e': return @"enum"; 503 | case 'i': return @"int"; 504 | case 'I': return @"unsigned"; 505 | case 'f': return @"float"; 506 | case 'd': return @"double"; 507 | #ifndef __LP64__ 508 | case 'q': return @"long long"; 509 | #else 510 | case 'q': 511 | #endif 512 | case 'l': return @"long"; 513 | #ifndef __LP64__ 514 | case 'Q': return @"unsigned long long"; 515 | #else 516 | case 'Q': 517 | #endif 518 | case 'L': return @"unsigned long"; 519 | case ':': return @"SEL"; 520 | case '#': return @"Class"; 521 | case '@': return xtypeStar( type+1, " *" ); 522 | case '^': return xtypeStar( type+1, " *" ); 523 | case '{': return xtypeStar( type, "" ); 524 | case '[': { 525 | int dim = atoi( type+1 ); 526 | while ( isnumber( *++type ) ) 527 | ; 528 | return [NSString stringWithFormat:@"%@[%d]", xtype( type ), dim]; 529 | } 530 | case 'r': 531 | return [@"const " stringByAppendingString:xtype( type+1 )]; 532 | case '*': return @"char *"; 533 | default: 534 | return utf8String( type ); //@"id"; 535 | } 536 | } 537 | 538 | NSString *xtype( const char *type ) { 539 | NSString *typeStr = xtype_( type ); 540 | return [NSString stringWithFormat:@"%@", 541 | [typeStr hasSuffix:@"*"] ? @"classStyle" : @"typeStyle", type, typeStr]; 542 | } 543 | 544 | #endif 545 | -------------------------------------------------------------------------------- /SwiftIvarTypeDetector/SwiftIvarTypeDetector.h: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftIvarTypeDetector.h 3 | // SwiftIvarTypeDetector 4 | // 5 | // Created by JP Simard on 7/10/14. 6 | // Copyright (c) 2014 Realm. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import 12 | -------------------------------------------------------------------------------- /SwiftIvarTypeDetectorTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | io.realm.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /SwiftIvarTypeDetectorTests/SwiftIvarTypeDetectorTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftIvarTypeDetectorTests.swift 3 | // SwiftIvarTypeDetector 4 | // 5 | // Created by JP Simard on 7/10/14. 6 | // Copyright (c) 2014 Realm. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | import SwiftIvarTypeDetector 11 | 12 | class GenericClass {} 13 | 14 | class SimpleClass: NSObject {} 15 | 16 | class ParentClass { 17 | var boolCol = false 18 | var intCol = 0 19 | var floatCol = 0 as Float 20 | var doubleCol = 0.0 21 | var stringCol = "" 22 | var rectCol = CGRectMake(1.0, 2.0, 3.0, 4.0) 23 | var simpleCol = SimpleClass() 24 | var genericCol = GenericClass() 25 | } 26 | 27 | class SwiftIvarTypeDetectorTests: XCTestCase { 28 | 29 | func testGenericPropertyType() { 30 | let properties = Detector.propertiesForClass(ParentClass.self) 31 | print("properties: \(properties)") 32 | XCTAssertNotNil(properties, "class should have properties") 33 | } 34 | } 35 | --------------------------------------------------------------------------------