使用Swift的单一代码库:iOS和macOS项目的代码组织

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

使用 Swift 的 Monorepo:为 iOS 和 macOS 项目组织代码



在现代 iOS 和 macOS 开发中,代码管理策略的选择直接影响开发速度、重构质量和团队协作的便利性。传统的多仓库方法(polyrepo)常常导致依赖重复、版本同步困难以及代码库碎片化。替代方案是 monorepo——一个为项目的所有模块、库和应用程序提供的统一存储库。在本文中,我们将以 Swift 和 Apple 生态系统为例,探讨如何组织 monorepo、使用哪些工具以及需要注意哪些陷阱。



什么是 Monorepo,为什么 Swift 项目需要它



Monorepo 是一种版本管理策略,其中项目的所有代码(多个应用程序、库、配置)都存储在一个 Git 仓库中。在 Swift 的上下文中,这意味着您可以在一个仓库中拥有:



  • iOS 应用程序(例如,MyApp)
  • macOS 应用程序(MyMacApp)
  • 通用模型库(CoreModels)
  • 网络层(Networking)
  • UI 组件(UIComponents)
  • 测试和 CI 脚本


Monorepo 对 Swift 项目的优势:

  • 统一的依赖版本——所有模块使用相同版本的库(例如,Alamofire 或 SwiftUI),从而消除冲突。
  • 原子提交——对库 API 的更改及其在应用程序中的使用通过一次提交完成,从而简化代码审查和回滚。
  • 简化重构——您可以重命名模块中的公共方法,并立即在同一仓库中修复所有调用位置。
  • 共享 CI/CD——用于构建和测试所有组件的单一流水线。


在 Swift 中使用 Monorepo 的工具



在 Apple 生态系统中,有两个主要工具用于组织 monorepo:Swift Package Manager (SPM) 和 Tuist。让我们看看它们的特点。



Swift Package Manager (SPM)

SPM 是一个内置的包管理器,非常适合 monorepo。您通过 Package.swift 定义模块,Xcode 会自动解析依赖关系。结构示例:



MyMonorepo/├── Package.swift├── Sources/│   ├── CoreModels/│   │   └── Models.swift│   ├── Networking/│   │   └── APIClient.swift│   └── UIComponents/│       └── ButtonView.swift├── Apps/│   ├── MyApp/│   │   └── (iOS проект)│   └── MyMacApp/│       └── (macOS проект)└── Tests/    ├── CoreModelsTests/    └── NetworkingTests/


此类 monorepo 的 Package.swift 示例:



// swift-tools-version:5.9import PackageDescription

let package = Package( name: "MyMonorepo", platforms: [ .iOS(.v16), .macOS(.v13) ], products: [ .library(name: "CoreModels", targets: ["CoreModels"]), .library(name: "Networking", targets: ["Networking"]), .library(name: "UIComponents", targets: ["UIComponents"]), ], dependencies: [ .package(url: "https://github.com/Alamofire/Alamofire.git", from: "5.8.0") ], targets: [ .target(name: "CoreModels"), .target( name: "Networking", dependencies: ["CoreModels", "Alamofire"] ), .target( name: "UIComponents", dependencies: ["CoreModels"] ), .testTarget(name: "CoreModelsTests", dependencies: ["CoreModels"]), .testTarget(name: "NetworkingTests", dependencies: ["Networking"]), ])

博客

书籍推荐