├── .vscode ├── extensions.json ├── launch.json ├── settings.json └── tasks.json ├── .gitignore ├── Application ├── Application.swift └── Info.plist ├── .swiftlint.yml ├── Main ├── Sources │ └── ContentView.swift └── Package.swift ├── project.yml └── README.md /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "nisargjhaveri.ios-debug", 4 | "sswg.swift-lang", 5 | "vknabel.vscode-swiftlint" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## User settings 2 | xcuserdata/ 3 | **/xcuserdata/ 4 | 5 | ## Generating version stuff 6 | *.ipa 7 | *.dSYM.* 8 | 9 | #xcodegen 10 | Demo.xcodeproj 11 | 12 | # build 13 | .derivedData 14 | .packages 15 | .build 16 | .swiftpm 17 | 18 | *.resolved 19 | -------------------------------------------------------------------------------- /Application/Application.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | import Main 3 | 4 | #if DEBUG 5 | @_exported import Inject 6 | #endif 7 | 8 | @main 9 | struct Application: App { 10 | var body: some Scene { 11 | WindowGroup { 12 | ContentView() 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /.swiftlint.yml: -------------------------------------------------------------------------------- 1 | swiftlint_version: 0.47.1 2 | 3 | excluded: 4 | - .vscode 5 | - .build 6 | 7 | opt_in_rules: 8 | - empty_count 9 | - empty_string 10 | - indentation_width 11 | 12 | identifier_name: 13 | min_length: 1 14 | max_length: 80 15 | 16 | type_name: 17 | min_length: 1 18 | max_length: 80 19 | 20 | indentation: 2 21 | 22 | indentation_width: 23 | indentation_width: 2 24 | -------------------------------------------------------------------------------- /Main/Sources/ContentView.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | 3 | #if DEBUG 4 | import Inject 5 | #endif 6 | 7 | public struct ContentView: View { 8 | public init() { 9 | 10 | } 11 | 12 | public var body: some View { 13 | VStack { 14 | Text("Testing") 15 | .padding() 16 | .background(Color.red) 17 | .border(.blue) 18 | } 19 | .enableInjection() 20 | } 21 | 22 | #if DEBUG 23 | @ObserveInjection var inject 24 | #endif 25 | } 26 | -------------------------------------------------------------------------------- /project.yml: -------------------------------------------------------------------------------- 1 | name: Demo 2 | options: 3 | bundleIdPrefix: dev.mt 4 | packages: 5 | Main: 6 | path: ./Main 7 | targets: 8 | Demo: 9 | type: application 10 | platform: iOS 11 | deploymentTarget: "14.0" 12 | sources: [Application] 13 | dependencies: 14 | - sdk: SwiftUI.framework 15 | - package: Main 16 | settings: 17 | base: 18 | CURRENT_PROJECT_VERSION: 1 19 | MARKETING_VERSION: 1 20 | OTHER_LDFLAGS: "-Xlinker -interposable -Xlinker -undefined -Xlinker dynamic_lookup" 21 | INFOPLIST_FILE: "Application/Info.plist" 22 | -------------------------------------------------------------------------------- /Application/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleIdentifier 6 | $(PRODUCT_BUNDLE_IDENTIFIER) 7 | CFBundleName 8 | $(PRODUCT_NAME) 9 | CFBundleShortVersionString 10 | $(MARKETING_VERSION) 11 | CFBundleVersion 12 | $(CURRENT_PROJECT_VERSION) 13 | CFBundleExecutable 14 | $(EXECUTABLE_NAME) 15 | 16 | 17 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | // A launch configuration that compiles the extension and then opens it inside a new window 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | { 6 | "version": "0.2.0", 7 | "configurations": [ 8 | { 9 | "type": "lldb", 10 | "request": "launch", 11 | "name": "xcodegen", 12 | "program": "xcodegen" 13 | }, 14 | { 15 | "name": "Launch", 16 | "type": "lldb", 17 | "request": "launch", 18 | "program": "~/Library/Developer/Xcode/DerivedData/Demo/Build/Products/Debug-${command:ios-debug.targetSdk}/Demo.app", 19 | "iosBundleId": "dev.mt.Demo", 20 | "iosTarget": "select", 21 | "preLaunchTask": "${defaultBuildTask}" 22 | } 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /Main/Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.5.0 2 | // The swift-tools-version declares the minimum version of Swift required to build this package. 3 | 4 | import PackageDescription 5 | 6 | let packageName = "Main" 7 | 8 | // Necessary for `sourcekit-lsp` support in VSCode:` 9 | 10 | let package = Package( 11 | name: packageName, 12 | platforms: [ 13 | .iOS(.v14), 14 | // disable building on macOS 15 | .macOS("99.0") 16 | ], 17 | products: [ 18 | .library(name: packageName, targets: [packageName]) 19 | ], 20 | dependencies: [ 21 | .package(url: "https://github.com/krzysztofzablocki/Inject.git", .branch("main")), 22 | .package(url: "https://github.com/johnno1962/HotReloading.git", .branch("main")) 23 | ], 24 | targets: [ 25 | .target( 26 | name: packageName, 27 | dependencies: [ 28 | .byNameItem( 29 | name: "Inject", 30 | condition: .when(platforms: [ 31 | .iOS 32 | ]) 33 | ), 34 | .byNameItem( 35 | name: "HotReloading", 36 | condition: .when(platforms: [ 37 | .iOS 38 | ]) 39 | ) 40 | ], 41 | path: "Sources" 42 | ) 43 | ] 44 | ) 45 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.defaultFormatter": "esbenp.prettier-vscode", 3 | "editor.formatOnSave": true, 4 | "editor.codeActionsOnSave": { 5 | "source.fixAll": "explicit" 6 | }, 7 | 8 | "[swift]": { 9 | "editor.defaultFormatter": "vknabel.vscode-swiftlint" 10 | }, 11 | 12 | "swiftlint.enable": true, 13 | "swiftlint.configSearchPaths": ["./.swiftlint.yml"], 14 | "swiftlint.autoLintWorkspace": false, 15 | "swiftlint.additionalParameters": ["--format"], 16 | 17 | "sourcekit-lsp.toolchainPath": "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain", 18 | "sourcekit-lsp.serverPath": "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/sourcekit-lsp", 19 | "sourcekit-lsp.serverArguments": [ 20 | "-Xswiftc", 21 | "-sdk", 22 | "-Xswiftc", 23 | "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk", 24 | "-Xswiftc", 25 | "-target", 26 | "-Xswiftc", 27 | "arm64-apple-ios13.0-simulator", 28 | "-Xcc", 29 | "-DSWIFT_PACKAGE=0" // Build package as if it were Application? 30 | ] 31 | 32 | // "swift.SDK" 33 | // "swift.buildPath": "~/Library/Developer/Xcode/DerivedData/Demo", 34 | // "swift.backgroundCompilation": true, 35 | // "swift.buildArguments": [] 36 | } 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SwiftUI iOS Debug & HotReloading in VSCode 2 | 3 | Demonstrating vscode development environment using xcodegen + HotReloading. 4 | 5 | - Language Server Protocol for Swift with [vscode-swift](https://github.com/swift-server/vscode-swift) extension. 6 | - Lint Swift with [SwiftLint](https://github.com/shinnn/vscode-swiftlint) extension. 7 | - Xcode project generating using [XcodeGen](https://github.com/yonaskolb/XcodeGen) 8 | - Launch & debugging with lldb [iOS Debug](https://github.com/nisargjhaveri/vscode-ios-debug) 9 | - HotReloading & Injection with [HotReloading](https://github.com/johnno1962/HotReloading) 10 | - SwiftUI injection property wrapper with [Inject](https://github.com/krzysztofzablocki/Inject.git) 11 | 12 | ![hotreloading-vscode-ios 2022-06-03 20_10_56](https://user-images.githubusercontent.com/274318/171922061-cabbb0aa-b2ba-4ade-a606-41a06c3c2ca3.gif) 13 | 14 | ## XcodeGen Extension for Visual Studio Code 15 | 16 | I have begun the development of an XcodeGen Extension for Visual Studio Code, designed to further streamline the process of working with Xcode projects in VSCode. This extension aims to make it easier to generate and manage Xcode project files directly from the VSCode environment. 17 | 18 | For more information, updates, and contributions, check out the extension repository: [vscode-xcodegen-builder](https://github.com/markst/vscode-xcodegen-builder). 19 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | // See https://go.microsoft.com/fwlink/?LinkId=733558 2 | // for the documentation about the tasks.json format 3 | { 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "type": "swift", 8 | "problemMatcher": ["$swiftc"], 9 | "group": "build", 10 | "label": "swift: Build Dependencies", 11 | "runOptions": { 12 | "runOn": "folderOpen" 13 | }, 14 | "command": "swift", 15 | "args": [ 16 | "build", 17 | "--target", 18 | "Inject", 19 | "-Xswiftc", 20 | "-sdk", 21 | "-Xswiftc", 22 | "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk", 23 | "-Xswiftc", 24 | "-target", 25 | "-Xswiftc", 26 | "arm64-apple-ios13.0-simulator" 27 | ], 28 | "options": { 29 | "cwd": "${workspaceFolder}/Main" 30 | } 31 | }, 32 | { 33 | "label": "xcodegen", 34 | "type": "process", 35 | "command": "xcodegen" 36 | }, 37 | { 38 | "label": "clean", 39 | "type": "shell", 40 | "command": "rm -R -f ~/Library/Developer/Xcode/DerivedData/Demo/Result.xcresult" 41 | }, 42 | { 43 | "label": "xcodebuild", 44 | "type": "process", 45 | "command": "xcodebuild", 46 | "args": [ 47 | "-scheme", 48 | "Demo", 49 | "-configuration", 50 | "Debug", 51 | "-sdk", 52 | "${command:ios-debug.targetSdk}", 53 | "-derivedDataPath", 54 | "~/Library/Developer/Xcode/DerivedData/Demo", // <- use `BUILD_DIR`? 55 | "-clonedSourcePackagesDirPath", 56 | "./Main/.build", 57 | "-resultBundlePath", 58 | "~/Library/Developer/Xcode/DerivedData/Demo/Result.xcresult", 59 | "-allowProvisioningUpdates", 60 | "ARCHS=arm64" 61 | ], 62 | "group": { 63 | "kind": "build", 64 | "isDefault": true 65 | }, 66 | "dependsOn": ["xcodegen", "clean"] 67 | } 68 | ] 69 | } 70 | --------------------------------------------------------------------------------