Die iOS-Abhängigkeiten lassen sich nach dem Upgrade nicht mehr wie zuvor auflösen, oder der erste Archive-Lauf scheitert an Plugin- und Signaturfehlern.

Die schnellste Lösung: Lassen Sie Flutter 3.47 standardmäßig mit Swift Package Manager arbeiten, behalten Sie inkompatible Plugins zunächst über CocoaPods und wechseln Sie die produktive Build-Kette erst nach einem erfolgreichen Archive- und TestFlight-Test in einer isolierten Mac-Umgebung.

Für wen dieser Leitfaden gedacht ist: Sie aktualisieren ein bestehendes Flutter-Projekt auf 3.47 und möchten eine Unterbrechung der iOS-Veröffentlichung vermeiden. Besonders relevant ist das für Projekte mit mehreren nativen Plugins, unklarer SwiftPM-Kompatibilität oder einem Entwicklungsrechner unter Windows oder Linux, der für Build und Veröffentlichung auf einen Mac angewiesen ist.

Zuletzt aktualisiert am 17.09.2026; die Angaben wurden anhand der Flutter-Release-Dokumentation, der SwiftPM-Migrationsdokumentation und der iOS-Veröffentlichungsdokumentation geprüft.

Die Ausgangslage vor der Migration sichern

Flutter 3.47 iOS-Abhängigkeiten zu migrieren bedeutet nicht, den bisherigen CocoaPods-Aufbau an einem Nachmittag vollständig zu löschen. Seit Flutter 3.44 wird Swift Package Manager standardmäßig für native iOS- und macOS-Abhängigkeiten verwendet. Flutter 3.47 liegt damit in einer Werkzeuglinie, in der die neue Auflösung der normale Startpunkt ist, während nicht kompatible Abhängigkeiten weiterhin auf CocoaPods zurückfallen können. Die offizielle Anleitung für Flutter-Anwendungsentwickler mit SwiftPM beschreibt diesen Übergang.

Die eigentliche Gefahr liegt in der fehlenden Rückfallmöglichkeit. Wenn Sie die einzige Produktionsumgebung direkt verändern, können Sie später nicht mehr sauber unterscheiden, ob ein Fehler durch das Flutter-Upgrade, die Paketauflösung, eine Xcode-Projektänderung, die Signatur oder ein Plugin verursacht wurde.

Sichern Sie deshalb vor der ersten Änderung:

  • die Ausgabe von flutter --version einschließlich des verwendeten Flutter-SDK-Pfads;
  • pubspec.yaml und die zugehörige Lock-Datei;
  • den letzten funktionierenden Xcode-Workspace und die Projektdateien;
  • die aktuelle Podfile-Konfiguration, lokale Pods, private Spezifikationen und eigene Build-Skripte;
  • die verwendete Signaturmethode, ohne private Schlüssel oder Teamdaten in Logs zu kopieren;
  • das Datum und die Artefakte des letzten erfolgreichen Archive- und TestFlight-Laufs.

Der Branch sollte beispielsweise migration/flutter-347-spm heißen. Führen Sie den Versuch mit einem nicht produktiven Ausgabeverzeichnis und einem neutralen Projektpfad wie /Users/BUILDUSER/Projects/AppMigration aus. Ersetzen Sie BUILDUSER und den Projektnamen durch Ihre anonymisierten Werte; Bundle ID, Team ID, Zertifikatsnamen und Protokolle gehören nicht in öffentliche Beispiele.

Warum verändert Flutter 3.47 das iOS-Projekt automatisch?
Weil die Migration nicht nur eine neue Paketquelle einträgt. Flutter kann Abhängigkeiten, Plugin-Registrierung und generierte iOS-Projektbestandteile an die SwiftPM-Auflösung anpassen. Die Änderung ist deshalb ein nachvollziehbares Ergebnis der neuen Standardroute, nicht automatisch ein Defekt. Vergleichen Sie die Änderungen im Versionskontrollsystem und akzeptieren Sie nichts, was Sie nicht einer konkreten Abhängigkeit oder einem Generierungsschritt zuordnen können.

