使用 Xcode 进行服务端开发
Use Xcode for server-side development
2022年6月6日
一句话判断
苹果终于正式拥抱了 Server-side Swift——用 Xcode 同时开发客户端和服务端,共享数据模型,Food Truck 示例项目就是这套工作流的最佳示范。
这场 Session 讲了什么
苹果在 WWDC 2022 上正式展示了如何用 Xcode 进行服务端 Swift 开发。这不是一个全新的概念——Vapor 和 Kitura 等框架已经存在多年——但苹果这次提供了官方的工作流指导和一个完整的示例项目 Food Truck。
Session 的核心思路是:用一个 Xcode Workspace 同时管理客户端(iOS App)和服务端(Swift 后端)两个 target。共享的数据模型放在一个独立的 Swift Package 里,两端都依赖它。这样你修改一个数据结构,客户端和服务端会同时更新,再也不用手动同步 API 定义。
Food Truck 示例展示了完整的开发流程:Vapor 框架搭建的 REST API 服务端、SwiftUI 构建的 iOS 客户端、共享的 FoodTruckModel 数据模型。你可以在 Xcode 中直接调试服务端代码,设置断点、查看变量,和调试客户端完全一样。
值得深挖的点
共享数据模型的工程价值。 在传统的客户端+服务端开发中,API 接口的同步是一个持续的痛点。Swift 的 Package 系统提供了一个优雅的解决方案:把 DTO(Data Transfer Object)和 API 路由定义放在一个共享的 Package 里。客户端和服务端都依赖这个 Package,编译器会帮你确保两端的类型定义一致。这比 OpenAPI/Swagger 生成代码的方式更轻量,也更符合 Swift 的类型系统。
Xcode 作为全栈 IDE 的可能性。 Session 展示了 Xcode 同时运行 iOS 模拟器和本地服务器的能力。你在客户端发起的网络请求可以直接在同一个 Xcode 实例中调试服务端的处理逻辑——包括断点、变量检查、甚至 Instruments 性能分析。这种体验对于习惯了切换 IDE 的全栈开发者来说是巨大的效率提升。
代码片段
// 共享的数据模型 Package
// Package.swift
// Targets: FoodTruckModel (shared), FoodTruckClient, FoodTruckServer
// 共享的数据模型
public struct Donut: Codable, Identifiable {
public let id: UUID
public var name: String
public var flavor: String
public var price: Double
public init(name: String, flavor: String, price: Double) {
self.id = UUID()
self.name = name
self.flavor = flavor
self.price = price
}
}
// 服务端路由(Vapor)
import Vapor
import FoodTruckModel
func routes(_ app: Application) throws {
app.get("donuts") { req async throws -> [Donut] in
// 直接返回共享的 Donut 类型
try await DonutController().getAll()
}
app.post("donuts") { req async throws -> Donut in
let newDonut = try req.content.decode(Donut.self)
return try await DonutController().create(newDonut)
}
}
// 客户端直接使用相同的 Donut 类型
import FoodTruckModel
class DonutService {
func fetchDonuts() async throws -> [Donut] {
let (data, _) = try await URLSession.shared.data(from: donutsURL)
return try JSONDecoder().decode([Donut].self, from: data)
}
}
最佳实践
- 使用 Swift Package 来组织共享代码,不要把模型文件复制粘贴到两个 target 里。
- 在 Xcode Scheme 中设置好服务端的启动参数和端口号,确保客户端的 API 地址和本地服务端一致。
- 用
async/await统一客户端和服务端的异步代码风格,减少心智负担。 - 服务端的错误类型也放到共享 Package 里,这样客户端可以直接处理服务端的错误码。
还有什么值得关注
- 苹果虽然没有推出自己的服务端框架,但明确推荐了 Vapor 作为首选方案。
- Food Truck 示例项目的代码在苹果的示例代码库中可以找到,值得下载学习。
- 服务端的 Swift 代码也可以用 Instruments 做性能分析——包括内存泄漏、CPU 占用等。
- 如果你做的是内部工具或原型开发,这种”一个 Xcode 搞定前后端”的方式效率极高。但对于大型生产级服务端,你仍然需要考虑容器化部署、日志系统、监控等运维问题。