Administrator
发布于 2026-02-24 / 2 阅读
0
0

VSCode的Swift/SwiftUI配置

行,我给你一套**“Swift Workspace 全工具链一键调试”**的落地方案:

目标是在 VS Code 里同时搞定:

  • iOS App(SweetPad 跑模拟器/真机 + Debug)

  • LSP(SourceKit-LSP + xcode-build-server 稳定索引)

  • SwiftPM CLI(indexer / project-index 一键 debug / release)

  • Vapor(本地 run + attach / 或直接 Debug 启动)

  • 常用脚本(重建 BSP、清 DerivedData、重置包缓存)

下面按文件+路径+内容给你,基本照抄就能用。


0. 约定你的项目结构

你现在大概率类似这样(按你提供的 cwd):

AIChats/
├─ AIChats.xcodeproj
├─ Workspace/                  (可选:SwiftPM workspace 或 Sources)
├─ ProjectArchitecture/
│  └─ indexer/                 (SwiftPM 包,含 target: project-index)
│     ├─ Package.swift
│     └─ Sources/...
├─ .vscode/
│  ├─ settings.json
│  ├─ tasks.json
│  └─ launch.json
└─ .bsp/
   └─ xcode-build-server.json  (或在项目根由工具生成)

你已经有 xcode-build-server.json 了,后面我会把“重生成”也变成一键 task。


1) VS Code 插件建议(最小必装)

  • SweetPad(iOS build/run/debug)

  • Swift(swiftlang.swift-vscode:SwiftPM build/debug + SourceKit-LSP 生态)

(你装过的那些就不赘述了)


2) 

.vscode/settings.json

目标:

  • SourceKit-LSP 优先走 BSP(xcode-build-server)

  • 避免 VSCode 自动在根目录跑 swift package describe(你之前看到 “找不到 Package.swift” 就是因为它在错误目录触发)

创建/更新:AIChats/.vscode/settings.json

{
  // 让 Swift 扩展不要乱猜 workspace 的 SwiftPM 根(避免自动 describe 报错)
  "swift.disableSwiftPackageManagerIntegration": true,

  // 让 SourceKit-LSP 通过 BSP 获取编译命令(xcode-build-server)
  "swift.sourcekit-lsp.serverPath": "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/sourcekit-lsp",
  "swift.sourcekit-lsp.toolchainPath": "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain",
  "swift.sourcekit-lsp.useBsp": true,

  // 可选:减少索引抖动
  "swift.sourcekit-lsp.backgroundIndexing": true,

  // SweetPad 通常不需要额外设置;如果你有 workspace scheme,保证 scheme 可见即可
  "sweetpad.showBuildOutput": true
}

关键是 "swift.disableSwiftPackageManagerIntegration": true:

这样 Swift 扩展就不会在项目根目录莫名其妙跑 swift package describe,你也不会再看到“找不到 Package.swift”的任务报错(除非你自己手动触发)。


3) 一键任务:

.vscode/tasks.json

创建:AIChats/.vscode/tasks.json

里面我放了 8 个常用任务:

  • 生成/重生成 BSP(xcode-build-server)

  • 清理 DerivedData / build_root

  • SwiftPM build indexer debug/release

  • Vapor run(如果你有 vapor 包路径)

  • 组合任务:一键重建索引链路

{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "BSP: Generate xcode-build-server config (AIChats)",
      "type": "shell",
      "command": "/opt/homebrew/bin/xcode-build-server",
      "args": [
        "config",
        "-project",
        "${workspaceFolder}/AIChats.xcodeproj",
        "-scheme",
        "AIChats",
        "-configuration",
        "Debug"
      ],
      "options": {
        "cwd": "${workspaceFolder}"
      },
      "problemMatcher": []
    },
    {
      "label": "Xcode: Clean DerivedData (AIChats)",
      "type": "shell",
      "command": "bash",
      "args": [
        "-lc",
        "rm -rf ~/Library/Developer/Xcode/DerivedData/AIChats-*"
      ],
      "problemMatcher": []
    },
    {
      "label": "SwiftPM: Build Debug project-index (ProjectArchitecture/indexer)",
      "type": "shell",
      "command": "bash",
      "args": [
        "-lc",
        "cd ${workspaceFolder}/ProjectArchitecture/indexer && swift build -c debug --target project-index"
      ],
      "problemMatcher": []
    },
    {
      "label": "SwiftPM: Build Release project-index (ProjectArchitecture/indexer)",
      "type": "shell",
      "command": "bash",
      "args": [
        "-lc",
        "cd ${workspaceFolder}/ProjectArchitecture/indexer && swift build -c release --target project-index"
      ],
      "problemMatcher": []
    },
    {
      "label": "SwiftPM: Test (ProjectArchitecture/indexer)",
      "type": "shell",
      "command": "bash",
      "args": [
        "-lc",
        "cd ${workspaceFolder}/ProjectArchitecture/indexer && swift test"
      ],
      "problemMatcher": []
    },

    // 如果你有 Vapor 工程(示例路径,你按真实路径改)
    {
      "label": "Vapor: Run (Server)",
      "type": "shell",
      "command": "bash",
      "args": [
        "-lc",
        "cd ${workspaceFolder}/Server && swift run Run serve --hostname 127.0.0.1 --port 8080"
      ],
      "problemMatcher": [],
      "isBackground": true
    },

    // 一键组合:重建 BSP + 清理 DerivedData(适合你遇到 LSP 索引丢失时)
    {
      "label": "OneKey: Fix LSP (Clean + Regenerate BSP)",
      "dependsOrder": "sequence",
      "dependsOn": [
        "Xcode: Clean DerivedData (AIChats)",
        "BSP: Generate xcode-build-server config (AIChats)"
      ],
      "problemMatcher": []
    },

    // 一键组合:build indexer debug + test
    {
      "label": "OneKey: Build & Test Indexer",
      "dependsOrder": "sequence",
      "dependsOn": [
        "SwiftPM: Build Debug project-index (ProjectArchitecture/indexer)",
        "SwiftPM: Test (ProjectArchitecture/indexer)"
      ],
      "problemMatcher": []
    }
  ]
}