In der ersten Arbeitsstunde die Plugin-Landschaft erfassen

Beginnen Sie nicht mit einem vollständigen Release-Build. Erstellen Sie zuerst eine Kompatibilitätsliste für jedes Plugin, das nativen iOS-Code einbindet. Ein reines Dart-Paket ist für diese Migration anders zu bewerten als ein Plugin mit Objective-C- oder Swift-Dateien, vorkompilierten Frameworks, eigenen Build-Phasen oder manuellen Podfile-Anweisungen.

Prüfen Sie zunächst als festgelegtes Entwicklerkonto im Projektverzeichnis:

cd /Users/BUILDUSER/Projects/AppMigration
/opt/flutter/bin/flutter pub deps --style=compact
/opt/flutter/bin/flutter pub get

Ersetzen Sie /opt/flutter/bin/flutter durch den tatsächlich festgelegten SDK-Pfad. Als erwartbares Ergebnis erhalten Sie eine aufgelöste Abhängigkeitsliste und anschließend eine erfolgreiche Paketaktualisierung. Speichern Sie die Ausgabe im privaten Migrationsprotokoll. Wenn pub get scheitert, ist das noch kein SwiftPM-Fehler; dann müssen Sie zuerst die Dart-Abhängigkeiten stabilisieren.

Suchen Sie anschließend nach nativen Integrationspunkten:

  • ios/Podfile mit manuellen pod-Einträgen;
  • lokalen Pods und privaten Spec-Repositories;
  • Frameworks, XCFrameworks oder binären Bibliotheken;
  • eigenen Run-Script-Phasen im Xcode-Projekt;
  • Plugins, deren Dokumentation nur CocoaPods beschreibt;
  • festen Mindestversionen für iOS oder Swift;
  • Skripten, die Dateien im Pods-Verzeichnis erwarten.

Ordnen Sie jedes Plugin einer von drei Gruppen zu:

  1. SwiftPM bestätigt: Die Plugin-Dokumentation oder die veröffentlichte Paketstruktur weist SwiftPM-Unterstützung aus.
  2. CocoaPods-Rückfall: Das Plugin funktioniert im aktuellen Projekt, bietet aber noch keinen belastbaren SwiftPM-Pfad.
  3. Unklar: Native Dateien, private Quellen oder individuelle Build-Schritte verhindern eine sichere Einstufung.

Die Flutter-Dokumentation zur Plugin-Entwicklung hilft dabei, zwischen Flutter-Plugin-Code und nativen Integrationsbestandteilen zu unterscheiden. Eine einmalige Debug-Kompilierung reicht nicht als Freigabe: Kamera-, Push-, In-App-Kauf-, Login- oder Hintergrundfunktionen können erst in Release, Archive oder auf einem TestFlight-Gerät auffallen.

Was tun, wenn ein Flutter-Plugin Swift Package Manager nicht unterstützt?
Belassen Sie dieses Plugin zunächst in CocoaPods, ersetzen Sie es durch eine nachweislich kompatible Alternative oder verschieben Sie die Migration. Ändern Sie nicht vorschnell den Quellcode eines Drittanbieter-Plugins, nur um eine reine SwiftPM-Konfiguration zu erzwingen. Damit würden Sie die Wartung vom Paketautor auf Ihr Team verlagern und spätere Updates schwer reproduzierbar machen.

Die erste SwiftPM-Auflösung mit kontrollierter Rücknahme durchführen

Nach der Bestandsaufnahme legen Sie eine Kopie des Projekts oder einen separaten Arbeits-Workspace an. Öffnen Sie nicht sofort das einzige produktive Xcode-Projekt. Führen Sie die Befehle immer als festgelegtes Build-Konto aus, nicht einmal interaktiv und einmal als anderer CI-Benutzer.

