├── .gitignore ├── .swiftpm └── xcode │ └── package.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ └── IDEWorkspaceChecks.plist ├── DebugFrame.podspec ├── Example ├── Example.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── Example.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── Example │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ ├── Contents.json │ │ ├── first.colorset │ │ │ └── Contents.json │ │ ├── second.colorset │ │ │ └── Contents.json │ │ └── third.colorset │ │ │ └── Contents.json │ ├── ContentView.swift │ ├── ExampleApp.swift │ └── Preview Content │ │ └── Preview Assets.xcassets │ │ └── Contents.json ├── ExampleTests │ ├── ContentViewTests.swift │ ├── ViewImageConfig.swift │ └── __Snapshots__ │ │ └── ContentViewTests │ │ └── test_body_loaded.1.png ├── Podfile └── Podfile.lock ├── License ├── Package.swift ├── README.md └── Source ├── DebugFrame.xcodeproj ├── project.pbxproj └── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ └── IDEWorkspaceChecks.plist └── DebugFrame ├── DebugFrame.h └── DebugFrame.swift /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | # Build generated 3 | build/ 4 | DerivedData/ 5 | Package.resolved 6 | 7 | # Various settings 8 | *.pbxuser 9 | !default.pbxuser 10 | *.mode1v3 11 | !default.mode1v3 12 | *.mode2v3 13 | !default.mode2v3 14 | *.perspectivev3 15 | !default.perspectivev3 16 | xcuserdata/ 17 | 18 | # Other 19 | *.moved-aside 20 | *.xcuserstate 21 | 22 | # Obj-C/Swift specific 23 | *.hmap 24 | *.ipa 25 | *.dSYM.zip 26 | *.dSYM 27 | 28 | # Playgrounds 29 | timeline.xctimeline 30 | playground.xcworkspace 31 | 32 | # CocoaPods 33 | Pods/ 34 | 35 | # Carthage 36 | Carthage/Build 37 | Carthage/Checkouts 38 | 39 | # development 40 | 41 | logs/* 42 | tmp/* 43 | 44 | # AppCode 45 | 46 | .idea/ 47 | 48 | # fastlane 49 | 50 | **/fastlane/report.xml 51 | **/fastlane/README.md 52 | **/fastlane/Preview.html 53 | **/fastlane/screenshots/**/*.png 54 | **/fastlane/test_output 55 | 56 | ## GitLab CI 57 | 58 | .bundle/ 59 | vendor/ 60 | 61 | Brewfile.lock.json -------------------------------------------------------------------------------- /.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /DebugFrame.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |spec| 2 | spec.name = "DebugFrame" 3 | spec.version = "2.2.1" 4 | spec.summary = "Debug frame modifier for SwiftUI views." 5 | spec.homepage = "https://github.com/vdshko/DebugFrame.git" 6 | spec.license = { :type => "MIT", :file => "License" } 7 | spec.author = { "Vladislav Shkodich" => "vladislavshkodich@gmail.com" } 8 | spec.frameworks = 'Foundation' 9 | spec.source = { :git => "https://github.com/vdshko/DebugFrame.git", :tag => "#{spec.version}" } 10 | spec.source_files = 'Source/DebugFrame/**/*.swift' 11 | spec.ios.deployment_target = "14.0" 12 | spec.osx.deployment_target = "11.0" 13 | spec.swift_versions = "5.0" 14 | end 15 | -------------------------------------------------------------------------------- /Example/Example.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 56; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 6F81C2FF859C203BCFCEACC4 /* Pods_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 08076DBEAB5F41E6D8882C36 /* Pods_Example.framework */; }; 11 | A165D22D295079D200F0FC7C /* ExampleApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = A165D22C295079D200F0FC7C /* ExampleApp.swift */; }; 12 | A165D22F295079D200F0FC7C /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A165D22E295079D200F0FC7C /* ContentView.swift */; }; 13 | A165D231295079D400F0FC7C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A165D230295079D400F0FC7C /* Assets.xcassets */; }; 14 | A165D234295079D400F0FC7C /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A165D233295079D400F0FC7C /* Preview Assets.xcassets */; }; 15 | A165D23E295079D400F0FC7C /* ContentViewTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A165D23D295079D400F0FC7C /* ContentViewTests.swift */; }; 16 | A17D74602950CC5800933F95 /* ViewImageConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = A17D745F2950CC5800933F95 /* ViewImageConfig.swift */; }; 17 | A4837229CBE148E914432AD4 /* Pods_ExampleTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2ADDD86C0D96ED43E014A84F /* Pods_ExampleTests.framework */; }; 18 | /* End PBXBuildFile section */ 19 | 20 | /* Begin PBXContainerItemProxy section */ 21 | A165D23A295079D400F0FC7C /* PBXContainerItemProxy */ = { 22 | isa = PBXContainerItemProxy; 23 | containerPortal = A165D221295079D200F0FC7C /* Project object */; 24 | proxyType = 1; 25 | remoteGlobalIDString = A165D228295079D200F0FC7C; 26 | remoteInfo = Example; 27 | }; 28 | /* End PBXContainerItemProxy section */ 29 | 30 | /* Begin PBXFileReference section */ 31 | 08076DBEAB5F41E6D8882C36 /* Pods_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 32 | 2ADDD86C0D96ED43E014A84F /* Pods_ExampleTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ExampleTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 33 | 35E69AD1F353F06B8DCCC4D6 /* Pods-ExampleTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ExampleTests.release.xcconfig"; path = "Target Support Files/Pods-ExampleTests/Pods-ExampleTests.release.xcconfig"; sourceTree = ""; }; 34 | 4545F90C046C815C9DEE9D3D /* Pods-Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Example.release.xcconfig"; path = "Target Support Files/Pods-Example/Pods-Example.release.xcconfig"; sourceTree = ""; }; 35 | 964E020197643C99E65E2548 /* Pods-Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Example.debug.xcconfig"; path = "Target Support Files/Pods-Example/Pods-Example.debug.xcconfig"; sourceTree = ""; }; 36 | A165D229295079D200F0FC7C /* Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Example.app; sourceTree = BUILT_PRODUCTS_DIR; }; 37 | A165D22C295079D200F0FC7C /* ExampleApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExampleApp.swift; sourceTree = ""; }; 38 | A165D22E295079D200F0FC7C /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; 39 | A165D230295079D400F0FC7C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 40 | A165D233295079D400F0FC7C /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; 41 | A165D239295079D400F0FC7C /* ExampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ExampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 42 | A165D23D295079D400F0FC7C /* ContentViewTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentViewTests.swift; sourceTree = ""; }; 43 | A17D745F2950CC5800933F95 /* ViewImageConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewImageConfig.swift; sourceTree = ""; }; 44 | BA45544DA9E91EA5BEE47DD5 /* Pods-ExampleTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ExampleTests.debug.xcconfig"; path = "Target Support Files/Pods-ExampleTests/Pods-ExampleTests.debug.xcconfig"; sourceTree = ""; }; 45 | /* End PBXFileReference section */ 46 | 47 | /* Begin PBXFrameworksBuildPhase section */ 48 | A165D226295079D200F0FC7C /* Frameworks */ = { 49 | isa = PBXFrameworksBuildPhase; 50 | buildActionMask = 2147483647; 51 | files = ( 52 | 6F81C2FF859C203BCFCEACC4 /* Pods_Example.framework in Frameworks */, 53 | ); 54 | runOnlyForDeploymentPostprocessing = 0; 55 | }; 56 | A165D236295079D400F0FC7C /* Frameworks */ = { 57 | isa = PBXFrameworksBuildPhase; 58 | buildActionMask = 2147483647; 59 | files = ( 60 | A4837229CBE148E914432AD4 /* Pods_ExampleTests.framework in Frameworks */, 61 | ); 62 | runOnlyForDeploymentPostprocessing = 0; 63 | }; 64 | /* End PBXFrameworksBuildPhase section */ 65 | 66 | /* Begin PBXGroup section */ 67 | 9310EE60B2952E8A9F0824D2 /* Pods */ = { 68 | isa = PBXGroup; 69 | children = ( 70 | BA45544DA9E91EA5BEE47DD5 /* Pods-ExampleTests.debug.xcconfig */, 71 | 35E69AD1F353F06B8DCCC4D6 /* Pods-ExampleTests.release.xcconfig */, 72 | 964E020197643C99E65E2548 /* Pods-Example.debug.xcconfig */, 73 | 4545F90C046C815C9DEE9D3D /* Pods-Example.release.xcconfig */, 74 | ); 75 | path = Pods; 76 | sourceTree = ""; 77 | }; 78 | A165D220295079D200F0FC7C = { 79 | isa = PBXGroup; 80 | children = ( 81 | A165D22B295079D200F0FC7C /* Example */, 82 | A165D23C295079D400F0FC7C /* ExampleTests */, 83 | A165D22A295079D200F0FC7C /* Products */, 84 | 9310EE60B2952E8A9F0824D2 /* Pods */, 85 | EBD2501ECFC7409D09848FEE /* Frameworks */, 86 | ); 87 | sourceTree = ""; 88 | }; 89 | A165D22A295079D200F0FC7C /* Products */ = { 90 | isa = PBXGroup; 91 | children = ( 92 | A165D229295079D200F0FC7C /* Example.app */, 93 | A165D239295079D400F0FC7C /* ExampleTests.xctest */, 94 | ); 95 | name = Products; 96 | sourceTree = ""; 97 | }; 98 | A165D22B295079D200F0FC7C /* Example */ = { 99 | isa = PBXGroup; 100 | children = ( 101 | A165D22C295079D200F0FC7C /* ExampleApp.swift */, 102 | A165D22E295079D200F0FC7C /* ContentView.swift */, 103 | A165D230295079D400F0FC7C /* Assets.xcassets */, 104 | A165D232295079D400F0FC7C /* Preview Content */, 105 | ); 106 | path = Example; 107 | sourceTree = ""; 108 | }; 109 | A165D232295079D400F0FC7C /* Preview Content */ = { 110 | isa = PBXGroup; 111 | children = ( 112 | A165D233295079D400F0FC7C /* Preview Assets.xcassets */, 113 | ); 114 | path = "Preview Content"; 115 | sourceTree = ""; 116 | }; 117 | A165D23C295079D400F0FC7C /* ExampleTests */ = { 118 | isa = PBXGroup; 119 | children = ( 120 | A165D23D295079D400F0FC7C /* ContentViewTests.swift */, 121 | A17D745F2950CC5800933F95 /* ViewImageConfig.swift */, 122 | ); 123 | path = ExampleTests; 124 | sourceTree = ""; 125 | }; 126 | EBD2501ECFC7409D09848FEE /* Frameworks */ = { 127 | isa = PBXGroup; 128 | children = ( 129 | 2ADDD86C0D96ED43E014A84F /* Pods_ExampleTests.framework */, 130 | 08076DBEAB5F41E6D8882C36 /* Pods_Example.framework */, 131 | ); 132 | name = Frameworks; 133 | sourceTree = ""; 134 | }; 135 | /* End PBXGroup section */ 136 | 137 | /* Begin PBXNativeTarget section */ 138 | A165D228295079D200F0FC7C /* Example */ = { 139 | isa = PBXNativeTarget; 140 | buildConfigurationList = A165D24D295079D400F0FC7C /* Build configuration list for PBXNativeTarget "Example" */; 141 | buildPhases = ( 142 | 3F46DCEFAE46A6F37D8572F1 /* [CP] Check Pods Manifest.lock */, 143 | A165D225295079D200F0FC7C /* Sources */, 144 | A165D226295079D200F0FC7C /* Frameworks */, 145 | A165D227295079D200F0FC7C /* Resources */, 146 | AF8BD0E3537EB06D8D1F952C /* [CP] Embed Pods Frameworks */, 147 | ); 148 | buildRules = ( 149 | ); 150 | dependencies = ( 151 | ); 152 | name = Example; 153 | productName = Example; 154 | productReference = A165D229295079D200F0FC7C /* Example.app */; 155 | productType = "com.apple.product-type.application"; 156 | }; 157 | A165D238295079D400F0FC7C /* ExampleTests */ = { 158 | isa = PBXNativeTarget; 159 | buildConfigurationList = A165D250295079D400F0FC7C /* Build configuration list for PBXNativeTarget "ExampleTests" */; 160 | buildPhases = ( 161 | 59BA1D337F5C88ACD5A0CB82 /* [CP] Check Pods Manifest.lock */, 162 | A165D235295079D400F0FC7C /* Sources */, 163 | A165D236295079D400F0FC7C /* Frameworks */, 164 | A165D237295079D400F0FC7C /* Resources */, 165 | 39DEADBC2B136C89A5F01175 /* [CP] Embed Pods Frameworks */, 166 | ); 167 | buildRules = ( 168 | ); 169 | dependencies = ( 170 | A165D23B295079D400F0FC7C /* PBXTargetDependency */, 171 | ); 172 | name = ExampleTests; 173 | productName = ExampleTests; 174 | productReference = A165D239295079D400F0FC7C /* ExampleTests.xctest */; 175 | productType = "com.apple.product-type.bundle.unit-test"; 176 | }; 177 | /* End PBXNativeTarget section */ 178 | 179 | /* Begin PBXProject section */ 180 | A165D221295079D200F0FC7C /* Project object */ = { 181 | isa = PBXProject; 182 | attributes = { 183 | BuildIndependentTargetsInParallel = 1; 184 | LastSwiftUpdateCheck = 1410; 185 | LastUpgradeCheck = 1410; 186 | TargetAttributes = { 187 | A165D228295079D200F0FC7C = { 188 | CreatedOnToolsVersion = 14.1; 189 | }; 190 | A165D238295079D400F0FC7C = { 191 | CreatedOnToolsVersion = 14.1; 192 | TestTargetID = A165D228295079D200F0FC7C; 193 | }; 194 | }; 195 | }; 196 | buildConfigurationList = A165D224295079D200F0FC7C /* Build configuration list for PBXProject "Example" */; 197 | compatibilityVersion = "Xcode 14.0"; 198 | developmentRegion = en; 199 | hasScannedForEncodings = 0; 200 | knownRegions = ( 201 | en, 202 | Base, 203 | ); 204 | mainGroup = A165D220295079D200F0FC7C; 205 | productRefGroup = A165D22A295079D200F0FC7C /* Products */; 206 | projectDirPath = ""; 207 | projectRoot = ""; 208 | targets = ( 209 | A165D228295079D200F0FC7C /* Example */, 210 | A165D238295079D400F0FC7C /* ExampleTests */, 211 | ); 212 | }; 213 | /* End PBXProject section */ 214 | 215 | /* Begin PBXResourcesBuildPhase section */ 216 | A165D227295079D200F0FC7C /* Resources */ = { 217 | isa = PBXResourcesBuildPhase; 218 | buildActionMask = 2147483647; 219 | files = ( 220 | A165D234295079D400F0FC7C /* Preview Assets.xcassets in Resources */, 221 | A165D231295079D400F0FC7C /* Assets.xcassets in Resources */, 222 | ); 223 | runOnlyForDeploymentPostprocessing = 0; 224 | }; 225 | A165D237295079D400F0FC7C /* Resources */ = { 226 | isa = PBXResourcesBuildPhase; 227 | buildActionMask = 2147483647; 228 | files = ( 229 | ); 230 | runOnlyForDeploymentPostprocessing = 0; 231 | }; 232 | /* End PBXResourcesBuildPhase section */ 233 | 234 | /* Begin PBXShellScriptBuildPhase section */ 235 | 39DEADBC2B136C89A5F01175 /* [CP] Embed Pods Frameworks */ = { 236 | isa = PBXShellScriptBuildPhase; 237 | buildActionMask = 2147483647; 238 | files = ( 239 | ); 240 | inputFileListPaths = ( 241 | "${PODS_ROOT}/Target Support Files/Pods-ExampleTests/Pods-ExampleTests-frameworks-${CONFIGURATION}-input-files.xcfilelist", 242 | ); 243 | name = "[CP] Embed Pods Frameworks"; 244 | outputFileListPaths = ( 245 | "${PODS_ROOT}/Target Support Files/Pods-ExampleTests/Pods-ExampleTests-frameworks-${CONFIGURATION}-output-files.xcfilelist", 246 | ); 247 | runOnlyForDeploymentPostprocessing = 0; 248 | shellPath = /bin/sh; 249 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ExampleTests/Pods-ExampleTests-frameworks.sh\"\n"; 250 | showEnvVarsInLog = 0; 251 | }; 252 | 3F46DCEFAE46A6F37D8572F1 /* [CP] Check Pods Manifest.lock */ = { 253 | isa = PBXShellScriptBuildPhase; 254 | buildActionMask = 2147483647; 255 | files = ( 256 | ); 257 | inputFileListPaths = ( 258 | ); 259 | inputPaths = ( 260 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 261 | "${PODS_ROOT}/Manifest.lock", 262 | ); 263 | name = "[CP] Check Pods Manifest.lock"; 264 | outputFileListPaths = ( 265 | ); 266 | outputPaths = ( 267 | "$(DERIVED_FILE_DIR)/Pods-Example-checkManifestLockResult.txt", 268 | ); 269 | runOnlyForDeploymentPostprocessing = 0; 270 | shellPath = /bin/sh; 271 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 272 | showEnvVarsInLog = 0; 273 | }; 274 | 59BA1D337F5C88ACD5A0CB82 /* [CP] Check Pods Manifest.lock */ = { 275 | isa = PBXShellScriptBuildPhase; 276 | buildActionMask = 2147483647; 277 | files = ( 278 | ); 279 | inputFileListPaths = ( 280 | ); 281 | inputPaths = ( 282 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 283 | "${PODS_ROOT}/Manifest.lock", 284 | ); 285 | name = "[CP] Check Pods Manifest.lock"; 286 | outputFileListPaths = ( 287 | ); 288 | outputPaths = ( 289 | "$(DERIVED_FILE_DIR)/Pods-ExampleTests-checkManifestLockResult.txt", 290 | ); 291 | runOnlyForDeploymentPostprocessing = 0; 292 | shellPath = /bin/sh; 293 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 294 | showEnvVarsInLog = 0; 295 | }; 296 | AF8BD0E3537EB06D8D1F952C /* [CP] Embed Pods Frameworks */ = { 297 | isa = PBXShellScriptBuildPhase; 298 | buildActionMask = 2147483647; 299 | files = ( 300 | ); 301 | inputFileListPaths = ( 302 | "${PODS_ROOT}/Target Support Files/Pods-Example/Pods-Example-frameworks-${CONFIGURATION}-input-files.xcfilelist", 303 | ); 304 | name = "[CP] Embed Pods Frameworks"; 305 | outputFileListPaths = ( 306 | "${PODS_ROOT}/Target Support Files/Pods-Example/Pods-Example-frameworks-${CONFIGURATION}-output-files.xcfilelist", 307 | ); 308 | runOnlyForDeploymentPostprocessing = 0; 309 | shellPath = /bin/sh; 310 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Example/Pods-Example-frameworks.sh\"\n"; 311 | showEnvVarsInLog = 0; 312 | }; 313 | /* End PBXShellScriptBuildPhase section */ 314 | 315 | /* Begin PBXSourcesBuildPhase section */ 316 | A165D225295079D200F0FC7C /* Sources */ = { 317 | isa = PBXSourcesBuildPhase; 318 | buildActionMask = 2147483647; 319 | files = ( 320 | A165D22F295079D200F0FC7C /* ContentView.swift in Sources */, 321 | A165D22D295079D200F0FC7C /* ExampleApp.swift in Sources */, 322 | ); 323 | runOnlyForDeploymentPostprocessing = 0; 324 | }; 325 | A165D235295079D400F0FC7C /* Sources */ = { 326 | isa = PBXSourcesBuildPhase; 327 | buildActionMask = 2147483647; 328 | files = ( 329 | A17D74602950CC5800933F95 /* ViewImageConfig.swift in Sources */, 330 | A165D23E295079D400F0FC7C /* ContentViewTests.swift in Sources */, 331 | ); 332 | runOnlyForDeploymentPostprocessing = 0; 333 | }; 334 | /* End PBXSourcesBuildPhase section */ 335 | 336 | /* Begin PBXTargetDependency section */ 337 | A165D23B295079D400F0FC7C /* PBXTargetDependency */ = { 338 | isa = PBXTargetDependency; 339 | target = A165D228295079D200F0FC7C /* Example */; 340 | targetProxy = A165D23A295079D400F0FC7C /* PBXContainerItemProxy */; 341 | }; 342 | /* End PBXTargetDependency section */ 343 | 344 | /* Begin XCBuildConfiguration section */ 345 | A165D24B295079D400F0FC7C /* Debug */ = { 346 | isa = XCBuildConfiguration; 347 | buildSettings = { 348 | ALWAYS_SEARCH_USER_PATHS = NO; 349 | CLANG_ANALYZER_NONNULL = YES; 350 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 351 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 352 | CLANG_ENABLE_MODULES = YES; 353 | CLANG_ENABLE_OBJC_ARC = YES; 354 | CLANG_ENABLE_OBJC_WEAK = YES; 355 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 356 | CLANG_WARN_BOOL_CONVERSION = YES; 357 | CLANG_WARN_COMMA = YES; 358 | CLANG_WARN_CONSTANT_CONVERSION = YES; 359 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 360 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 361 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 362 | CLANG_WARN_EMPTY_BODY = YES; 363 | CLANG_WARN_ENUM_CONVERSION = YES; 364 | CLANG_WARN_INFINITE_RECURSION = YES; 365 | CLANG_WARN_INT_CONVERSION = YES; 366 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 367 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 368 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 369 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 370 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 371 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 372 | CLANG_WARN_STRICT_PROTOTYPES = YES; 373 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 374 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 375 | CLANG_WARN_UNREACHABLE_CODE = YES; 376 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 377 | COPY_PHASE_STRIP = NO; 378 | DEBUG_INFORMATION_FORMAT = dwarf; 379 | ENABLE_STRICT_OBJC_MSGSEND = YES; 380 | ENABLE_TESTABILITY = YES; 381 | GCC_C_LANGUAGE_STANDARD = gnu11; 382 | GCC_DYNAMIC_NO_PIC = NO; 383 | GCC_NO_COMMON_BLOCKS = YES; 384 | GCC_OPTIMIZATION_LEVEL = 0; 385 | GCC_PREPROCESSOR_DEFINITIONS = ( 386 | "DEBUG=1", 387 | "$(inherited)", 388 | ); 389 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 390 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 391 | GCC_WARN_UNDECLARED_SELECTOR = YES; 392 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 393 | GCC_WARN_UNUSED_FUNCTION = YES; 394 | GCC_WARN_UNUSED_VARIABLE = YES; 395 | IPHONEOS_DEPLOYMENT_TARGET = 16.1; 396 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 397 | MTL_FAST_MATH = YES; 398 | ONLY_ACTIVE_ARCH = YES; 399 | SDKROOT = iphoneos; 400 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 401 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 402 | }; 403 | name = Debug; 404 | }; 405 | A165D24C295079D400F0FC7C /* Release */ = { 406 | isa = XCBuildConfiguration; 407 | buildSettings = { 408 | ALWAYS_SEARCH_USER_PATHS = NO; 409 | CLANG_ANALYZER_NONNULL = YES; 410 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 411 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 412 | CLANG_ENABLE_MODULES = YES; 413 | CLANG_ENABLE_OBJC_ARC = YES; 414 | CLANG_ENABLE_OBJC_WEAK = YES; 415 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 416 | CLANG_WARN_BOOL_CONVERSION = YES; 417 | CLANG_WARN_COMMA = YES; 418 | CLANG_WARN_CONSTANT_CONVERSION = YES; 419 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 420 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 421 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 422 | CLANG_WARN_EMPTY_BODY = YES; 423 | CLANG_WARN_ENUM_CONVERSION = YES; 424 | CLANG_WARN_INFINITE_RECURSION = YES; 425 | CLANG_WARN_INT_CONVERSION = YES; 426 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 427 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 428 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 429 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 430 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 431 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 432 | CLANG_WARN_STRICT_PROTOTYPES = YES; 433 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 434 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 435 | CLANG_WARN_UNREACHABLE_CODE = YES; 436 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 437 | COPY_PHASE_STRIP = NO; 438 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 439 | ENABLE_NS_ASSERTIONS = NO; 440 | ENABLE_STRICT_OBJC_MSGSEND = YES; 441 | GCC_C_LANGUAGE_STANDARD = gnu11; 442 | GCC_NO_COMMON_BLOCKS = YES; 443 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 444 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 445 | GCC_WARN_UNDECLARED_SELECTOR = YES; 446 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 447 | GCC_WARN_UNUSED_FUNCTION = YES; 448 | GCC_WARN_UNUSED_VARIABLE = YES; 449 | IPHONEOS_DEPLOYMENT_TARGET = 16.1; 450 | MTL_ENABLE_DEBUG_INFO = NO; 451 | MTL_FAST_MATH = YES; 452 | SDKROOT = iphoneos; 453 | SWIFT_COMPILATION_MODE = wholemodule; 454 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 455 | VALIDATE_PRODUCT = YES; 456 | }; 457 | name = Release; 458 | }; 459 | A165D24E295079D400F0FC7C /* Debug */ = { 460 | isa = XCBuildConfiguration; 461 | baseConfigurationReference = 964E020197643C99E65E2548 /* Pods-Example.debug.xcconfig */; 462 | buildSettings = { 463 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 464 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 465 | CODE_SIGN_STYLE = Automatic; 466 | CURRENT_PROJECT_VERSION = 1; 467 | DEVELOPMENT_ASSET_PATHS = "\"Example/Preview Content\""; 468 | DEVELOPMENT_TEAM = ""; 469 | ENABLE_PREVIEWS = YES; 470 | GENERATE_INFOPLIST_FILE = YES; 471 | INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; 472 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 473 | INFOPLIST_KEY_UILaunchScreen_Generation = YES; 474 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 475 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 476 | IPHONEOS_DEPLOYMENT_TARGET = 14.0; 477 | LD_RUNPATH_SEARCH_PATHS = ( 478 | "$(inherited)", 479 | "@executable_path/Frameworks", 480 | ); 481 | MARKETING_VERSION = 1.0; 482 | PRODUCT_BUNDLE_IDENTIFIER = com.vdshko.projects.DebugFrame.Example; 483 | PRODUCT_NAME = "$(TARGET_NAME)"; 484 | SWIFT_EMIT_LOC_STRINGS = YES; 485 | SWIFT_VERSION = 5.0; 486 | TARGETED_DEVICE_FAMILY = "1,2"; 487 | }; 488 | name = Debug; 489 | }; 490 | A165D24F295079D400F0FC7C /* Release */ = { 491 | isa = XCBuildConfiguration; 492 | baseConfigurationReference = 4545F90C046C815C9DEE9D3D /* Pods-Example.release.xcconfig */; 493 | buildSettings = { 494 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 495 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 496 | CODE_SIGN_STYLE = Automatic; 497 | CURRENT_PROJECT_VERSION = 1; 498 | DEVELOPMENT_ASSET_PATHS = "\"Example/Preview Content\""; 499 | DEVELOPMENT_TEAM = ""; 500 | ENABLE_PREVIEWS = YES; 501 | GENERATE_INFOPLIST_FILE = YES; 502 | INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; 503 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 504 | INFOPLIST_KEY_UILaunchScreen_Generation = YES; 505 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 506 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 507 | IPHONEOS_DEPLOYMENT_TARGET = 14.0; 508 | LD_RUNPATH_SEARCH_PATHS = ( 509 | "$(inherited)", 510 | "@executable_path/Frameworks", 511 | ); 512 | MARKETING_VERSION = 1.0; 513 | PRODUCT_BUNDLE_IDENTIFIER = com.vdshko.projects.DebugFrame.Example; 514 | PRODUCT_NAME = "$(TARGET_NAME)"; 515 | SWIFT_EMIT_LOC_STRINGS = YES; 516 | SWIFT_VERSION = 5.0; 517 | TARGETED_DEVICE_FAMILY = "1,2"; 518 | }; 519 | name = Release; 520 | }; 521 | A165D251295079D400F0FC7C /* Debug */ = { 522 | isa = XCBuildConfiguration; 523 | baseConfigurationReference = BA45544DA9E91EA5BEE47DD5 /* Pods-ExampleTests.debug.xcconfig */; 524 | buildSettings = { 525 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = "$(inherited)"; 526 | BUNDLE_LOADER = "$(TEST_HOST)"; 527 | CODE_SIGN_STYLE = Automatic; 528 | CURRENT_PROJECT_VERSION = 1; 529 | GENERATE_INFOPLIST_FILE = YES; 530 | IPHONEOS_DEPLOYMENT_TARGET = 14.0; 531 | MARKETING_VERSION = 1.0; 532 | PRODUCT_BUNDLE_IDENTIFIER = com.vdshko.projects.DebugFrame.ExampleTests; 533 | PRODUCT_NAME = "$(TARGET_NAME)"; 534 | SWIFT_EMIT_LOC_STRINGS = NO; 535 | SWIFT_VERSION = 5.0; 536 | TARGETED_DEVICE_FAMILY = "1,2"; 537 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Example"; 538 | }; 539 | name = Debug; 540 | }; 541 | A165D252295079D400F0FC7C /* Release */ = { 542 | isa = XCBuildConfiguration; 543 | baseConfigurationReference = 35E69AD1F353F06B8DCCC4D6 /* Pods-ExampleTests.release.xcconfig */; 544 | buildSettings = { 545 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = "$(inherited)"; 546 | BUNDLE_LOADER = "$(TEST_HOST)"; 547 | CODE_SIGN_STYLE = Automatic; 548 | CURRENT_PROJECT_VERSION = 1; 549 | GENERATE_INFOPLIST_FILE = YES; 550 | IPHONEOS_DEPLOYMENT_TARGET = 14.0; 551 | MARKETING_VERSION = 1.0; 552 | PRODUCT_BUNDLE_IDENTIFIER = com.vdshko.projects.DebugFrame.ExampleTests; 553 | PRODUCT_NAME = "$(TARGET_NAME)"; 554 | SWIFT_EMIT_LOC_STRINGS = NO; 555 | SWIFT_VERSION = 5.0; 556 | TARGETED_DEVICE_FAMILY = "1,2"; 557 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Example"; 558 | }; 559 | name = Release; 560 | }; 561 | /* End XCBuildConfiguration section */ 562 | 563 | /* Begin XCConfigurationList section */ 564 | A165D224295079D200F0FC7C /* Build configuration list for PBXProject "Example" */ = { 565 | isa = XCConfigurationList; 566 | buildConfigurations = ( 567 | A165D24B295079D400F0FC7C /* Debug */, 568 | A165D24C295079D400F0FC7C /* Release */, 569 | ); 570 | defaultConfigurationIsVisible = 0; 571 | defaultConfigurationName = Release; 572 | }; 573 | A165D24D295079D400F0FC7C /* Build configuration list for PBXNativeTarget "Example" */ = { 574 | isa = XCConfigurationList; 575 | buildConfigurations = ( 576 | A165D24E295079D400F0FC7C /* Debug */, 577 | A165D24F295079D400F0FC7C /* Release */, 578 | ); 579 | defaultConfigurationIsVisible = 0; 580 | defaultConfigurationName = Release; 581 | }; 582 | A165D250295079D400F0FC7C /* Build configuration list for PBXNativeTarget "ExampleTests" */ = { 583 | isa = XCConfigurationList; 584 | buildConfigurations = ( 585 | A165D251295079D400F0FC7C /* Debug */, 586 | A165D252295079D400F0FC7C /* Release */, 587 | ); 588 | defaultConfigurationIsVisible = 0; 589 | defaultConfigurationName = Release; 590 | }; 591 | /* End XCConfigurationList section */ 592 | }; 593 | rootObject = A165D221295079D200F0FC7C /* Project object */; 594 | } 595 | -------------------------------------------------------------------------------- /Example/Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/Example.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Example/Example.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Example/Example.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | } 8 | ], 9 | "info" : { 10 | "author" : "xcode", 11 | "version" : 1 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/first.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "srgb", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "0.780", 9 | "green" : "0.641", 10 | "red" : "0.736" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | } 15 | ], 16 | "info" : { 17 | "author" : "xcode", 18 | "version" : 1 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/second.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "srgb", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "0.651", 9 | "green" : "0.780", 10 | "red" : "0.580" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | } 15 | ], 16 | "info" : { 17 | "author" : "xcode", 18 | "version" : 1 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/third.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "srgb", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "0.378", 9 | "green" : "0.742", 10 | "red" : "0.780" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | } 15 | ], 16 | "info" : { 17 | "author" : "xcode", 18 | "version" : 1 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Example/Example/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // Example 4 | // 5 | // Created by Vladyslav Shkodych on 19.12.2022. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ContentView: View { 11 | 12 | var body: some View { 13 | VStack { 14 | title 15 | Spacer() 16 | rectangles 17 | Spacer() 18 | } 19 | .debugFrame(.size) 20 | .padding(20.0) 21 | .debugFrame() 22 | .padding(30.0) 23 | .background(Color.white) 24 | .ignoresSafeArea() 25 | } 26 | 27 | private var title: some View { 28 | VStack { 29 | Text("This is the Example of using \"DebugFrame\"") 30 | .multilineTextAlignment(.center) 31 | .font(.title) 32 | .foregroundColor(Color.primary) 33 | Image(systemName: "rectangle.dashed.and.paperclip") 34 | .resizable() 35 | .imageScale(.large) 36 | .frame(width: 100, height: 100) 37 | .foregroundColor(Color.red) 38 | } 39 | // .debugBackground() // uncomment to see in work 40 | } 41 | 42 | private var rectangles: some View { 43 | VStack { 44 | RoundedRectangle(cornerRadius: 4.0) 45 | .frame(width: 220.0, height: 100.0) 46 | .foregroundColor(Color("first")) 47 | .debugFrame(color: .black) 48 | HStack { 49 | Spacer() 50 | RoundedRectangle(cornerRadius: 4.0) 51 | .frame(width: 120.0, height: 150.0) 52 | .foregroundColor(Color("second")) 53 | .debugFrame(.size) 54 | .padding(.trailing, 25.0) 55 | } 56 | HStack { 57 | RoundedRectangle(cornerRadius: 4.0) 58 | .frame(width: 120.0, height: 100.0) 59 | .foregroundColor(Color("third")) 60 | .debugFrame(color: .white, .originX, .width) 61 | .padding(.leading, 20.0) 62 | Spacer() 63 | } 64 | } 65 | } 66 | } 67 | 68 | struct ContentView_Previews: PreviewProvider { 69 | 70 | static var previews: some View { 71 | ContentView() 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /Example/Example/ExampleApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ExampleApp.swift 3 | // Example 4 | // 5 | // Created by Vladyslav Shkodych on 19.12.2022. 6 | // 7 | 8 | import SwiftUI 9 | import DebugFrame 10 | 11 | @main 12 | struct ExampleApp: App { 13 | 14 | var body: some Scene { 15 | WindowGroup { 16 | ContentView() 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Example/Example/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Example/ExampleTests/ContentViewTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ExampleTests.swift 3 | // ExampleTests 4 | // 5 | // Created by Vladyslav Shkodych on 19.12.2022. 6 | // 7 | 8 | import XCTest 9 | import SwiftUI 10 | import SnapshotTesting 11 | @testable import Example 12 | 13 | final class ContentViewTests: XCTestCase { 14 | 15 | func test_body_loaded() { 16 | let view = ContentView_Previews.previews 17 | 18 | // iPhone 14 Pro 19 | assertSnapshot(matching: view, as: .main) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Example/ExampleTests/ViewImageConfig.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewImageConfig.swift 3 | // ExampleTests 4 | // 5 | // Created by Vladyslav Shkodych on 19.12.2022. 6 | // 7 | 8 | import Foundation 9 | import SwiftUI 10 | import UIKit 11 | import SnapshotTesting 12 | 13 | extension Snapshotting where Value: SwiftUI.View, Format == UIImage { 14 | 15 | public static var main: Snapshotting { 16 | return .main(precision: 0.99) 17 | } 18 | 19 | public static var mainWaiting: Snapshotting { 20 | return .wait(for: 0.05, on: .main) 21 | } 22 | 23 | public static func mainWaiting(for duration: TimeInterval = 0.05, precision: Float) -> Snapshotting { 24 | return .wait(for: duration, on: .main(precision: precision)) 25 | } 26 | 27 | public static func main(precision: Float) -> Snapshotting { 28 | return .image(precision: precision, layout: .device(config: .iPhone14Pro)) 29 | } 30 | } 31 | 32 | extension ViewImageConfig { 33 | 34 | public static let iPhone14Pro = ViewImageConfig.iPhone14Pro(.portrait) 35 | 36 | public static func iPhone14Pro(_ orientation: Orientation) -> ViewImageConfig { 37 | let safeArea: UIEdgeInsets 38 | let size: CGSize 39 | switch orientation { 40 | case .landscape: 41 | safeArea = .init(top: 0, left: 59, bottom: 21, right: 59) 42 | size = .init(width: 852, height: 393) 43 | case .portrait: 44 | safeArea = .init(top: 59, left: 0, bottom: 34, right: 0) 45 | size = .init(width: 393, height: 852) 46 | } 47 | return .init(safeArea: safeArea, size: size, traits: .iPhoneX(orientation)) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Example/ExampleTests/__Snapshots__/ContentViewTests/test_body_loaded.1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vdshko/DebugFrame/e9e3661dfa16a2510c5b61078cb72f0b03c1412c/Example/ExampleTests/__Snapshots__/ContentViewTests/test_body_loaded.1.png -------------------------------------------------------------------------------- /Example/Podfile: -------------------------------------------------------------------------------- 1 | platform :ios, '14.0' 2 | use_frameworks! 3 | 4 | install! 'cocoapods', :warn_for_unused_master_specs_repo => false 5 | 6 | target 'Example' do 7 | 8 | pod 'DebugFrame', :path => '../' 9 | end 10 | 11 | target 'ExampleTests' do 12 | 13 | # SnapshotTesting; https://github.com/pointfreeco/swift-snapshot-testing 14 | pod 'SnapshotTesting', '1.9.0', :inhibit_warnings => true 15 | end 16 | 17 | post_install do |installer| 18 | installer.pods_project.targets.each do |target| 19 | target.build_configurations.each do |config| 20 | config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '14.0' 21 | end 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /Example/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - DebugFrame (2.0.0) 3 | - SnapshotTesting (1.9.0) 4 | 5 | DEPENDENCIES: 6 | - DebugFrame (from `../`) 7 | - SnapshotTesting (= 1.9.0) 8 | 9 | SPEC REPOS: 10 | trunk: 11 | - SnapshotTesting 12 | 13 | EXTERNAL SOURCES: 14 | DebugFrame: 15 | :path: "../" 16 | 17 | SPEC CHECKSUMS: 18 | DebugFrame: 4e85e49a5327b09e055538442481398f3ad38be2 19 | SnapshotTesting: 6141c48b6aa76ead61431ca665c14ab9a066c53b 20 | 21 | PODFILE CHECKSUM: 8f2d82fe448e2e09320a9a650ed45b374d09e3ba 22 | 23 | COCOAPODS: 1.14.3 24 | -------------------------------------------------------------------------------- /License: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2022 vdshko 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 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, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version: 5.8 2 | 3 | import PackageDescription 4 | 5 | let package = Package( 6 | name: "DebugFrame", 7 | platforms: [ 8 | .iOS(.v14), 9 | .macOS(.v11) 10 | ], 11 | products: [ 12 | .library( 13 | name: "DebugFrame", 14 | targets: ["DebugFrame"]), 15 | ], 16 | targets: [ 17 | .target( 18 | name: "DebugFrame", 19 | path: "Source/DebugFrame" 20 | ) 21 | ] 22 | ) 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DebugFrame 2 | 3 | DebugFrame lib is a simple and powerful tool that can help you build your SwiftUI views easily. 4 | 5 | - Under the hood, it's a modifier that can be applied to any SwiftUI view. It adds an overlay to your view, which displays a border around the view and frame information, such as the view’s origin and size. This can be incredibly helpful when identifying layout issues, such as views that are too large or small or views that are positioned incorrectly. 6 | 7 | - Another feature is a debugBackground extension for the View, with a randomly picked Color each re-render time. 8 | 9 | ## Integration 10 | 11 | #### Setup with SPM: 12 | 13 | `DebugFrame` or `https://github.com/vdshko/DebugFrame` 14 | 15 | #### Setup with CocoaPods: 16 | 17 | `pod 'DebugFrame'` 18 | 19 | ## Usage of .debugFrame() 20 | ```swift 21 | VStack { 22 | title 23 | .debugFrame() 24 | Spacer() 25 | rectangles 26 | .debugFrame(color: .black) 27 | Spacer() 28 | } 29 | .debugFrame(color: .black, .size) 30 | ``` 31 | 32 | Screenshot of an app using DebugFrame. There are a few colored rectangles, and each one has a dotted line overlay and text showing the width and height. 33 | 34 | ## Usage of .debugBackground() 35 | ```swift 36 | VStack { 37 | title 38 | .debugBackground() 39 | Spacer() 40 | } 41 | ``` 42 | Screenshot of an app using DebugFrame. There is a title text with a randomly colored background rectangle version 1. 43 | Screenshot of an app using DebugFrame. There is a title text with a randomly colored background rectangle version 2. 44 | -------------------------------------------------------------------------------- /Source/DebugFrame.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 56; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | A14B8C9D29508B6B00C95F94 /* DebugFrame.swift in Sources */ = {isa = PBXBuildFile; fileRef = A14B8C9C29508B6B00C95F94 /* DebugFrame.swift */; }; 11 | A165D1D42950739A00F0FC7C /* DebugFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = A165D1D32950739A00F0FC7C /* DebugFrame.h */; settings = {ATTRIBUTES = (Public, ); }; }; 12 | /* End PBXBuildFile section */ 13 | 14 | /* Begin PBXFileReference section */ 15 | A14B8C9C29508B6B00C95F94 /* DebugFrame.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebugFrame.swift; sourceTree = ""; }; 16 | A165D1D02950739A00F0FC7C /* DebugFrame.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = DebugFrame.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 17 | A165D1D32950739A00F0FC7C /* DebugFrame.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DebugFrame.h; sourceTree = ""; }; 18 | /* End PBXFileReference section */ 19 | 20 | /* Begin PBXFrameworksBuildPhase section */ 21 | A165D1CD2950739A00F0FC7C /* Frameworks */ = { 22 | isa = PBXFrameworksBuildPhase; 23 | buildActionMask = 2147483647; 24 | files = ( 25 | ); 26 | runOnlyForDeploymentPostprocessing = 0; 27 | }; 28 | /* End PBXFrameworksBuildPhase section */ 29 | 30 | /* Begin PBXGroup section */ 31 | A165D1C62950739A00F0FC7C = { 32 | isa = PBXGroup; 33 | children = ( 34 | A165D1D22950739A00F0FC7C /* DebugFrame */, 35 | A165D1D12950739A00F0FC7C /* Products */, 36 | ); 37 | sourceTree = ""; 38 | }; 39 | A165D1D12950739A00F0FC7C /* Products */ = { 40 | isa = PBXGroup; 41 | children = ( 42 | A165D1D02950739A00F0FC7C /* DebugFrame.framework */, 43 | ); 44 | name = Products; 45 | sourceTree = ""; 46 | }; 47 | A165D1D22950739A00F0FC7C /* DebugFrame */ = { 48 | isa = PBXGroup; 49 | children = ( 50 | A165D1D32950739A00F0FC7C /* DebugFrame.h */, 51 | A14B8C9C29508B6B00C95F94 /* DebugFrame.swift */, 52 | ); 53 | path = DebugFrame; 54 | sourceTree = ""; 55 | }; 56 | /* End PBXGroup section */ 57 | 58 | /* Begin PBXHeadersBuildPhase section */ 59 | A165D1CB2950739A00F0FC7C /* Headers */ = { 60 | isa = PBXHeadersBuildPhase; 61 | buildActionMask = 2147483647; 62 | files = ( 63 | A165D1D42950739A00F0FC7C /* DebugFrame.h in Headers */, 64 | ); 65 | runOnlyForDeploymentPostprocessing = 0; 66 | }; 67 | /* End PBXHeadersBuildPhase section */ 68 | 69 | /* Begin PBXNativeTarget section */ 70 | A165D1CF2950739A00F0FC7C /* DebugFrame */ = { 71 | isa = PBXNativeTarget; 72 | buildConfigurationList = A165D1D72950739A00F0FC7C /* Build configuration list for PBXNativeTarget "DebugFrame" */; 73 | buildPhases = ( 74 | A165D1CB2950739A00F0FC7C /* Headers */, 75 | A165D1CC2950739A00F0FC7C /* Sources */, 76 | A165D1CD2950739A00F0FC7C /* Frameworks */, 77 | A165D1CE2950739A00F0FC7C /* Resources */, 78 | ); 79 | buildRules = ( 80 | ); 81 | dependencies = ( 82 | ); 83 | name = DebugFrame; 84 | productName = DebugFrame; 85 | productReference = A165D1D02950739A00F0FC7C /* DebugFrame.framework */; 86 | productType = "com.apple.product-type.framework"; 87 | }; 88 | /* End PBXNativeTarget section */ 89 | 90 | /* Begin PBXProject section */ 91 | A165D1C72950739A00F0FC7C /* Project object */ = { 92 | isa = PBXProject; 93 | attributes = { 94 | BuildIndependentTargetsInParallel = 1; 95 | LastSwiftUpdateCheck = 1410; 96 | LastUpgradeCheck = 1410; 97 | TargetAttributes = { 98 | A165D1CF2950739A00F0FC7C = { 99 | CreatedOnToolsVersion = 14.1; 100 | LastSwiftMigration = 1410; 101 | }; 102 | }; 103 | }; 104 | buildConfigurationList = A165D1CA2950739A00F0FC7C /* Build configuration list for PBXProject "DebugFrame" */; 105 | compatibilityVersion = "Xcode 14.0"; 106 | developmentRegion = en; 107 | hasScannedForEncodings = 0; 108 | knownRegions = ( 109 | en, 110 | Base, 111 | ); 112 | mainGroup = A165D1C62950739A00F0FC7C; 113 | productRefGroup = A165D1D12950739A00F0FC7C /* Products */; 114 | projectDirPath = ""; 115 | projectRoot = ""; 116 | targets = ( 117 | A165D1CF2950739A00F0FC7C /* DebugFrame */, 118 | ); 119 | }; 120 | /* End PBXProject section */ 121 | 122 | /* Begin PBXResourcesBuildPhase section */ 123 | A165D1CE2950739A00F0FC7C /* Resources */ = { 124 | isa = PBXResourcesBuildPhase; 125 | buildActionMask = 2147483647; 126 | files = ( 127 | ); 128 | runOnlyForDeploymentPostprocessing = 0; 129 | }; 130 | /* End PBXResourcesBuildPhase section */ 131 | 132 | /* Begin PBXSourcesBuildPhase section */ 133 | A165D1CC2950739A00F0FC7C /* Sources */ = { 134 | isa = PBXSourcesBuildPhase; 135 | buildActionMask = 2147483647; 136 | files = ( 137 | A14B8C9D29508B6B00C95F94 /* DebugFrame.swift in Sources */, 138 | ); 139 | runOnlyForDeploymentPostprocessing = 0; 140 | }; 141 | /* End PBXSourcesBuildPhase section */ 142 | 143 | /* Begin XCBuildConfiguration section */ 144 | A165D1D52950739A00F0FC7C /* Debug */ = { 145 | isa = XCBuildConfiguration; 146 | buildSettings = { 147 | ALWAYS_SEARCH_USER_PATHS = NO; 148 | CLANG_ANALYZER_NONNULL = YES; 149 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 150 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 151 | CLANG_ENABLE_MODULES = YES; 152 | CLANG_ENABLE_OBJC_ARC = YES; 153 | CLANG_ENABLE_OBJC_WEAK = YES; 154 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 155 | CLANG_WARN_BOOL_CONVERSION = YES; 156 | CLANG_WARN_COMMA = YES; 157 | CLANG_WARN_CONSTANT_CONVERSION = YES; 158 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 159 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 160 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 161 | CLANG_WARN_EMPTY_BODY = YES; 162 | CLANG_WARN_ENUM_CONVERSION = YES; 163 | CLANG_WARN_INFINITE_RECURSION = YES; 164 | CLANG_WARN_INT_CONVERSION = YES; 165 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 166 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 167 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 168 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 169 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 170 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 171 | CLANG_WARN_STRICT_PROTOTYPES = YES; 172 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 173 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 174 | CLANG_WARN_UNREACHABLE_CODE = YES; 175 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 176 | COPY_PHASE_STRIP = NO; 177 | CURRENT_PROJECT_VERSION = 1; 178 | DEBUG_INFORMATION_FORMAT = dwarf; 179 | ENABLE_STRICT_OBJC_MSGSEND = YES; 180 | ENABLE_TESTABILITY = YES; 181 | GCC_C_LANGUAGE_STANDARD = gnu11; 182 | GCC_DYNAMIC_NO_PIC = NO; 183 | GCC_NO_COMMON_BLOCKS = YES; 184 | GCC_OPTIMIZATION_LEVEL = 0; 185 | GCC_PREPROCESSOR_DEFINITIONS = ( 186 | "DEBUG=1", 187 | "$(inherited)", 188 | ); 189 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 190 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 191 | GCC_WARN_UNDECLARED_SELECTOR = YES; 192 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 193 | GCC_WARN_UNUSED_FUNCTION = YES; 194 | GCC_WARN_UNUSED_VARIABLE = YES; 195 | IPHONEOS_DEPLOYMENT_TARGET = 14.0; 196 | MACOSX_DEPLOYMENT_TARGET = 11.0; 197 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 198 | MTL_FAST_MATH = YES; 199 | ONLY_ACTIVE_ARCH = YES; 200 | SDKROOT = iphoneos; 201 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 202 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 203 | VERSIONING_SYSTEM = "apple-generic"; 204 | VERSION_INFO_PREFIX = ""; 205 | }; 206 | name = Debug; 207 | }; 208 | A165D1D62950739A00F0FC7C /* Release */ = { 209 | isa = XCBuildConfiguration; 210 | buildSettings = { 211 | ALWAYS_SEARCH_USER_PATHS = NO; 212 | CLANG_ANALYZER_NONNULL = YES; 213 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 214 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 215 | CLANG_ENABLE_MODULES = YES; 216 | CLANG_ENABLE_OBJC_ARC = YES; 217 | CLANG_ENABLE_OBJC_WEAK = YES; 218 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 219 | CLANG_WARN_BOOL_CONVERSION = YES; 220 | CLANG_WARN_COMMA = YES; 221 | CLANG_WARN_CONSTANT_CONVERSION = YES; 222 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 223 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 224 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 225 | CLANG_WARN_EMPTY_BODY = YES; 226 | CLANG_WARN_ENUM_CONVERSION = YES; 227 | CLANG_WARN_INFINITE_RECURSION = YES; 228 | CLANG_WARN_INT_CONVERSION = YES; 229 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 230 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 231 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 232 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 233 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 234 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 235 | CLANG_WARN_STRICT_PROTOTYPES = YES; 236 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 237 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 238 | CLANG_WARN_UNREACHABLE_CODE = YES; 239 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 240 | COPY_PHASE_STRIP = NO; 241 | CURRENT_PROJECT_VERSION = 1; 242 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 243 | ENABLE_NS_ASSERTIONS = NO; 244 | ENABLE_STRICT_OBJC_MSGSEND = YES; 245 | GCC_C_LANGUAGE_STANDARD = gnu11; 246 | GCC_NO_COMMON_BLOCKS = YES; 247 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 248 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 249 | GCC_WARN_UNDECLARED_SELECTOR = YES; 250 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 251 | GCC_WARN_UNUSED_FUNCTION = YES; 252 | GCC_WARN_UNUSED_VARIABLE = YES; 253 | IPHONEOS_DEPLOYMENT_TARGET = 14.0; 254 | MACOSX_DEPLOYMENT_TARGET = 11.0; 255 | MTL_ENABLE_DEBUG_INFO = NO; 256 | MTL_FAST_MATH = YES; 257 | SDKROOT = iphoneos; 258 | SWIFT_COMPILATION_MODE = wholemodule; 259 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 260 | VALIDATE_PRODUCT = YES; 261 | VERSIONING_SYSTEM = "apple-generic"; 262 | VERSION_INFO_PREFIX = ""; 263 | }; 264 | name = Release; 265 | }; 266 | A165D1D82950739A00F0FC7C /* Debug */ = { 267 | isa = XCBuildConfiguration; 268 | buildSettings = { 269 | CLANG_ENABLE_MODULES = YES; 270 | CODE_SIGN_STYLE = Automatic; 271 | CURRENT_PROJECT_VERSION = 1; 272 | DEFINES_MODULE = YES; 273 | DYLIB_COMPATIBILITY_VERSION = 1; 274 | DYLIB_CURRENT_VERSION = 1; 275 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 276 | GENERATE_INFOPLIST_FILE = YES; 277 | INFOPLIST_KEY_NSHumanReadableCopyright = ""; 278 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 279 | LD_RUNPATH_SEARCH_PATHS = ( 280 | "$(inherited)", 281 | "@executable_path/Frameworks", 282 | "@loader_path/Frameworks", 283 | ); 284 | MARKETING_VERSION = 1.0; 285 | PRODUCT_BUNDLE_IDENTIFIER = com.vdshko.projects.DebugFrame; 286 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 287 | SKIP_INSTALL = YES; 288 | SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx"; 289 | SUPPORTS_MACCATALYST = YES; 290 | SWIFT_EMIT_LOC_STRINGS = YES; 291 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 292 | SWIFT_VERSION = 5.0; 293 | TARGETED_DEVICE_FAMILY = "1,2"; 294 | }; 295 | name = Debug; 296 | }; 297 | A165D1D92950739A00F0FC7C /* Release */ = { 298 | isa = XCBuildConfiguration; 299 | buildSettings = { 300 | CLANG_ENABLE_MODULES = YES; 301 | CODE_SIGN_STYLE = Automatic; 302 | CURRENT_PROJECT_VERSION = 1; 303 | DEFINES_MODULE = YES; 304 | DYLIB_COMPATIBILITY_VERSION = 1; 305 | DYLIB_CURRENT_VERSION = 1; 306 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 307 | GENERATE_INFOPLIST_FILE = YES; 308 | INFOPLIST_KEY_NSHumanReadableCopyright = ""; 309 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 310 | LD_RUNPATH_SEARCH_PATHS = ( 311 | "$(inherited)", 312 | "@executable_path/Frameworks", 313 | "@loader_path/Frameworks", 314 | ); 315 | MARKETING_VERSION = 1.0; 316 | PRODUCT_BUNDLE_IDENTIFIER = com.vdshko.projects.DebugFrame; 317 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 318 | SKIP_INSTALL = YES; 319 | SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx"; 320 | SUPPORTS_MACCATALYST = YES; 321 | SWIFT_EMIT_LOC_STRINGS = YES; 322 | SWIFT_VERSION = 5.0; 323 | TARGETED_DEVICE_FAMILY = "1,2"; 324 | }; 325 | name = Release; 326 | }; 327 | /* End XCBuildConfiguration section */ 328 | 329 | /* Begin XCConfigurationList section */ 330 | A165D1CA2950739A00F0FC7C /* Build configuration list for PBXProject "DebugFrame" */ = { 331 | isa = XCConfigurationList; 332 | buildConfigurations = ( 333 | A165D1D52950739A00F0FC7C /* Debug */, 334 | A165D1D62950739A00F0FC7C /* Release */, 335 | ); 336 | defaultConfigurationIsVisible = 0; 337 | defaultConfigurationName = Release; 338 | }; 339 | A165D1D72950739A00F0FC7C /* Build configuration list for PBXNativeTarget "DebugFrame" */ = { 340 | isa = XCConfigurationList; 341 | buildConfigurations = ( 342 | A165D1D82950739A00F0FC7C /* Debug */, 343 | A165D1D92950739A00F0FC7C /* Release */, 344 | ); 345 | defaultConfigurationIsVisible = 0; 346 | defaultConfigurationName = Release; 347 | }; 348 | /* End XCConfigurationList section */ 349 | }; 350 | rootObject = A165D1C72950739A00F0FC7C /* Project object */; 351 | } 352 | -------------------------------------------------------------------------------- /Source/DebugFrame.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Source/DebugFrame.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Source/DebugFrame/DebugFrame.h: -------------------------------------------------------------------------------- 1 | // 2 | // DebugFrame.h 3 | // DebugFrame 4 | // 5 | // Created by Vladyslav Shkodych on 19.12.2022. 6 | // 7 | 8 | #import 9 | 10 | //! Project version number for DebugFrame. 11 | FOUNDATION_EXPORT double DebugFrameVersionNumber; 12 | 13 | //! Project version string for DebugFrame. 14 | FOUNDATION_EXPORT const unsigned char DebugFrameVersionString[]; 15 | 16 | // In this header, you should import all the public headers of your framework using statements like #import 17 | -------------------------------------------------------------------------------- /Source/DebugFrame/DebugFrame.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DebugFrame.swift 3 | // DebugFrame 4 | // 5 | // Created by Vladyslav Shkodych on 19.12.2022. 6 | // 7 | 8 | /* 9 | DebugFrame is an overlay that can be appended to your view, for debugging its origin and size. 10 | 11 | DebugFrame will not be compiled in the release build, so you may not worry if you forget to remove it from some of your view. 12 | To keep your code as clean as possible, it's probably a good idea to add a SwiftLint or any other linting rule to make an Xcode warning for this. 13 | 14 | There are two methods for modifying your view with debugFrame overlay. 15 | The two methods need only for easier use of the Xcode autocomplete. 16 | */ 17 | 18 | import Foundation 19 | import SwiftUI 20 | 21 | // MARK: - DebugFrame ViewModifier 22 | 23 | private struct DebugFrame: ViewModifier { 24 | 25 | // MARK: - Properties 26 | 27 | let color: Color 28 | let outputs: [DebugFrameOutput] 29 | 30 | // MARK: - Body 31 | 32 | func body(content: Content) -> some View { 33 | #if DEBUG 34 | content.overlay(overlayView) 35 | #else 36 | content 37 | #endif 38 | } 39 | 40 | // MARK: - Private methods 41 | 42 | private var overlayView: some View { 43 | GeometryReader { geometry in 44 | ZStack(alignment: .bottom) { 45 | Rectangle() 46 | .strokeBorder(style: StrokeStyle(lineWidth: 1, dash: [5])) 47 | .foregroundColor(color) 48 | Text(defineOutput(with: geometry)) 49 | .foregroundColor(color) 50 | .font(.caption2) 51 | } 52 | } 53 | } 54 | 55 | private func defineOutput(with geometry: GeometryProxy) -> String { 56 | let globalOrigin: CGPoint = geometry.frame(in: .global).origin 57 | let originX: String = "x: \(rounded(globalOrigin.x))" 58 | let originY: String = "y: \(rounded(globalOrigin.y))" 59 | let width: String = "w: \(rounded(geometry.size.width))" 60 | let height: String = "h: \(rounded(geometry.size.height))" 61 | 62 | return String( 63 | outputs.reduce(into: String()) { 64 | switch $1 { 65 | case .all: $0 += "(\(originX), \(originY)) | (\(width), \(height))" 66 | case .origin: $0 += "(\(originX), \(originY))" 67 | case .size: $0 += "(\(width), \(height))" 68 | case .originX: $0 += originX 69 | case .originY: $0 += originY 70 | case .width: $0 += width 71 | case .height: $0 += height 72 | } 73 | $0 += " | " 74 | }.dropLast(3) 75 | ) 76 | } 77 | 78 | private func rounded(_ value: CGFloat) -> Float { 79 | return Float(round(100 * value) / 100) 80 | } 81 | } 82 | 83 | // MARK: - DebugFrameOutput enum 84 | 85 | public enum DebugFrameOutput { 86 | 87 | /// (originX, originY) | (width, height) 88 | case all 89 | /// (originX, originY) 90 | case origin 91 | /// (width, height) 92 | case size 93 | /// originX 94 | case originX 95 | /// originY 96 | case originY 97 | /// width 98 | case width 99 | /// height 100 | case height 101 | } 102 | 103 | // MARK: - ViewExtensions 104 | 105 | public extension View { 106 | 107 | /// Applies an overlay to your view and returns a new view. The overlay contains a border of your view, its origin, and size. 108 | /// - Parameter color: Default color for the border of the overlay and outputs. 109 | /// - Returns: View that uses the debug overlay. 110 | func debugFrame(color: Color = Color.red) -> some View { 111 | return modifier( 112 | DebugFrame( 113 | color: color, 114 | outputs: [DebugFrameOutput.all] 115 | ) 116 | ) 117 | } 118 | 119 | /// Applies an overlay to your view and returns a new view. The overlay contains a border of your view, its origin, and size. 120 | /// - Parameters: 121 | /// - color: Default color for the border of the overlay and outputs. 122 | /// - outputs: Default outputs of the overlay such as origin and size. 123 | /// - Returns: View that uses the debug overlay. 124 | func debugFrame(color: Color = Color.red, _ outputs: DebugFrameOutput...) -> some View { 125 | return modifier( 126 | DebugFrame( 127 | color: color, 128 | outputs: outputs.isEmpty ? [DebugFrameOutput.all] : outputs 129 | ) 130 | ) 131 | } 132 | 133 | /// Applies a background, with random Color, to your view and returns a new view. 134 | /// 135 | /// Each time SwiftUI re-creates the body for the view with this background, the Color will be picked randomly. 136 | /// - Returns: View with the re-rendered background Color. 137 | func debugBackground() -> some View { 138 | #if DEBUG 139 | background( 140 | Color( 141 | red: .random(in: 0...1), 142 | green: .random(in: 0...1), 143 | blue: .random(in: 0...1), 144 | opacity: 0.8 145 | ) 146 | ) 147 | #else 148 | self 149 | #endif 150 | } 151 | } 152 | --------------------------------------------------------------------------------