Monorepository mit Swift: Code-Organisation für iOS und macOS

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten
```html

Einleitung: Warum ein Monorepo in Swift?



Die Entwicklung für iOS und macOS steht oft vor einem Dilemma: Wie organisiert man Code, sodass er skalierbar, wiederverwendbar und leicht wartbar bleibt? Der traditionelle Ansatz mit vielen einzelnen Repositories (Multi-Repo) führt zu Fragmentierung, doppelten Abhängigkeiten und Schwierigkeiten bei der Koordination von Änderungen. Die Lösung ist ein Monorepo.



Ein Monorepo ist ein einziges Repository, das alle Komponenten eines Projekts enthält: Apps, Bibliotheken, Build-Tools und Konfigurationen. Für das Swift-Ökosystem ist dieser Ansatz besonders relevant dank des Swift Package Manager (SPM), der seit Version 5.3+ lokale Pakete und modulare Architekturen hervorragend unterstützt.



In diesem Artikel werden wir analysieren, wie man ein Monorepo für Swift-Projekte organisiert, die Struktur, Tools (Tuist, XcodeGen) und Best Practices mit Codebeispielen betrachten.



1. Vorteile eines Monorepos für Swift



Bevor wir zur Implementierung übergehen, betrachten wir die wichtigsten Vorteile:



  • Einheitliche Abhängigkeitsversionen — alle Module verwenden dieselbe Version der Bibliotheken, wodurch Konflikte vermieden werden.
  • Atomare Commits — eine API-Änderung in einem Paket wirkt sich sofort auf alle abhängigen Module aus, ohne dass eine Synchronisation zwischen Repositories erforderlich ist.
  • Vereinfachung von CI/CD — eine Pipeline, eine Konfiguration, Caching von Builds.
  • Wiederverwendung von Code — gemeinsame Hilfsprogramme, Modelle, Netzwerkschichten sind für alle Targets (iOS, macOS, watchOS) leicht zugänglich.
  • Code-Review — Änderungen in verschiedenen Teilen des Projekts sind in einem einzigen PR sichtbar.


Es gibt jedoch auch Nachteile: die Größe des Repositories, die Klonzeit, die Notwendigkeit einer durchdachten Struktur. Aber für mittelgroße und größere Teams ist ein Monorepo oft die optimale Wahl.



2. Struktur eines Monorepos in Swift



Betrachten wir eine typische Struktur für ein Projekt, das eine iOS-App und eine macOS-App mit einer gemeinsamen Bibliothek umfasst:



MyProject/├── Apps/│   ├── iOSApp/│   │   ├── Sources/│   │   │   └── AppDelegate.swift│   │   ├── Resources/│   │   └── Package.swift│   └── macOSApp/│       ├── Sources/│       │   └── AppDelegate.swift│       ├── Resources/│       └── Package.swift├── Packages/│   ├── Core/│   │   ├── Sources/│   │   │   ├── Core.swift│   │   │   └── Extensions/│   │   ├── Tests/│   │   └── Package.swift│   ├── Networking/│   │   ├── Sources/│   │   │   └── NetworkManager.swift│   │   ├── Tests/│   │   └── Package.swift│   └── UIComponents/│       ├── Sources/│       │   └── CustomButton.swift│       ├── Tests/│       └── Package.swift├── Tools/│   └── Scripts/│       └── build.sh├── .github/│   └── workflows/│       └── ci.yml├── Package.swift (root)├── Tuist.swift (falls wir Tuist verwenden)└── README.md


Erklärung der Struktur:

  • Apps/ — Verzeichnis mit den endgültigen Anwendungen. Jede App ist ein separates Swift-Paket, das von den Paketen in Packages/ abhängt.
  • Packages/ — alle internen Bibliotheken und Module. Jedes Paket hat sein eigenes Package.swift und kann unabhängig getestet werden.
  • Tools/ — Build-Skripte, Linter, Codegenerierung.
  • Das root Package.swift (oder die Tuist/XcodeGen-Konfiguration) — beschreibt den Workspace und die Verbindungen zwischen den Paketen.


2.1 Beispiel eines root Package.swift (SPM)



// swift-tools-version:5.9import PackageDescription

let package = Package( name: "MyProject", platforms: [ .iOS(.v16), .macOS(.v13) ], products: [ .library(name: "Core", targets: ["Core"]), .library(name: "Networking", targets: ["Networking"]), .library(name: "UICompon ```

Blogs

Buchempfehlungen