Ein konservativer Ablauf sieht so aus:

  1. Wechseln Sie in den isolierten Projektordner und wählen Sie den festgelegten Flutter-SDK-Pfad.
  2. Führen Sie flutter clean nur in diesem Arbeits-Workspace aus.
  3. Rufen Sie flutter pub get auf und prüfen Sie die erzeugten beziehungsweise geänderten iOS-Dateien.
  4. Öffnen Sie anschließend den von Flutter vorgesehenen Xcode-Workspace, nicht blind eine alte Projektdatei.
  5. Lassen Sie Xcode die SwiftPM-Pakete auflösen und dokumentieren Sie Paketquelle, Version und Fehlermeldungen.
  6. Starten Sie zunächst einen unsignierten Simulator- oder Basis-Build.
  7. Vergleichen Sie Projektänderungen mit der gesicherten Baseline.

Ein exemplarischer Prüfpunkt lautet:

cd /Users/BUILDUSER/Projects/AppMigration
/opt/flutter/bin/flutter clean
/opt/flutter/bin/flutter pub get
/opt/flutter/bin/flutter build ios --debug --no-codesign

Der erwartete Erfolg ist hier nicht ein veröffentlichbares Paket, sondern ein abgeschlossener Kompilierungslauf ohne Signaturanforderung. Bei einem Fehler sichern Sie die vollständige Ausgabe, notieren Paketname und Build-Phase und setzen den Arbeits-Workspace auf den Migrations-Commit zurück. Entfernen Sie nicht eigenmächtig Lock-Dateien, solange Sie nicht dokumentiert haben, welche Auflösung dadurch verändert wird.

Hinweis: SwiftPM-Caches beschleunigen spätere Läufe, ersetzen aber keine Prüfung in einer sauberen Umgebung. Ein Cache kann einen fehlenden Download, eine nicht reproduzierbare Paketversion oder eine lokale Projektänderung verdecken.

SwiftPM und CocoaPods im Übergang sauber trennen

Kann ein Flutter-Projekt SwiftPM und CocoaPods gleichzeitig verwenden?
Ja, in der Übergangsphase können verschiedene Plugins über unterschiedliche Wege eingebunden werden. Nicht zulässig ist jedoch, dieselbe native Bibliothek doppelt einzubringen. Genau daraus entstehen typische Fehler wie doppelte Symbole, nicht gefundene Module oder widersprüchliche Mindestversionen.

Bewerten Sie Konflikte anhand der sichtbaren Evidenz:

  • Doppelte Symbole: Prüfen Sie zuerst, ob dieselbe Bibliothek als SwiftPM-Paket und Pod eingebunden wird. Entfernen Sie nur die doppelte Quelle, nicht wahllos beide Integrationen.
  • Modul nicht gefunden: Kontrollieren Sie Paketprodukt, Target-Zuordnung und die generierten Plugin-Einträge.
  • Mindestversion kollidiert: Ermitteln Sie, welches Plugin die höhere iOS-Anforderung setzt, und prüfen Sie, ob eine kompatible Version dokumentiert ist.
  • Paket-Download schlägt fehl: Wiederholen Sie die Auflösung in der isolierten Umgebung und speichern Sie die genaue Quelle sowie den Zeitpunkt. Ein späterer Cache-Treffer ist kein Beweis für eine stabile Neuinstallation.
  • Manuelles Podfile-Skript bricht: Kennzeichnen Sie das Skript als Migrationsblocker, statt es ohne Verständnis in Swift zu übertragen.

Die Entscheidung für SwiftPM, Hybridbetrieb oder Rückfall

