├── README.md ├── SwiftUIPdf.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── xcuserdata │ └── ketyung.xcuserdatad │ └── xcschemes │ └── xcschememanagement.plist ├── SwiftUIPdf ├── Assets.xcassets │ ├── AccentColor.colorset │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── appiconpdf.png │ │ ├── appiconpdf@2x-1.png │ │ ├── appiconpdf@2x-2.png │ │ ├── appiconpdf@2x.png │ │ └── appiconpdf@3x.png │ ├── Contents.json │ └── techchee_logo.imageset │ │ ├── Contents.json │ │ ├── techchee_logo.png │ │ ├── techchee_logo@2x.png │ │ └── techchee_logo@3x.png ├── Info.plist ├── Models │ └── Content.swift ├── Preview Content │ └── Preview Assets.xcassets │ │ └── Contents.json ├── SwiftUIPdfApp.swift ├── Utilities │ ├── Extensions.swift │ └── PdfCreator.swift ├── ViewControllers │ └── ViewController.swift ├── ViewModels │ └── ContentViewModel.swift └── Views │ ├── ContentView.swift │ ├── MenuView.swift │ ├── PdfPreviewView.swift │ ├── PdfViewUI.swift │ ├── ShareView.swift │ ├── ViewControllerSwiftUIView.swift │ └── WebView.swift ├── SwiftUIPdfTests ├── Info.plist └── SwiftUIPdfTests.swift └── SwiftUIPdfUITests ├── Info.plist └── SwiftUIPdfUITests.swift /README.md: -------------------------------------------------------------------------------- 1 | # SwiftUIPdf 2 | Sample source code for tutorial - Build a PDF composer app with PDFKit - the SwiftUI and MVVM way . Unlicensed license. https://unlicense.org/ 3 | -------------------------------------------------------------------------------- /SwiftUIPdf.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 105B0B5A25E1E94200527643 /* SwiftUIPdfApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 105B0B5925E1E94200527643 /* SwiftUIPdfApp.swift */; }; 11 | 105B0B5C25E1E94200527643 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 105B0B5B25E1E94200527643 /* ContentView.swift */; }; 12 | 105B0B5E25E1E94200527643 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 105B0B5D25E1E94200527643 /* Assets.xcassets */; }; 13 | 105B0B6125E1E94200527643 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 105B0B6025E1E94200527643 /* Preview Assets.xcassets */; }; 14 | 105B0B6C25E1E94200527643 /* SwiftUIPdfTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 105B0B6B25E1E94200527643 /* SwiftUIPdfTests.swift */; }; 15 | 105B0B7725E1E94200527643 /* SwiftUIPdfUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 105B0B7625E1E94200527643 /* SwiftUIPdfUITests.swift */; }; 16 | 105B0B8925E1E9AD00527643 /* Content.swift in Sources */ = {isa = PBXBuildFile; fileRef = 105B0B8825E1E9AD00527643 /* Content.swift */; }; 17 | 105B0B9225E1EC2F00527643 /* PdfCreator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 105B0B9125E1EC2F00527643 /* PdfCreator.swift */; }; 18 | 105B0B9825E1F2B600527643 /* PdfViewUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 105B0B9725E1F2B600527643 /* PdfViewUI.swift */; }; 19 | 105B0BA325E1F48A00527643 /* PdfPreviewView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 105B0BA225E1F48A00527643 /* PdfPreviewView.swift */; }; 20 | 105B0BAB25E1FC2700527643 /* ContentViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 105B0BAA25E1FC2700527643 /* ContentViewModel.swift */; }; 21 | 105B0BB825E23E4A00527643 /* ShareView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 105B0BB725E23E4A00527643 /* ShareView.swift */; }; 22 | 105B0BC025E2454B00527643 /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 105B0BBF25E2454B00527643 /* Extensions.swift */; }; 23 | 105B0BC625E4AA3500527643 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 105B0BC525E4AA3500527643 /* ViewController.swift */; }; 24 | 105B0BCB25E4AC0000527643 /* ViewControllerSwiftUIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 105B0BCA25E4AC0000527643 /* ViewControllerSwiftUIView.swift */; }; 25 | 105B0BD025E4AC7D00527643 /* MenuView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 105B0BCF25E4AC7D00527643 /* MenuView.swift */; }; 26 | 105B0BD525E87B5E00527643 /* WebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 105B0BD425E87B5E00527643 /* WebView.swift */; }; 27 | /* End PBXBuildFile section */ 28 | 29 | /* Begin PBXContainerItemProxy section */ 30 | 105B0B6825E1E94200527643 /* PBXContainerItemProxy */ = { 31 | isa = PBXContainerItemProxy; 32 | containerPortal = 105B0B4E25E1E94200527643 /* Project object */; 33 | proxyType = 1; 34 | remoteGlobalIDString = 105B0B5525E1E94200527643; 35 | remoteInfo = SwiftUIPdf; 36 | }; 37 | 105B0B7325E1E94200527643 /* PBXContainerItemProxy */ = { 38 | isa = PBXContainerItemProxy; 39 | containerPortal = 105B0B4E25E1E94200527643 /* Project object */; 40 | proxyType = 1; 41 | remoteGlobalIDString = 105B0B5525E1E94200527643; 42 | remoteInfo = SwiftUIPdf; 43 | }; 44 | /* End PBXContainerItemProxy section */ 45 | 46 | /* Begin PBXFileReference section */ 47 | 105B0B5625E1E94200527643 /* SwiftUIPdf.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SwiftUIPdf.app; sourceTree = BUILT_PRODUCTS_DIR; }; 48 | 105B0B5925E1E94200527643 /* SwiftUIPdfApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftUIPdfApp.swift; sourceTree = ""; }; 49 | 105B0B5B25E1E94200527643 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; 50 | 105B0B5D25E1E94200527643 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 51 | 105B0B6025E1E94200527643 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; 52 | 105B0B6225E1E94200527643 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 53 | 105B0B6725E1E94200527643 /* SwiftUIPdfTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SwiftUIPdfTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 54 | 105B0B6B25E1E94200527643 /* SwiftUIPdfTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftUIPdfTests.swift; sourceTree = ""; }; 55 | 105B0B6D25E1E94200527643 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 56 | 105B0B7225E1E94200527643 /* SwiftUIPdfUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SwiftUIPdfUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 57 | 105B0B7625E1E94200527643 /* SwiftUIPdfUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftUIPdfUITests.swift; sourceTree = ""; }; 58 | 105B0B7825E1E94200527643 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 59 | 105B0B8825E1E9AD00527643 /* Content.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Content.swift; sourceTree = ""; }; 60 | 105B0B9125E1EC2F00527643 /* PdfCreator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PdfCreator.swift; sourceTree = ""; }; 61 | 105B0B9725E1F2B600527643 /* PdfViewUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PdfViewUI.swift; sourceTree = ""; }; 62 | 105B0BA225E1F48A00527643 /* PdfPreviewView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PdfPreviewView.swift; sourceTree = ""; }; 63 | 105B0BAA25E1FC2700527643 /* ContentViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentViewModel.swift; sourceTree = ""; }; 64 | 105B0BB725E23E4A00527643 /* ShareView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareView.swift; sourceTree = ""; }; 65 | 105B0BBF25E2454B00527643 /* Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Extensions.swift; sourceTree = ""; }; 66 | 105B0BC525E4AA3500527643 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 67 | 105B0BCA25E4AC0000527643 /* ViewControllerSwiftUIView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewControllerSwiftUIView.swift; sourceTree = ""; }; 68 | 105B0BCF25E4AC7D00527643 /* MenuView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuView.swift; sourceTree = ""; }; 69 | 105B0BD425E87B5E00527643 /* WebView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WebView.swift; sourceTree = ""; }; 70 | /* End PBXFileReference section */ 71 | 72 | /* Begin PBXFrameworksBuildPhase section */ 73 | 105B0B5325E1E94200527643 /* Frameworks */ = { 74 | isa = PBXFrameworksBuildPhase; 75 | buildActionMask = 2147483647; 76 | files = ( 77 | ); 78 | runOnlyForDeploymentPostprocessing = 0; 79 | }; 80 | 105B0B6425E1E94200527643 /* Frameworks */ = { 81 | isa = PBXFrameworksBuildPhase; 82 | buildActionMask = 2147483647; 83 | files = ( 84 | ); 85 | runOnlyForDeploymentPostprocessing = 0; 86 | }; 87 | 105B0B6F25E1E94200527643 /* Frameworks */ = { 88 | isa = PBXFrameworksBuildPhase; 89 | buildActionMask = 2147483647; 90 | files = ( 91 | ); 92 | runOnlyForDeploymentPostprocessing = 0; 93 | }; 94 | /* End PBXFrameworksBuildPhase section */ 95 | 96 | /* Begin PBXGroup section */ 97 | 105B0B4D25E1E94200527643 = { 98 | isa = PBXGroup; 99 | children = ( 100 | 105B0B5825E1E94200527643 /* SwiftUIPdf */, 101 | 105B0B6A25E1E94200527643 /* SwiftUIPdfTests */, 102 | 105B0B7525E1E94200527643 /* SwiftUIPdfUITests */, 103 | 105B0B5725E1E94200527643 /* Products */, 104 | ); 105 | sourceTree = ""; 106 | }; 107 | 105B0B5725E1E94200527643 /* Products */ = { 108 | isa = PBXGroup; 109 | children = ( 110 | 105B0B5625E1E94200527643 /* SwiftUIPdf.app */, 111 | 105B0B6725E1E94200527643 /* SwiftUIPdfTests.xctest */, 112 | 105B0B7225E1E94200527643 /* SwiftUIPdfUITests.xctest */, 113 | ); 114 | name = Products; 115 | sourceTree = ""; 116 | }; 117 | 105B0B5825E1E94200527643 /* SwiftUIPdf */ = { 118 | isa = PBXGroup; 119 | children = ( 120 | 105B0BDC25E9DECD00527643 /* Utilities */, 121 | 105B0BC425E4AA2500527643 /* ViewControllers */, 122 | 105B0B9625E1F2A700527643 /* Views */, 123 | 105B0B9025E1EC2200527643 /* ViewModels */, 124 | 105B0B8725E1E99F00527643 /* Models */, 125 | 105B0B5925E1E94200527643 /* SwiftUIPdfApp.swift */, 126 | 105B0B5D25E1E94200527643 /* Assets.xcassets */, 127 | 105B0B6225E1E94200527643 /* Info.plist */, 128 | 105B0B5F25E1E94200527643 /* Preview Content */, 129 | ); 130 | path = SwiftUIPdf; 131 | sourceTree = ""; 132 | }; 133 | 105B0B5F25E1E94200527643 /* Preview Content */ = { 134 | isa = PBXGroup; 135 | children = ( 136 | 105B0B6025E1E94200527643 /* Preview Assets.xcassets */, 137 | ); 138 | path = "Preview Content"; 139 | sourceTree = ""; 140 | }; 141 | 105B0B6A25E1E94200527643 /* SwiftUIPdfTests */ = { 142 | isa = PBXGroup; 143 | children = ( 144 | 105B0B6B25E1E94200527643 /* SwiftUIPdfTests.swift */, 145 | 105B0B6D25E1E94200527643 /* Info.plist */, 146 | ); 147 | path = SwiftUIPdfTests; 148 | sourceTree = ""; 149 | }; 150 | 105B0B7525E1E94200527643 /* SwiftUIPdfUITests */ = { 151 | isa = PBXGroup; 152 | children = ( 153 | 105B0B7625E1E94200527643 /* SwiftUIPdfUITests.swift */, 154 | 105B0B7825E1E94200527643 /* Info.plist */, 155 | ); 156 | path = SwiftUIPdfUITests; 157 | sourceTree = ""; 158 | }; 159 | 105B0B8725E1E99F00527643 /* Models */ = { 160 | isa = PBXGroup; 161 | children = ( 162 | 105B0B8825E1E9AD00527643 /* Content.swift */, 163 | ); 164 | path = Models; 165 | sourceTree = ""; 166 | }; 167 | 105B0B9025E1EC2200527643 /* ViewModels */ = { 168 | isa = PBXGroup; 169 | children = ( 170 | 105B0BAA25E1FC2700527643 /* ContentViewModel.swift */, 171 | ); 172 | path = ViewModels; 173 | sourceTree = ""; 174 | }; 175 | 105B0B9625E1F2A700527643 /* Views */ = { 176 | isa = PBXGroup; 177 | children = ( 178 | 105B0B5B25E1E94200527643 /* ContentView.swift */, 179 | 105B0BA225E1F48A00527643 /* PdfPreviewView.swift */, 180 | 105B0B9725E1F2B600527643 /* PdfViewUI.swift */, 181 | 105B0BB725E23E4A00527643 /* ShareView.swift */, 182 | 105B0BCA25E4AC0000527643 /* ViewControllerSwiftUIView.swift */, 183 | 105B0BCF25E4AC7D00527643 /* MenuView.swift */, 184 | 105B0BD425E87B5E00527643 /* WebView.swift */, 185 | ); 186 | path = Views; 187 | sourceTree = ""; 188 | }; 189 | 105B0BC425E4AA2500527643 /* ViewControllers */ = { 190 | isa = PBXGroup; 191 | children = ( 192 | 105B0BC525E4AA3500527643 /* ViewController.swift */, 193 | ); 194 | path = ViewControllers; 195 | sourceTree = ""; 196 | }; 197 | 105B0BDC25E9DECD00527643 /* Utilities */ = { 198 | isa = PBXGroup; 199 | children = ( 200 | 105B0BBF25E2454B00527643 /* Extensions.swift */, 201 | 105B0B9125E1EC2F00527643 /* PdfCreator.swift */, 202 | ); 203 | path = Utilities; 204 | sourceTree = ""; 205 | }; 206 | /* End PBXGroup section */ 207 | 208 | /* Begin PBXNativeTarget section */ 209 | 105B0B5525E1E94200527643 /* SwiftUIPdf */ = { 210 | isa = PBXNativeTarget; 211 | buildConfigurationList = 105B0B7B25E1E94200527643 /* Build configuration list for PBXNativeTarget "SwiftUIPdf" */; 212 | buildPhases = ( 213 | 105B0B5225E1E94200527643 /* Sources */, 214 | 105B0B5325E1E94200527643 /* Frameworks */, 215 | 105B0B5425E1E94200527643 /* Resources */, 216 | ); 217 | buildRules = ( 218 | ); 219 | dependencies = ( 220 | ); 221 | name = SwiftUIPdf; 222 | productName = SwiftUIPdf; 223 | productReference = 105B0B5625E1E94200527643 /* SwiftUIPdf.app */; 224 | productType = "com.apple.product-type.application"; 225 | }; 226 | 105B0B6625E1E94200527643 /* SwiftUIPdfTests */ = { 227 | isa = PBXNativeTarget; 228 | buildConfigurationList = 105B0B7E25E1E94200527643 /* Build configuration list for PBXNativeTarget "SwiftUIPdfTests" */; 229 | buildPhases = ( 230 | 105B0B6325E1E94200527643 /* Sources */, 231 | 105B0B6425E1E94200527643 /* Frameworks */, 232 | 105B0B6525E1E94200527643 /* Resources */, 233 | ); 234 | buildRules = ( 235 | ); 236 | dependencies = ( 237 | 105B0B6925E1E94200527643 /* PBXTargetDependency */, 238 | ); 239 | name = SwiftUIPdfTests; 240 | productName = SwiftUIPdfTests; 241 | productReference = 105B0B6725E1E94200527643 /* SwiftUIPdfTests.xctest */; 242 | productType = "com.apple.product-type.bundle.unit-test"; 243 | }; 244 | 105B0B7125E1E94200527643 /* SwiftUIPdfUITests */ = { 245 | isa = PBXNativeTarget; 246 | buildConfigurationList = 105B0B8125E1E94200527643 /* Build configuration list for PBXNativeTarget "SwiftUIPdfUITests" */; 247 | buildPhases = ( 248 | 105B0B6E25E1E94200527643 /* Sources */, 249 | 105B0B6F25E1E94200527643 /* Frameworks */, 250 | 105B0B7025E1E94200527643 /* Resources */, 251 | ); 252 | buildRules = ( 253 | ); 254 | dependencies = ( 255 | 105B0B7425E1E94200527643 /* PBXTargetDependency */, 256 | ); 257 | name = SwiftUIPdfUITests; 258 | productName = SwiftUIPdfUITests; 259 | productReference = 105B0B7225E1E94200527643 /* SwiftUIPdfUITests.xctest */; 260 | productType = "com.apple.product-type.bundle.ui-testing"; 261 | }; 262 | /* End PBXNativeTarget section */ 263 | 264 | /* Begin PBXProject section */ 265 | 105B0B4E25E1E94200527643 /* Project object */ = { 266 | isa = PBXProject; 267 | attributes = { 268 | LastSwiftUpdateCheck = 1240; 269 | LastUpgradeCheck = 1240; 270 | TargetAttributes = { 271 | 105B0B5525E1E94200527643 = { 272 | CreatedOnToolsVersion = 12.4; 273 | }; 274 | 105B0B6625E1E94200527643 = { 275 | CreatedOnToolsVersion = 12.4; 276 | TestTargetID = 105B0B5525E1E94200527643; 277 | }; 278 | 105B0B7125E1E94200527643 = { 279 | CreatedOnToolsVersion = 12.4; 280 | TestTargetID = 105B0B5525E1E94200527643; 281 | }; 282 | }; 283 | }; 284 | buildConfigurationList = 105B0B5125E1E94200527643 /* Build configuration list for PBXProject "SwiftUIPdf" */; 285 | compatibilityVersion = "Xcode 9.3"; 286 | developmentRegion = en; 287 | hasScannedForEncodings = 0; 288 | knownRegions = ( 289 | en, 290 | Base, 291 | ); 292 | mainGroup = 105B0B4D25E1E94200527643; 293 | productRefGroup = 105B0B5725E1E94200527643 /* Products */; 294 | projectDirPath = ""; 295 | projectRoot = ""; 296 | targets = ( 297 | 105B0B5525E1E94200527643 /* SwiftUIPdf */, 298 | 105B0B6625E1E94200527643 /* SwiftUIPdfTests */, 299 | 105B0B7125E1E94200527643 /* SwiftUIPdfUITests */, 300 | ); 301 | }; 302 | /* End PBXProject section */ 303 | 304 | /* Begin PBXResourcesBuildPhase section */ 305 | 105B0B5425E1E94200527643 /* Resources */ = { 306 | isa = PBXResourcesBuildPhase; 307 | buildActionMask = 2147483647; 308 | files = ( 309 | 105B0B6125E1E94200527643 /* Preview Assets.xcassets in Resources */, 310 | 105B0B5E25E1E94200527643 /* Assets.xcassets in Resources */, 311 | ); 312 | runOnlyForDeploymentPostprocessing = 0; 313 | }; 314 | 105B0B6525E1E94200527643 /* Resources */ = { 315 | isa = PBXResourcesBuildPhase; 316 | buildActionMask = 2147483647; 317 | files = ( 318 | ); 319 | runOnlyForDeploymentPostprocessing = 0; 320 | }; 321 | 105B0B7025E1E94200527643 /* Resources */ = { 322 | isa = PBXResourcesBuildPhase; 323 | buildActionMask = 2147483647; 324 | files = ( 325 | ); 326 | runOnlyForDeploymentPostprocessing = 0; 327 | }; 328 | /* End PBXResourcesBuildPhase section */ 329 | 330 | /* Begin PBXSourcesBuildPhase section */ 331 | 105B0B5225E1E94200527643 /* Sources */ = { 332 | isa = PBXSourcesBuildPhase; 333 | buildActionMask = 2147483647; 334 | files = ( 335 | 105B0BC625E4AA3500527643 /* ViewController.swift in Sources */, 336 | 105B0BD025E4AC7D00527643 /* MenuView.swift in Sources */, 337 | 105B0BD525E87B5E00527643 /* WebView.swift in Sources */, 338 | 105B0B5C25E1E94200527643 /* ContentView.swift in Sources */, 339 | 105B0BC025E2454B00527643 /* Extensions.swift in Sources */, 340 | 105B0B9825E1F2B600527643 /* PdfViewUI.swift in Sources */, 341 | 105B0BCB25E4AC0000527643 /* ViewControllerSwiftUIView.swift in Sources */, 342 | 105B0BA325E1F48A00527643 /* PdfPreviewView.swift in Sources */, 343 | 105B0BAB25E1FC2700527643 /* ContentViewModel.swift in Sources */, 344 | 105B0B9225E1EC2F00527643 /* PdfCreator.swift in Sources */, 345 | 105B0BB825E23E4A00527643 /* ShareView.swift in Sources */, 346 | 105B0B5A25E1E94200527643 /* SwiftUIPdfApp.swift in Sources */, 347 | 105B0B8925E1E9AD00527643 /* Content.swift in Sources */, 348 | ); 349 | runOnlyForDeploymentPostprocessing = 0; 350 | }; 351 | 105B0B6325E1E94200527643 /* Sources */ = { 352 | isa = PBXSourcesBuildPhase; 353 | buildActionMask = 2147483647; 354 | files = ( 355 | 105B0B6C25E1E94200527643 /* SwiftUIPdfTests.swift in Sources */, 356 | ); 357 | runOnlyForDeploymentPostprocessing = 0; 358 | }; 359 | 105B0B6E25E1E94200527643 /* Sources */ = { 360 | isa = PBXSourcesBuildPhase; 361 | buildActionMask = 2147483647; 362 | files = ( 363 | 105B0B7725E1E94200527643 /* SwiftUIPdfUITests.swift in Sources */, 364 | ); 365 | runOnlyForDeploymentPostprocessing = 0; 366 | }; 367 | /* End PBXSourcesBuildPhase section */ 368 | 369 | /* Begin PBXTargetDependency section */ 370 | 105B0B6925E1E94200527643 /* PBXTargetDependency */ = { 371 | isa = PBXTargetDependency; 372 | target = 105B0B5525E1E94200527643 /* SwiftUIPdf */; 373 | targetProxy = 105B0B6825E1E94200527643 /* PBXContainerItemProxy */; 374 | }; 375 | 105B0B7425E1E94200527643 /* PBXTargetDependency */ = { 376 | isa = PBXTargetDependency; 377 | target = 105B0B5525E1E94200527643 /* SwiftUIPdf */; 378 | targetProxy = 105B0B7325E1E94200527643 /* PBXContainerItemProxy */; 379 | }; 380 | /* End PBXTargetDependency section */ 381 | 382 | /* Begin XCBuildConfiguration section */ 383 | 105B0B7925E1E94200527643 /* Debug */ = { 384 | isa = XCBuildConfiguration; 385 | buildSettings = { 386 | ALWAYS_SEARCH_USER_PATHS = NO; 387 | CLANG_ANALYZER_NONNULL = YES; 388 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 389 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 390 | CLANG_CXX_LIBRARY = "libc++"; 391 | CLANG_ENABLE_MODULES = YES; 392 | CLANG_ENABLE_OBJC_ARC = YES; 393 | CLANG_ENABLE_OBJC_WEAK = YES; 394 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 395 | CLANG_WARN_BOOL_CONVERSION = YES; 396 | CLANG_WARN_COMMA = YES; 397 | CLANG_WARN_CONSTANT_CONVERSION = YES; 398 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 399 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 400 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 401 | CLANG_WARN_EMPTY_BODY = YES; 402 | CLANG_WARN_ENUM_CONVERSION = YES; 403 | CLANG_WARN_INFINITE_RECURSION = YES; 404 | CLANG_WARN_INT_CONVERSION = YES; 405 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 406 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 407 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 408 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 409 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 410 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 411 | CLANG_WARN_STRICT_PROTOTYPES = YES; 412 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 413 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 414 | CLANG_WARN_UNREACHABLE_CODE = YES; 415 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 416 | COPY_PHASE_STRIP = NO; 417 | DEBUG_INFORMATION_FORMAT = dwarf; 418 | ENABLE_STRICT_OBJC_MSGSEND = YES; 419 | ENABLE_TESTABILITY = YES; 420 | GCC_C_LANGUAGE_STANDARD = gnu11; 421 | GCC_DYNAMIC_NO_PIC = NO; 422 | GCC_NO_COMMON_BLOCKS = YES; 423 | GCC_OPTIMIZATION_LEVEL = 0; 424 | GCC_PREPROCESSOR_DEFINITIONS = ( 425 | "DEBUG=1", 426 | "$(inherited)", 427 | ); 428 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 429 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 430 | GCC_WARN_UNDECLARED_SELECTOR = YES; 431 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 432 | GCC_WARN_UNUSED_FUNCTION = YES; 433 | GCC_WARN_UNUSED_VARIABLE = YES; 434 | IPHONEOS_DEPLOYMENT_TARGET = 14.4; 435 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 436 | MTL_FAST_MATH = YES; 437 | ONLY_ACTIVE_ARCH = YES; 438 | SDKROOT = iphoneos; 439 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 440 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 441 | }; 442 | name = Debug; 443 | }; 444 | 105B0B7A25E1E94200527643 /* Release */ = { 445 | isa = XCBuildConfiguration; 446 | buildSettings = { 447 | ALWAYS_SEARCH_USER_PATHS = NO; 448 | CLANG_ANALYZER_NONNULL = YES; 449 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 450 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 451 | CLANG_CXX_LIBRARY = "libc++"; 452 | CLANG_ENABLE_MODULES = YES; 453 | CLANG_ENABLE_OBJC_ARC = YES; 454 | CLANG_ENABLE_OBJC_WEAK = YES; 455 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 456 | CLANG_WARN_BOOL_CONVERSION = YES; 457 | CLANG_WARN_COMMA = YES; 458 | CLANG_WARN_CONSTANT_CONVERSION = YES; 459 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 460 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 461 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 462 | CLANG_WARN_EMPTY_BODY = YES; 463 | CLANG_WARN_ENUM_CONVERSION = YES; 464 | CLANG_WARN_INFINITE_RECURSION = YES; 465 | CLANG_WARN_INT_CONVERSION = YES; 466 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 467 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 468 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 469 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 470 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 471 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 472 | CLANG_WARN_STRICT_PROTOTYPES = YES; 473 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 474 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 475 | CLANG_WARN_UNREACHABLE_CODE = YES; 476 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 477 | COPY_PHASE_STRIP = NO; 478 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 479 | ENABLE_NS_ASSERTIONS = NO; 480 | ENABLE_STRICT_OBJC_MSGSEND = YES; 481 | GCC_C_LANGUAGE_STANDARD = gnu11; 482 | GCC_NO_COMMON_BLOCKS = YES; 483 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 484 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 485 | GCC_WARN_UNDECLARED_SELECTOR = YES; 486 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 487 | GCC_WARN_UNUSED_FUNCTION = YES; 488 | GCC_WARN_UNUSED_VARIABLE = YES; 489 | IPHONEOS_DEPLOYMENT_TARGET = 14.4; 490 | MTL_ENABLE_DEBUG_INFO = NO; 491 | MTL_FAST_MATH = YES; 492 | SDKROOT = iphoneos; 493 | SWIFT_COMPILATION_MODE = wholemodule; 494 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 495 | VALIDATE_PRODUCT = YES; 496 | }; 497 | name = Release; 498 | }; 499 | 105B0B7C25E1E94200527643 /* Debug */ = { 500 | isa = XCBuildConfiguration; 501 | buildSettings = { 502 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 503 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 504 | CODE_SIGN_STYLE = Automatic; 505 | DEVELOPMENT_ASSET_PATHS = "\"SwiftUIPdf/Preview Content\""; 506 | DEVELOPMENT_TEAM = 69FAF79796; 507 | ENABLE_PREVIEWS = YES; 508 | INFOPLIST_FILE = SwiftUIPdf/Info.plist; 509 | IPHONEOS_DEPLOYMENT_TARGET = 14.0; 510 | LD_RUNPATH_SEARCH_PATHS = ( 511 | "$(inherited)", 512 | "@executable_path/Frameworks", 513 | ); 514 | PRODUCT_BUNDLE_IDENTIFIER = com.techchee.swiftui.tut.SwiftUIPdf; 515 | PRODUCT_NAME = "$(TARGET_NAME)"; 516 | SWIFT_VERSION = 5.0; 517 | TARGETED_DEVICE_FAMILY = "1,2"; 518 | }; 519 | name = Debug; 520 | }; 521 | 105B0B7D25E1E94200527643 /* Release */ = { 522 | isa = XCBuildConfiguration; 523 | buildSettings = { 524 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 525 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 526 | CODE_SIGN_STYLE = Automatic; 527 | DEVELOPMENT_ASSET_PATHS = "\"SwiftUIPdf/Preview Content\""; 528 | DEVELOPMENT_TEAM = 69FAF79796; 529 | ENABLE_PREVIEWS = YES; 530 | INFOPLIST_FILE = SwiftUIPdf/Info.plist; 531 | IPHONEOS_DEPLOYMENT_TARGET = 14.0; 532 | LD_RUNPATH_SEARCH_PATHS = ( 533 | "$(inherited)", 534 | "@executable_path/Frameworks", 535 | ); 536 | PRODUCT_BUNDLE_IDENTIFIER = com.techchee.swiftui.tut.SwiftUIPdf; 537 | PRODUCT_NAME = "$(TARGET_NAME)"; 538 | SWIFT_VERSION = 5.0; 539 | TARGETED_DEVICE_FAMILY = "1,2"; 540 | }; 541 | name = Release; 542 | }; 543 | 105B0B7F25E1E94200527643 /* Debug */ = { 544 | isa = XCBuildConfiguration; 545 | buildSettings = { 546 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 547 | BUNDLE_LOADER = "$(TEST_HOST)"; 548 | CODE_SIGN_STYLE = Automatic; 549 | DEVELOPMENT_TEAM = 69FAF79796; 550 | INFOPLIST_FILE = SwiftUIPdfTests/Info.plist; 551 | IPHONEOS_DEPLOYMENT_TARGET = 14.0; 552 | LD_RUNPATH_SEARCH_PATHS = ( 553 | "$(inherited)", 554 | "@executable_path/Frameworks", 555 | "@loader_path/Frameworks", 556 | ); 557 | PRODUCT_BUNDLE_IDENTIFIER = com.techchee.swiftui.tut.SwiftUIPdfTests; 558 | PRODUCT_NAME = "$(TARGET_NAME)"; 559 | SWIFT_VERSION = 5.0; 560 | TARGETED_DEVICE_FAMILY = "1,2"; 561 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SwiftUIPdf.app/SwiftUIPdf"; 562 | }; 563 | name = Debug; 564 | }; 565 | 105B0B8025E1E94200527643 /* Release */ = { 566 | isa = XCBuildConfiguration; 567 | buildSettings = { 568 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 569 | BUNDLE_LOADER = "$(TEST_HOST)"; 570 | CODE_SIGN_STYLE = Automatic; 571 | DEVELOPMENT_TEAM = 69FAF79796; 572 | INFOPLIST_FILE = SwiftUIPdfTests/Info.plist; 573 | IPHONEOS_DEPLOYMENT_TARGET = 14.0; 574 | LD_RUNPATH_SEARCH_PATHS = ( 575 | "$(inherited)", 576 | "@executable_path/Frameworks", 577 | "@loader_path/Frameworks", 578 | ); 579 | PRODUCT_BUNDLE_IDENTIFIER = com.techchee.swiftui.tut.SwiftUIPdfTests; 580 | PRODUCT_NAME = "$(TARGET_NAME)"; 581 | SWIFT_VERSION = 5.0; 582 | TARGETED_DEVICE_FAMILY = "1,2"; 583 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SwiftUIPdf.app/SwiftUIPdf"; 584 | }; 585 | name = Release; 586 | }; 587 | 105B0B8225E1E94200527643 /* Debug */ = { 588 | isa = XCBuildConfiguration; 589 | buildSettings = { 590 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 591 | CODE_SIGN_STYLE = Automatic; 592 | DEVELOPMENT_TEAM = 69FAF79796; 593 | INFOPLIST_FILE = SwiftUIPdfUITests/Info.plist; 594 | LD_RUNPATH_SEARCH_PATHS = ( 595 | "$(inherited)", 596 | "@executable_path/Frameworks", 597 | "@loader_path/Frameworks", 598 | ); 599 | PRODUCT_BUNDLE_IDENTIFIER = com.techchee.swiftui.tut.SwiftUIPdfUITests; 600 | PRODUCT_NAME = "$(TARGET_NAME)"; 601 | SWIFT_VERSION = 5.0; 602 | TARGETED_DEVICE_FAMILY = "1,2"; 603 | TEST_TARGET_NAME = SwiftUIPdf; 604 | }; 605 | name = Debug; 606 | }; 607 | 105B0B8325E1E94200527643 /* Release */ = { 608 | isa = XCBuildConfiguration; 609 | buildSettings = { 610 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 611 | CODE_SIGN_STYLE = Automatic; 612 | DEVELOPMENT_TEAM = 69FAF79796; 613 | INFOPLIST_FILE = SwiftUIPdfUITests/Info.plist; 614 | LD_RUNPATH_SEARCH_PATHS = ( 615 | "$(inherited)", 616 | "@executable_path/Frameworks", 617 | "@loader_path/Frameworks", 618 | ); 619 | PRODUCT_BUNDLE_IDENTIFIER = com.techchee.swiftui.tut.SwiftUIPdfUITests; 620 | PRODUCT_NAME = "$(TARGET_NAME)"; 621 | SWIFT_VERSION = 5.0; 622 | TARGETED_DEVICE_FAMILY = "1,2"; 623 | TEST_TARGET_NAME = SwiftUIPdf; 624 | }; 625 | name = Release; 626 | }; 627 | /* End XCBuildConfiguration section */ 628 | 629 | /* Begin XCConfigurationList section */ 630 | 105B0B5125E1E94200527643 /* Build configuration list for PBXProject "SwiftUIPdf" */ = { 631 | isa = XCConfigurationList; 632 | buildConfigurations = ( 633 | 105B0B7925E1E94200527643 /* Debug */, 634 | 105B0B7A25E1E94200527643 /* Release */, 635 | ); 636 | defaultConfigurationIsVisible = 0; 637 | defaultConfigurationName = Release; 638 | }; 639 | 105B0B7B25E1E94200527643 /* Build configuration list for PBXNativeTarget "SwiftUIPdf" */ = { 640 | isa = XCConfigurationList; 641 | buildConfigurations = ( 642 | 105B0B7C25E1E94200527643 /* Debug */, 643 | 105B0B7D25E1E94200527643 /* Release */, 644 | ); 645 | defaultConfigurationIsVisible = 0; 646 | defaultConfigurationName = Release; 647 | }; 648 | 105B0B7E25E1E94200527643 /* Build configuration list for PBXNativeTarget "SwiftUIPdfTests" */ = { 649 | isa = XCConfigurationList; 650 | buildConfigurations = ( 651 | 105B0B7F25E1E94200527643 /* Debug */, 652 | 105B0B8025E1E94200527643 /* Release */, 653 | ); 654 | defaultConfigurationIsVisible = 0; 655 | defaultConfigurationName = Release; 656 | }; 657 | 105B0B8125E1E94200527643 /* Build configuration list for PBXNativeTarget "SwiftUIPdfUITests" */ = { 658 | isa = XCConfigurationList; 659 | buildConfigurations = ( 660 | 105B0B8225E1E94200527643 /* Debug */, 661 | 105B0B8325E1E94200527643 /* Release */, 662 | ); 663 | defaultConfigurationIsVisible = 0; 664 | defaultConfigurationName = Release; 665 | }; 666 | /* End XCConfigurationList section */ 667 | }; 668 | rootObject = 105B0B4E25E1E94200527643 /* Project object */; 669 | } 670 | -------------------------------------------------------------------------------- /SwiftUIPdf.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SwiftUIPdf.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /SwiftUIPdf.xcodeproj/xcuserdata/ketyung.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | SwiftUIPdf.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /SwiftUIPdf/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /SwiftUIPdf/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "scale" : "2x", 6 | "size" : "20x20" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "scale" : "3x", 11 | "size" : "20x20" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "scale" : "2x", 16 | "size" : "29x29" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "scale" : "3x", 21 | "size" : "29x29" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "scale" : "2x", 26 | "size" : "40x40" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "scale" : "3x", 31 | "size" : "40x40" 32 | }, 33 | { 34 | "filename" : "appiconpdf@2x.png", 35 | "idiom" : "iphone", 36 | "scale" : "2x", 37 | "size" : "60x60" 38 | }, 39 | { 40 | "filename" : "appiconpdf@3x.png", 41 | "idiom" : "iphone", 42 | "scale" : "3x", 43 | "size" : "60x60" 44 | }, 45 | { 46 | "idiom" : "ipad", 47 | "scale" : "1x", 48 | "size" : "20x20" 49 | }, 50 | { 51 | "idiom" : "ipad", 52 | "scale" : "2x", 53 | "size" : "20x20" 54 | }, 55 | { 56 | "idiom" : "ipad", 57 | "scale" : "1x", 58 | "size" : "29x29" 59 | }, 60 | { 61 | "idiom" : "ipad", 62 | "scale" : "2x", 63 | "size" : "29x29" 64 | }, 65 | { 66 | "idiom" : "ipad", 67 | "scale" : "1x", 68 | "size" : "40x40" 69 | }, 70 | { 71 | "idiom" : "ipad", 72 | "scale" : "2x", 73 | "size" : "40x40" 74 | }, 75 | { 76 | "filename" : "appiconpdf.png", 77 | "idiom" : "ipad", 78 | "scale" : "1x", 79 | "size" : "76x76" 80 | }, 81 | { 82 | "filename" : "appiconpdf@2x-1.png", 83 | "idiom" : "ipad", 84 | "scale" : "2x", 85 | "size" : "76x76" 86 | }, 87 | { 88 | "filename" : "appiconpdf@2x-2.png", 89 | "idiom" : "ipad", 90 | "scale" : "2x", 91 | "size" : "83.5x83.5" 92 | }, 93 | { 94 | "idiom" : "ios-marketing", 95 | "scale" : "1x", 96 | "size" : "1024x1024" 97 | } 98 | ], 99 | "info" : { 100 | "author" : "xcode", 101 | "version" : 1 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /SwiftUIPdf/Assets.xcassets/AppIcon.appiconset/appiconpdf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ketyung/SwiftUIPdf/7cc45e34ded533dad372dc9b9d495ed81786ef76/SwiftUIPdf/Assets.xcassets/AppIcon.appiconset/appiconpdf.png -------------------------------------------------------------------------------- /SwiftUIPdf/Assets.xcassets/AppIcon.appiconset/appiconpdf@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ketyung/SwiftUIPdf/7cc45e34ded533dad372dc9b9d495ed81786ef76/SwiftUIPdf/Assets.xcassets/AppIcon.appiconset/appiconpdf@2x-1.png -------------------------------------------------------------------------------- /SwiftUIPdf/Assets.xcassets/AppIcon.appiconset/appiconpdf@2x-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ketyung/SwiftUIPdf/7cc45e34ded533dad372dc9b9d495ed81786ef76/SwiftUIPdf/Assets.xcassets/AppIcon.appiconset/appiconpdf@2x-2.png -------------------------------------------------------------------------------- /SwiftUIPdf/Assets.xcassets/AppIcon.appiconset/appiconpdf@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ketyung/SwiftUIPdf/7cc45e34ded533dad372dc9b9d495ed81786ef76/SwiftUIPdf/Assets.xcassets/AppIcon.appiconset/appiconpdf@2x.png -------------------------------------------------------------------------------- /SwiftUIPdf/Assets.xcassets/AppIcon.appiconset/appiconpdf@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ketyung/SwiftUIPdf/7cc45e34ded533dad372dc9b9d495ed81786ef76/SwiftUIPdf/Assets.xcassets/AppIcon.appiconset/appiconpdf@3x.png -------------------------------------------------------------------------------- /SwiftUIPdf/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /SwiftUIPdf/Assets.xcassets/techchee_logo.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "techchee_logo.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "techchee_logo@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "techchee_logo@3x.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SwiftUIPdf/Assets.xcassets/techchee_logo.imageset/techchee_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ketyung/SwiftUIPdf/7cc45e34ded533dad372dc9b9d495ed81786ef76/SwiftUIPdf/Assets.xcassets/techchee_logo.imageset/techchee_logo.png -------------------------------------------------------------------------------- /SwiftUIPdf/Assets.xcassets/techchee_logo.imageset/techchee_logo@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ketyung/SwiftUIPdf/7cc45e34ded533dad372dc9b9d495ed81786ef76/SwiftUIPdf/Assets.xcassets/techchee_logo.imageset/techchee_logo@2x.png -------------------------------------------------------------------------------- /SwiftUIPdf/Assets.xcassets/techchee_logo.imageset/techchee_logo@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ketyung/SwiftUIPdf/7cc45e34ded533dad372dc9b9d495ed81786ef76/SwiftUIPdf/Assets.xcassets/techchee_logo.imageset/techchee_logo@3x.png -------------------------------------------------------------------------------- /SwiftUIPdf/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UIApplicationSceneManifest 24 | 25 | UIApplicationSupportsMultipleScenes 26 | 27 | 28 | UIApplicationSupportsIndirectInputEvents 29 | 30 | UILaunchScreen 31 | 32 | UIRequiredDeviceCapabilities 33 | 34 | armv7 35 | 36 | UISupportedInterfaceOrientations 37 | 38 | UIInterfaceOrientationPortrait 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UISupportedInterfaceOrientations~ipad 43 | 44 | UIInterfaceOrientationPortrait 45 | UIInterfaceOrientationPortraitUpsideDown 46 | UIInterfaceOrientationLandscapeLeft 47 | UIInterfaceOrientationLandscapeRight 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /SwiftUIPdf/Models/Content.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Content.swift 3 | // SwiftUIPdf 4 | // 5 | // Created by Chee Ket Yung on 21/02/2021. 6 | // 7 | 8 | import Foundation 9 | 10 | 11 | struct Content { 12 | 13 | var title : String = "" 14 | 15 | var body : String = "" 16 | 17 | } 18 | -------------------------------------------------------------------------------- /SwiftUIPdf/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /SwiftUIPdf/SwiftUIPdfApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftUIPdfApp.swift 3 | // SwiftUIPdf 4 | // 5 | // Created by Chee Ket Yung on 21/02/2021. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main struct SwiftUIPdfApp: App { 11 | 12 | var body: some Scene { 13 | WindowGroup { 14 | MenuView() 15 | .environmentObject(ContentViewModel()) 16 | //ContentView() 17 | 18 | } 19 | 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SwiftUIPdf/Utilities/Extensions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Extensions.swift 3 | // SwiftUIPdf 4 | // 5 | // Created by Chee Ket Yung on 21/02/2021. 6 | // 7 | 8 | import SwiftUI 9 | import UIKit 10 | 11 | extension View { 12 | func hideKeyboard() { 13 | UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /SwiftUIPdf/Utilities/PdfCreator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PdfCreator.swift 3 | // SwiftUIPdf 4 | // 5 | // Created by Chee Ket Yung on 21/02/2021. 6 | // 7 | 8 | import PDFKit 9 | 10 | class PdfCreator : NSObject { 11 | 12 | private var pageRect : CGRect 13 | 14 | private var renderer : UIGraphicsPDFRenderer? 15 | 16 | 17 | /** 18 | W: 8.5 inches * 72 DPI = 612 points 19 | H: 11 inches * 72 DPI = 792 points 20 | A4 = [W x H] 595 x 842 points 21 | */ 22 | init(pageRect : CGRect = CGRect(x: 0, y: 0, width: (8.5 * 72.0), height: (11 * 72.0))) { 23 | 24 | let format = UIGraphicsPDFRendererFormat() 25 | let metaData = [ 26 | kCGPDFContextTitle: "It's a PDF!", 27 | kCGPDFContextAuthor: "TechChee" 28 | ] 29 | format.documentInfo = metaData as [String: Any] 30 | 31 | self.pageRect = pageRect 32 | self.renderer = UIGraphicsPDFRenderer(bounds: self.pageRect, 33 | format: format) 34 | super.init() 35 | } 36 | 37 | deinit { 38 | 39 | self.renderer = nil 40 | } 41 | 42 | } 43 | 44 | extension PdfCreator { 45 | 46 | private func addTitle ( title : String ){ 47 | 48 | let textRect = CGRect(x: 20, y: 20, // top margin 49 | width: pageRect.width - 40 ,height: 40) 50 | 51 | title.draw(in: textRect, withAttributes: [NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 30)]) 52 | 53 | } 54 | 55 | private func addBody (body : String) { 56 | 57 | 58 | let paragraphStyle = NSMutableParagraphStyle() 59 | paragraphStyle.alignment = .justified 60 | 61 | let attributes = [ 62 | NSAttributedString.Key.font: UIFont.systemFont(ofSize: 20), 63 | NSAttributedString.Key.paragraphStyle: paragraphStyle, 64 | NSAttributedString.Key.foregroundColor : UIColor.gray 65 | ] 66 | 67 | let bodyRect = CGRect(x: 20, y: 70, 68 | width: pageRect.width - 40 ,height: pageRect.height - 80) 69 | body.draw(in: bodyRect, withAttributes: attributes) 70 | } 71 | } 72 | 73 | extension PdfCreator { 74 | 75 | func pdfData( title : String, body: String ) -> Data? { 76 | 77 | if let renderer = self.renderer { 78 | 79 | let data = renderer.pdfData { ctx in 80 | 81 | ctx.beginPage() 82 | 83 | addTitle(title: title) 84 | 85 | addBody(body: body) 86 | 87 | addWaterMarkAtBottom() 88 | } 89 | 90 | return data 91 | 92 | } 93 | 94 | return nil 95 | } 96 | } 97 | 98 | extension PdfCreator { 99 | 100 | func pdfDoc( title : String, body: String ) -> PDFDocument? { 101 | 102 | if let data = self.pdfData(title: title, body: body){ 103 | 104 | return PDFDocument(data: data) 105 | } 106 | 107 | return nil 108 | } 109 | } 110 | 111 | 112 | extension PdfCreator { 113 | 114 | func addWaterMarkAtBottom(){ 115 | 116 | if let logo = UIImage(named: "techchee_logo") { 117 | 118 | let attributes = [ 119 | NSAttributedString.Key.font: UIFont.systemFont(ofSize: 20), 120 | NSAttributedString.Key.foregroundColor : UIColor.lightGray 121 | ] 122 | 123 | let logoAt = CGRect(x: pageRect.size.width - (logo.size.width + 10), y: pageRect.height - (logo.size.height + 10), 124 | width: logo.size.width, height: logo.size.height) 125 | 126 | 127 | let textAt = CGRect (x: logoAt.origin.x - 102, y : logoAt.origin.y + 2, width:100, height: 30 ) 128 | 129 | let text = "Created By " 130 | 131 | text.draw(in : textAt, withAttributes : attributes) 132 | 133 | logo.draw(in: logoAt) 134 | 135 | } 136 | } 137 | 138 | 139 | 140 | } 141 | -------------------------------------------------------------------------------- /SwiftUIPdf/ViewControllers/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // SwiftUIPdf 4 | // 5 | // Created by Chee Ket Yung on 23/02/2021. 6 | // 7 | 8 | import UIKit 9 | import PDFKit 10 | 11 | class ViewController : UIViewController { 12 | 13 | private var data : Data? 14 | 15 | override func viewDidLoad() { 16 | super.viewDidLoad() 17 | createPdfView() 18 | createShareButton() 19 | } 20 | 21 | 22 | private func createPdfView(){ 23 | 24 | let pdfMetaData = [kCGPDFContextCreator: "My First PDF File", 25 | kCGPDFContextAuthor: "TechChee.com"] 26 | 27 | let format = UIGraphicsPDFRendererFormat() 28 | format.documentInfo = pdfMetaData as [String: Any] 29 | 30 | let pageRect = CGRect(x:0, y:0, width: 500, height: 600) 31 | 32 | 33 | let renderer = UIGraphicsPDFRenderer(bounds:pageRect , format: format) 34 | 35 | 36 | self.data = renderer.pdfData{ context in 37 | context.beginPage() // call it when you need to start a new page 38 | let attributes = [NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 30)] 39 | 40 | let text = "My First PDF file" 41 | text.draw(in : CGRect(x: 20, y: 30, width: 300, height: 50), withAttributes: attributes) 42 | 43 | if let image = UIImage(named: "techchee_logo"){ 44 | // loop to draw 12 images 45 | for i in (0 ..< 12){ 46 | 47 | let y : CGFloat = 100 + (image.size.height * CGFloat(i)) + (10 * CGFloat(i)) 48 | let num = "\(String(format: "%02d", i+1)) " 49 | num.draw(in: CGRect(x: 20, y : y + 3 , width: 30, height: 30), 50 | withAttributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 20)]) 51 | image.draw(in: CGRect(x: 60, y : y, width: image.size.width , height: image.size.height) ) 52 | } 53 | } 54 | } 55 | 56 | if let data = self.data { 57 | 58 | let pdfView = PDFView(frame: CGRect(x: 10, y : 10, width: self.view.frame.size.width - 20, 59 | height: self.view.frame.size.height * 0.6)) 60 | pdfView.autoScales = true 61 | pdfView.document = PDFDocument(data: data) 62 | 63 | self.view.addSubview( pdfView ) 64 | 65 | } 66 | } 67 | 68 | 69 | 70 | 71 | private func createShareButton() { 72 | 73 | 74 | let y = (self.view.frame.height * 0.6) + 20 75 | let button:UIButton = UIButton(frame: CGRect(x: (self.view.frame.size.width - 200) / 2, y: y , width: 200, height: 50)) 76 | button.backgroundColor = .black 77 | button.setTitle("Share", for: .normal) 78 | button.addTarget(self, action:#selector(self.shareButtonClicked), for: .touchUpInside) 79 | self.view.addSubview(button) 80 | 81 | } 82 | 83 | 84 | @objc private func shareButtonClicked() { 85 | 86 | if let data = data { 87 | 88 | let sharer = UIActivityViewController(activityItems: [data], applicationActivities: nil) 89 | self.present(sharer, animated:true) 90 | } 91 | 92 | } 93 | 94 | } 95 | -------------------------------------------------------------------------------- /SwiftUIPdf/ViewModels/ContentViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentViewModel.swift 3 | // SwiftUIPdf 4 | // 5 | // Created by Chee Ket Yung on 21/02/2021. 6 | // 7 | 8 | import Foundation 9 | import PDFKit 10 | 11 | class ContentViewModel : ObservableObject { 12 | 13 | @Published private var content = Content() 14 | 15 | var title : String { 16 | 17 | get { content.title } 18 | 19 | set (newTitle) { 20 | 21 | content.title = newTitle 22 | } 23 | } 24 | 25 | var body : String { 26 | 27 | get { content.body } 28 | 29 | set(newBody) { 30 | 31 | content.body = newBody 32 | } 33 | } 34 | } 35 | 36 | 37 | extension ContentViewModel { 38 | 39 | func clear(){ 40 | 41 | self.title = "" 42 | self.body = "" 43 | } 44 | } 45 | 46 | extension ContentViewModel { 47 | 48 | 49 | func pdfData() -> Data? { 50 | 51 | return PdfCreator().pdfData(title: self.title, body: self.body) 52 | } 53 | 54 | func pdfDoc() -> PDFDocument? { 55 | 56 | let pdfCreator = PdfCreator() 57 | return pdfCreator.pdfDoc(title: self.title, body: self.body) 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /SwiftUIPdf/Views/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // SwiftUIPdf 4 | // 5 | // Created by Chee Ket Yung on 21/02/2021. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ContentView: View { 11 | 12 | @EnvironmentObject private var contentViewModel : ContentViewModel 13 | 14 | 15 | var body: some View { 16 | 17 | // NavigationView { 18 | VStack { 19 | 20 | form() 21 | 22 | buttons() 23 | 24 | Spacer() 25 | } 26 | .navigationTitle(Text("PDF Composer")) 27 | //} 28 | } 29 | } 30 | 31 | extension ContentView { 32 | 33 | private func form() -> some View { 34 | 35 | Form { 36 | 37 | TextField("Title", text: $contentViewModel.title ) 38 | 39 | Text("Body") 40 | .font(.headline) 41 | 42 | TextEditor(text: $contentViewModel.body) 43 | .frame(height: 100) 44 | 45 | } 46 | .frame(height: 270) 47 | .padding(4) 48 | } 49 | 50 | 51 | private func buttons() -> some View { 52 | 53 | HStack(spacing : 50) { 54 | 55 | NavigationLink(destination : PdfPreviewView() ){ 56 | Text("Create") 57 | .padding(10) 58 | .frame(width: 100) 59 | .background(Color.blue) 60 | .foregroundColor(.white) 61 | .cornerRadius(20) 62 | } 63 | 64 | Button(action: { 65 | 66 | contentViewModel.clear() 67 | hideKeyboard() 68 | 69 | }, label: { 70 | 71 | Text("Clear") 72 | .padding(10) 73 | .frame(width: 100) 74 | .background(Color.red) 75 | .foregroundColor(.white) 76 | .cornerRadius(20) 77 | }) 78 | } 79 | } 80 | } 81 | 82 | struct ContentView_Previews: PreviewProvider { 83 | static var previews: some View { 84 | ContentView() 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /SwiftUIPdf/Views/MenuView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MenuView.swift 3 | // SwiftUIPdf 4 | // 5 | // Created by Chee Ket Yung on 23/02/2021. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct MenuView : View { 11 | 12 | 13 | var body : some View { 14 | 15 | NavigationView { 16 | 17 | List { 18 | 19 | NavigationLink( destination: ContentView()){ 20 | 21 | Text ("1. A simple PDF composer app created in SwiftUI and the MVVM way") 22 | } 23 | 24 | NavigationLink( destination: ViewControllerSwiftUIView().navigationTitle(Text("Example 1")) ){ 25 | 26 | Text ("2. An example of PDF created in a UIKit ViewController and is wrapped by UIViewControllerRepresentable in SwiftUI") 27 | } 28 | 29 | 30 | NavigationLink( destination: WebView(urlString: "https://blog.techchee.com/pdf-composer-app-swiftui") ){ 31 | 32 | Text ("3. The tutorial blog post explaining No 1. on how to create a simple PDF composer app in SwiftUI") 33 | } 34 | 35 | } 36 | .navigationTitle(Text("Menu")) 37 | 38 | } 39 | .navigationViewStyle(StackNavigationViewStyle()) 40 | 41 | 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /SwiftUIPdf/Views/PdfPreviewView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PdrPreviewView.swift 3 | // SwiftUIPdf 4 | // 5 | // Created by Chee Ket Yung on 21/02/2021. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct PdfPreviewView : View { 11 | 12 | @EnvironmentObject private var contentViewModel : ContentViewModel 13 | 14 | @State private var showShareSheet : Bool = false 15 | 16 | var body: some View { 17 | 18 | VStack { 19 | 20 | PdfViewUI(data: contentViewModel.pdfData()) 21 | 22 | shareButton() 23 | 24 | Spacer() 25 | } 26 | .navigationTitle(Text("Your PDF")) 27 | .navigationBarTitleDisplayMode(.inline) 28 | .sheet(isPresented: $showShareSheet, content: { 29 | 30 | if let data = contentViewModel.pdfData() { 31 | ShareView(activityItems: [data]) 32 | } 33 | }) 34 | 35 | } 36 | 37 | } 38 | 39 | 40 | extension PdfPreviewView { 41 | 42 | private func shareButton() -> some View { 43 | 44 | Button(action: { 45 | self.showShareSheet.toggle() 46 | }, label: { 47 | Text("Share") 48 | .padding(10) 49 | .frame(width: 100) 50 | .background(Color.blue) 51 | .foregroundColor(.white) 52 | .cornerRadius(20) 53 | 54 | }) 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /SwiftUIPdf/Views/PdfViewUI.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PdfViewUI.swift 3 | // SwiftUIPdf 4 | // 5 | // Created by Chee Ket Yung on 21/02/2021. 6 | // 7 | 8 | import SwiftUI 9 | import PDFKit 10 | 11 | struct PdfViewUI : UIViewRepresentable { 12 | 13 | private var data: Data? 14 | 15 | private let autoScales : Bool 16 | 17 | init(data : Data?, autoScales : Bool = true ) { 18 | self.data = data 19 | self.autoScales = autoScales 20 | } 21 | 22 | func makeUIView(context: Context) -> PDFView { 23 | let pdfView = PDFView() 24 | 25 | pdfView.autoScales = self.autoScales 26 | 27 | if let data = self.data { 28 | 29 | pdfView.document = PDFDocument(data: data) 30 | 31 | } 32 | 33 | return pdfView 34 | } 35 | 36 | func updateUIView(_ uiView: PDFView, context: Context) { 37 | // Empty 38 | } 39 | 40 | } 41 | 42 | -------------------------------------------------------------------------------- /SwiftUIPdf/Views/ShareView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ActivityView.swift 3 | // SwiftUIPdf 4 | // 5 | // Created by Chee Ket Yung on 21/02/2021. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ShareView: UIViewControllerRepresentable { 11 | 12 | let activityItems: [Any] 13 | let applicationActivities: [UIActivity]? = nil 14 | 15 | func makeUIViewController(context: UIViewControllerRepresentableContext) -> UIActivityViewController { 16 | return UIActivityViewController(activityItems: activityItems,applicationActivities: applicationActivities) 17 | } 18 | 19 | func updateUIViewController(_ uiViewController: UIActivityViewController, 20 | context: UIViewControllerRepresentableContext) { 21 | // empty 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SwiftUIPdf/Views/ViewControllerSwiftUIView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewControllerSwiftUIView.swift 3 | // SwiftUIPdf 4 | // 5 | // Created by Chee Ket Yung on 23/02/2021. 6 | // 7 | 8 | import SwiftUI 9 | 10 | 11 | struct ViewControllerSwiftUIView: UIViewControllerRepresentable { 12 | 13 | 14 | func makeUIViewController(context: UIViewControllerRepresentableContext) -> ViewController { 15 | return ViewController() 16 | } 17 | 18 | func updateUIViewController(_ uiViewController: ViewController, 19 | context: UIViewControllerRepresentableContext) { 20 | 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /SwiftUIPdf/Views/WebView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WebView.swift 3 | // SwiftUINavigation 4 | // 5 | // Created by Chee Ket Yung on 10/01/2021. 6 | // 7 | 8 | import SwiftUI 9 | import WebKit 10 | 11 | struct WebView : UIViewRepresentable { 12 | 13 | let urlString : String 14 | 15 | func makeUIView(context: Context) -> WKWebView { 16 | return WKWebView() 17 | } 18 | 19 | func updateUIView(_ uiView: WKWebView, context: Context) { 20 | 21 | if let url = URL(string: urlString) { 22 | 23 | uiView.load( URLRequest(url: url ) ) 24 | } 25 | } 26 | 27 | } 28 | 29 | struct WebView_Previews : PreviewProvider { 30 | static var previews: some View { 31 | WebView(urlString: "https://techchee.com" ) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /SwiftUIPdfTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /SwiftUIPdfTests/SwiftUIPdfTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftUIPdfTests.swift 3 | // SwiftUIPdfTests 4 | // 5 | // Created by Chee Ket Yung on 21/02/2021. 6 | // 7 | 8 | import XCTest 9 | @testable import SwiftUIPdf 10 | 11 | class SwiftUIPdfTests: XCTestCase { 12 | 13 | override func setUpWithError() throws { 14 | // Put setup code here. This method is called before the invocation of each test method in the class. 15 | } 16 | 17 | override func tearDownWithError() throws { 18 | // Put teardown code here. This method is called after the invocation of each test method in the class. 19 | } 20 | 21 | func testExample() throws { 22 | // This is an example of a functional test case. 23 | // Use XCTAssert and related functions to verify your tests produce the correct results. 24 | } 25 | 26 | func testPerformanceExample() throws { 27 | // This is an example of a performance test case. 28 | self.measure { 29 | // Put the code you want to measure the time of here. 30 | } 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /SwiftUIPdfUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /SwiftUIPdfUITests/SwiftUIPdfUITests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftUIPdfUITests.swift 3 | // SwiftUIPdfUITests 4 | // 5 | // Created by Chee Ket Yung on 21/02/2021. 6 | // 7 | 8 | import XCTest 9 | 10 | class SwiftUIPdfUITests: XCTestCase { 11 | 12 | override func setUpWithError() throws { 13 | // Put setup code here. This method is called before the invocation of each test method in the class. 14 | 15 | // In UI tests it is usually best to stop immediately when a failure occurs. 16 | continueAfterFailure = false 17 | 18 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 19 | } 20 | 21 | override func tearDownWithError() throws { 22 | // Put teardown code here. This method is called after the invocation of each test method in the class. 23 | } 24 | 25 | func testExample() throws { 26 | // UI tests must launch the application that they test. 27 | let app = XCUIApplication() 28 | app.launch() 29 | 30 | // Use recording to get started writing UI tests. 31 | // Use XCTAssert and related functions to verify your tests produce the correct results. 32 | } 33 | 34 | func testLaunchPerformance() throws { 35 | if #available(macOS 10.15, iOS 13.0, tvOS 13.0, *) { 36 | // This measures how long it takes to launch your application. 37 | measure(metrics: [XCTApplicationLaunchMetric()]) { 38 | XCUIApplication().launch() 39 | } 40 | } 41 | } 42 | } 43 | --------------------------------------------------------------------------------