说明:xcode-build-server config 这条会在项目根生成 .bsp/json 配置(取决于版本)。

它不会删除你拉的第三方包:最多影响 DerivedData / 索引缓存,不会动你的 Package 依赖声明。


4) 一键 Debug:

.vscode/launch.json

创建:AIChats/.vscode/launch.json

4.1 SwiftPM indexer(你已经有,我补全并加一个“带参数运行”版本)

{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "swift",
      "request": "launch",
      "name": "Debug project-index (SwiftPM)",
      "cwd": "${workspaceFolder}/ProjectArchitecture/indexer",
      "target": "project-index",
      "configuration": "debug",
      "preLaunchTask": "SwiftPM: Build Debug project-index (ProjectArchitecture/indexer)"
    },
    {
      "type": "swift",
      "request": "launch",
      "name": "Debug project-index (SwiftPM) with args",
      "cwd": "${workspaceFolder}/ProjectArchitecture/indexer",
      "target": "project-index",
      "args": [
        "--input",
        "${workspaceFolder}",
        "--output",
        "${workspaceFolder}/ProjectArchitecture/indexer-output.json"
      ],
      "configuration": "debug",
      "preLaunchTask": "SwiftPM: Build Debug project-index (ProjectArchitecture/indexer)"
    },
    {
      "type": "swift",
      "request": "launch",
      "name": "Release project-index (SwiftPM)",
      "cwd": "${workspaceFolder}/ProjectArchitecture/indexer",
      "target": "project-index",
      "configuration": "release",
      "preLaunchTask": "SwiftPM: Build Release project-index (ProjectArchitecture/indexer)"
    }

    // Vapor 的 Debug Launch(如果你的 Server 是 SwiftPM)
    // 你把 cwd/target 改成你真实 Vapor 包的路径和可执行 target 名
    ,
    {
      "type": "swift",
      "request": "launch",
      "name": "Debug Vapor (SwiftPM)",
      "cwd": "${workspaceFolder}/Server",
      "target": "Run",
      "args": ["serve", "--hostname", "127.0.0.1", "--port", "8080"],
      "configuration": "debug"
    }
  ]
}

Vapor 那条如果你的 target 不是 Run(比如 App),你改一下即可。

如果你 Vapor 项目不在这个 workspace,就先删掉那段。


5) iOS App 一键调试(SweetPad)

SweetPad 的核心是:读取 Xcode scheme,然后在 VSCode 里 build/run/debug

你需要做的是:

  1. 打开 VS Code Command Palette(⇧⌘P)

  2. 搜索 SweetPad: Select Scheme → 选 AIChats

  3. 搜索 SweetPad: Select Destination → 选模拟器/真机

  4. 之后你就可以用:

    • SweetPad: Build

    • SweetPad: Run

    • SweetPad: Debug

建议:把常用命令绑快捷键(可选)

AIChats/.vscode/keybindings.json(可选)

[
  { "key": "cmd+shift+b", "command": "sweetpad.build" },
  { "key": "cmd+shift+r", "command": "sweetpad.run" },
  { "key": "cmd+shift+d", "command": "sweetpad.debug" }
]

你也可以不配快捷键,直接用 SweetPad 的面板按钮。


6) 你关心的两件事(提前帮你踩坑)

6.1 “重生成 BSP 会不会删第三方包?”

不会。

它只会影响:

  • .bsp/xcode-build-server.json(或类似)

  • DerivedData 下的 build_root/索引缓存

  • VSCode / SourceKit-LSP 的索引状态

不会触碰:

  • Package.resolved

  • Xcode 的 Swift Packages 依赖

  • 你 repo 里的三方源码

6.2 “为什么有时 LSP 找不到 Constants.swift?”

本质是 BSP 生成时选错了 project/workspace/scheme/build_root。

你现在的 json 里指向的是:

AIChats.xcodeproj/project.xcworkspace

这没问题,但如果你后续改成 .xcworkspace(比如你用了 workspace 组织),建议 BSP 用 -workspace 来生成更稳。


7) 你现在就可以怎么用(真正“一键”工作流)

A. LSP 索引又抽风了(找不到文件/类型)

跑这个 task:

  • OneKey: Fix LSP (Clean + Regenerate BSP)

然后:

  • Reload Window(VSCode 重载)

  • SourceKit-LSP 会重新索引

B. 调试 indexer

直接点 Run and Debug:

  • Debug project-index (SwiftPM)

C. 调试 iOS App

SweetPad:

  • Debug(自动 attach LLDB)

D. 调试 Vapor

Run and Debug:

  • Debug Vapor (SwiftPM)

    或 task:Vapor: Run (Server)


8) 你把这两处按真实情况改一下就完美

  1. BSP: Generate ... 里 scheme 名

    • 你实际 scheme 如果不是 AIChats,改一下

  2. Vapor 路径 ${workspaceFolder}/Server

    • 你如果没有 Server 目录就删掉相关 task/launch


如果你愿意“更狠一点”(真·一键),我还能给你加一个 Compound 调试

按一次 F5 同时启动 Vapor + indexer + iOS App(iOS 用 SweetPad 需要单独触发,但我们可以用 task 串起来实现“接近一键”)。你把你 Vapor 工程路径和可执行 target 名告诉我(或贴 Package.swift 里 executable target 名),我就把 compound 配好。


评论