Verwenden Sie die folgende Checkliste als verbindliches Freigabeinstrument. Ein Punkt gilt erst dann als erledigt, wenn ein konkreter Nachweis im Migrationsprotokoll liegt:

  • [ ] Flutter-SDK-Pfad, Xcode-Version und Ausführungskonto sind im isolierten Workspace festgehalten.
  • [ ] pubspec.yaml, Lock-Datei, Podfile und der letzte funktionierende Release-Zustand sind gesichert.
  • [ ] Jedes Plugin mit nativem iOS-Code ist als SwiftPM-kompatibel, CocoaPods-Rückfall oder unklar eingestuft.
  • [ ] Es gibt keine unbewerteten lokalen Pods, privaten Spezifikationen, Frameworks oder eigenen Run-Script-Phasen.
  • [ ] SwiftPM und CocoaPods binden keine identische native Bibliothek doppelt ein.
  • [ ] Die Paketauflösung funktioniert ohne einen vorausgesetzten lokalen Cache.
  • [ ] Der unsignierte Simulator- oder Basis-Build läuft im isolierten Workspace erfolgreich durch.
  • [ ] Bei einem Fehler existiert ein getesteter Commit, der den vorherigen Abhängigkeitszustand wiederherstellt.
  • [ ] Der signierte Release-Build und das Xcode-Archive werden ohne neue Warnungen mit Veröffentlichungsrelevanz erzeugt.
  • [ ] Der Build wird von App Store Connect verarbeitet und lässt sich über TestFlight auf einem echten Gerät installieren.
  • [ ] Die kritischen nativen Funktionen des Projekts sind im TestFlight-Build geprüft.
  • [ ] Erst nach diesen Nachweisen wurde die produktive Build-Kette für die Umschaltung freigegeben.

Treffen Sie die Entscheidung zusätzlich nach diesen Bedingungen:

  • Wenn alle nativen Plugins dokumentiert SwiftPM unterstützen, wählen Sie SwiftPM als Hauptpfad.
  • Wenn mindestens ein Plugin nur über CocoaPods stabil eingebunden wird, wählen Sie für dieses Plugin den CocoaPods-Rückfall und halten Sie den Grund fest.
  • Wenn dieselbe native Bibliothek über beide Systeme erscheint, stoppen Sie den Build, beseitigen die Doppelung und starten die Basisprüfung erneut.
  • Wenn ein lokales Pod, ein privates Spec-Repository oder ein eigenes Run-Script nicht nachvollziehbar migriert werden kann, lassen Sie diese Abhängigkeit vorerst in CocoaPods.
  • Wenn der unsignierte Build erfolgreich ist, fahren Sie mit Release und Archive fort; ist er erfolglos, bleiben Sie in der Diagnosephase.
  • Wenn Archive erfolgreich ist, aber TestFlight-Verarbeitung oder Geräteprüfung scheitert, wechseln Sie nicht produktiv, sondern stellen Sie den letzten freigegebenen Zustand wieder her.
  • Wenn Archive und TestFlight mit den kritischen nativen Funktionen erfolgreich sind, dürfen Sie die neue Kette für die Produktionsentscheidung vorschlagen.
  • Wenn Sie keinen funktionierenden Rückfall-Commit besitzen, ist die Migration noch nicht für die produktive Build-Maschine freigegeben.

Die Bewertung ergibt also nicht automatisch „alles SwiftPM“. Sie führt zu einem von drei Ergebnissen: vollständige SwiftPM-Umstellung, dokumentierter Hybridbetrieb oder Verschiebung mit aktivem CocoaPods-Pfad.

Flutter beschreibt die Unterstützung und Einschränkungen der Migration in der SwiftPM-Anleitung für App-Entwickler. Für die Entscheidung zählt nicht das Ziel „100 Prozent SwiftPM“, sondern eine eindeutig reproduzierbare Veröffentlichung.

Remote-Mac- und CI-Umgebung reproduzierbar machen

Wenn Sie unter Windows oder Linux entwickeln, sollte der entfernte Mac nicht als einmalige Reparaturstation behandelt werden. Er muss dieselbe feste Werkzeugkette verwenden wie der spätere Build-Auftrag. Fixieren Sie Flutter-SDK-Pfad, Xcode-Auswahl, Arbeitsverzeichnis, Ausführungsbenutzer und Lock-Dateien.

Halten Sie außerdem getrennt:

  • SwiftPM- und CocoaPods-Caches;
  • Signaturzertifikate und private Schlüssel;
  • App-Store-Connect-Zugangsdaten;
  • Build-Artefakte und Diagnoseprotokolle;
  • Remote-Sitzungsinformationen und Wiederanlaufanweisungen.

Legen Sie in der internen Anleitung fest, was nach einer unterbrochenen SSH-, VNC- oder Web-Sitzung passiert: Wird der laufende Prozess geprüft, der Workspace gesperrt, der Build neu gestartet oder zunächst der Status des letzten Artefakts kontrolliert? Diese Regel ist wichtiger als ein vermeintlich schneller Cache-Treffer.

Für Datenschutz und Zugangskontrolle sollten Sie keine privaten Schlüssel in Shell-History, unverschlüsselten Logs oder gemeinsam genutzten Projektordnern speichern. Die Datenschutzhinweise von SSHMac sollten Sie vor dem Einsatz eines fremden oder gemieteten Arbeitsrechners ebenso prüfen wie Ihre eigene Aufbewahrungs- und Löschregel.

Der Vergleich fällt in der Übergangsphase so aus:

  • Lokaler Mac: direkte Diagnose und physische Gerätezugriffe, aber Änderungen können versehentlich die einzige Produktionsumgebung treffen.
  • Isolierter Remote-Mac: sauberer Migrationspfad und getrennte Produktionskette, jedoch müssen Zugang, Sitzungswiederaufnahme und Geheimnisverwaltung dokumentiert sein.
  • Nur CI-Build: gut für reproduzierbare Artefakte, aber ungeeignet, wenn Sie native Projektänderungen oder Plugin-Fehler interaktiv untersuchen müssen.

Als redaktionelle Bewertung für diesen Migrationsfall erhält der isolierte Remote-Mac 5 von 5 Punkten für Trennung, 4 von 5 für Diagnose und 3 von 5 für physische Geräteintegration. Ein lokaler Produktions-Mac erhält 2 von 5 für Trennung, 5 von 5 für Diagnose und 5 von 5 für Gerätezugriff. Die Bewertung ist eine Entscheidungshilfe für diesen Ablauf, keine gemessene Leistungsangabe.

Archive und TestFlight als Freigabeschranke verwenden

Der Release-Test beginnt erst, wenn Paketauflösung und unsignierter Build funktionieren. Folgen Sie danach der offiziellen Flutter-Anleitung für iOS-Builds und Veröffentlichungen, ohne Projekt- oder Signaturdaten in öffentliche Beispiele zu übernehmen.

Arbeiten Sie in dieser Reihenfolge:

  1. Prüfen Sie Versionsnummer und Build-Nummer gegen den letzten veröffentlichten Stand.
  2. Führen Sie einen signierten Release-Build mit dem vorgesehenen Team und Profil aus.
  3. Erzeugen Sie ein Xcode-Archive im isolierten Workspace.
  4. Exportieren Sie die IPA mit der vorgesehenen Methode.
  5. Laden Sie das Artefakt in App Store Connect hoch.
  6. Warten Sie auf die Verarbeitung und prüfen Sie den Build-Status.
  7. Installieren Sie den TestFlight-Build auf einem echten Gerät und testen Sie jede native Funktion, die von einem migrierten Plugin abhängt.

Apple unterscheidet beim Upload mehrere Verarbeitungs- und Build-Zustände; die Übersicht der App-Build-Status ist daher die Referenz für die Auswertung. Ein erfolgreicher Upload allein beweist nicht, dass Push-Mitteilungen, Käufe, Kamera, Hintergrundaufgaben oder Deep Links funktionieren. Die Apple-Dokumentation zum Upload von Builds und der beschriebene App-Store-Connect-Workflow helfen bei der Trennung von Upload, Verarbeitung und Testphase.

Wie rollen Sie nach einer SwiftPM-Migration zurück, wenn Archive scheitert?
Beenden Sie den Wechsel zur Produktionskette, nehmen Sie den letzten funktionierenden Migrations-Commit und stellen Sie den zuvor gesicherten CocoaPods- beziehungsweise Hybridzustand in einer separaten Arbeitskopie wieder her. Prüfen Sie danach erneut Release-Build, Archive und TestFlight. Erst wenn der Rückfall bestätigt ist, analysieren Sie den neuen Fehler anhand der Archive-Logs; ein erneuter Produktionsversuch ohne gesicherte Rückfallebene verlängert nur die Ausfallzeit.

Behalten Sie mindestens einen alten, veröffentlichungsfähigen Abhängigkeitsstand, bis der neue TestFlight-Build installiert und die kritischen nativen Funktionen erfolgreich geprüft wurde. Für diesen Artikel werden keine Bauzeiten, Cache-Ersparnisse oder Stabilitätsquoten behauptet, weil dafür keine verifizierten SSHMac-Messdaten vorliegen.

Die endgültige Umschaltung erst nach der Freigabe beschließen

Nach dem TestFlight-Lauf gibt es drei sachliche Endpunkte:

  • Vollständige SwiftPM-Umstellung: Alle nativen Plugins sind geprüft, keine doppelte Bibliothek bleibt bestehen und Archive sowie TestFlight sind erfolgreich.
  • Dauerhafter Hybridbetrieb: Nur einzelne, dokumentierte Plugins bleiben über CocoaPods eingebunden; die Verantwortlichkeit und der nächste Prüfpunkt sind festgehalten.
  • Aufgeschobene Migration: Ein unklarer Build-Schritt, ein nicht kompatibles Plugin oder ein ungeklärter Archive-Fehler verhindert den Wechsel. Dann bleibt der bisherige Produktionspfad aktiv.

Die Migration sollte nicht allein deshalb abgeschlossen werden, weil Flutter 3.47 SwiftPM als Standardroute verwendet. Auch der offiziell genannte CocoaPods-Zeitpunkt, ab dem die Registrierung am 02.12.2026 schreibgeschützt werden soll, ist kein Grund, eine ungetestete Abhängigkeitskette in Produktion zu nehmen. Die Kompatibilität muss pro Plugin geprüft werden; ein allgemeiner Termin ersetzt keine Projektprüfung.

Wenn Sie aktuell nur einen produktiven Mac besitzen oder überwiegend unter Windows beziehungsweise Linux arbeiten, ist eine getrennte Remote-Mac-Umgebung für diese Übergangsphase oft die kontrolliertere Lösung. Ihre bestehende lokale oder gemietete Umgebung hat dagegen reale Nachteile, wenn sie gleichzeitig Entwicklung, Migration und Veröffentlichung tragen muss: Ein Fehlversuch kann den einzigen Release-Pfad blockieren, lokale Caches erschweren die Fehlersuche und eine unterbrochene Sitzung kann unklare Zwischenzustände hinterlassen. Eine SSHMac-Umgebung kann für die temporäre Migration die produktive Kette getrennt halten, bevor Sie sich für einen dauerhaften Eigenkauf, eine lokale Build-Maschine oder eine langfristige Miete entscheiden. Einen Überblick über die verfügbaren Zugangswege finden Sie auf der SSHMac-Übersichtsseite.

Für ein Projekt mit dauerhaft hoher Build-Last und benötigtem physischem Gerätezugriff ist ein eigener Mac weiterhin die ehrlichere Wahl. Für eine begrenzte Migration, eine zusätzliche Release-Umgebung oder die Absicherung eines Windows- oder Linux-Arbeitsplatzes ist dagegen entscheidend, dass Sie beide Abhängigkeitsketten reproduzierbar testen und erst danach die produktive Route ersetzen.