Wenn mehrere Personen gleichzeitig ein Storyboard oder eine XIB-Datei bearbeiten, kann der XML-Merge erfolgreich aussehen, obwohl die eigentlichen Probleme erst beim vollständigen Archivieren sichtbar werden: Ein verbundenes Objekt wurde gelöscht, eine Oberflächendatei lässt sich nicht kompilieren, das Format lokalisierter strings-Dateien ist beschädigt oder gleichnamige Ausgaben aus zwei Modulen überschreiben einander. Statt auf einem Cloud Mac von ArmVMS zunächst einen vollständigen Build auszuführen und erst danach einen Fehler zu erhalten, empfiehlt sich eine unabhängige Vorprüfung mit dem in Xcode enthaltenen ibtool.
Was ibtool prüfen kann
ibtool ist der Kommandozeilen-Compiler für Interface-Builder-Ressourcen. Das Werkzeug kann .storyboard- und .xib-Dateien separat einlesen und Fehler in der XML-Struktur, Objektverbindungen, bestimmten Eigenschaftskonfigurationen sowie Warnungen während der Kompilierung melden. Für diese Prüfung muss der Anwendungscode in der Regel nicht vorab kompiliert werden. Sie eignet sich daher für Commit-Prüfungen oder eine frühe Stufe der CI-Pipeline.
Einen vollständigen Build kann sie nicht ersetzen. Ob benutzerdefinierte Klassen tatsächlich vorhanden sind, Swift-Typen zusammenpassen, Ressourcen dem richtigen Target angehören und der abschließende Link-Vorgang erfolgreich ist, muss weiterhin mit xcodebuild geprüft werden. Die sinnvolle Reihenfolge lautet daher: zuerst ibtool ausführen und erst nach erfolgreicher Prüfung das Zielprojekt bauen und testen.
Betrachten Sie ibtool als Syntax- und Strukturprüfer für Oberflächenressourcen, nicht als abschließende Abnahme des auslieferbaren Produkts. Sein Nutzen liegt im schnellen Fehlschlagen, nicht in der vollständigen Abdeckung der Build-Semantik.
Prüfen Sie vor dem Start, welches Entwicklerverzeichnis der Auftrag tatsächlich verwendet. So vermeiden Sie, dass die interaktive Sitzung und die Automatisierung unterschiedliche Xcode-Versionen auswählen:
xcode-select -p
xcodebuild -version
xcrun --find ibtool
Sind auf einem Rechner mehrere Xcode-Versionen installiert, sollte die globale Auswahl nicht innerhalb von Aufträgen wiederholt geändert werden. Setzen Sie stattdessen DEVELOPER_DIR explizit für den jeweiligen Auftrag und verwenden Sie für die Vorprüfung und den anschließenden Build denselben Wert.
Storyboards und XIBs stapelweise kompilieren
Das folgende Skript sucht rekursiv nach Oberflächendateien im Projekt und überspringt dabei Abhängigkeiten, Build-Produkte und Cache-Verzeichnisse. Aus dem relativen Pfad wird ein Hash erzeugt. Dadurch kollidieren die Ausgaben auch dann nicht, wenn mehrere Module jeweils eine Datei namens Main.storyboard enthalten.
#!/bin/bash
set -euo pipefail
export LANG=C
export LC_ALL=C
ROOT="${1:-$PWD}"
TMP="$(mktemp -d "${TMPDIR:-/tmp}/ibtool-check.XXXXXX")"
trap 'rm -rf "$TMP"' EXIT
status=0
while IFS= read -r -d '' file; do
rel="${file#"$ROOT"/}"
key="$(printf '%s' "$rel" | shasum -a 256 | cut -c1-12)"
log="$TMP/$key.log"
case "$file" in
*.storyboard) output="$TMP/$key.storyboardc" ;;
*.xib) output="$TMP/$key.nib" ;;
*) continue ;;
esac
printf 'Checking %s
' "$rel"
if ! xcrun ibtool \
--errors \
--warnings \
--notices \
--compile "$output" \
"$file" >"$log" 2>&1; then
cat "$log"
status=1
fi
done < <(
find "$ROOT" \
\( -path '*/Pods/*' \
-o -path '*/Carthage/*' \
-o -path '*/.build/*' \
-o -path '*/DerivedData/*' \) -prune \
-o \( -name '*.storyboard' -o -name '*.xib' \) \
-type f -print0
)
exit "$status"
Die Kombination aus -print0 und read -d '' verarbeitet auch Pfade mit Leerzeichen korrekt. Das temporäre Verzeichnis wird über trap entfernt, sodass keine kompilierten Produkte im Arbeitsverzeichnis zurückbleiben. Fehlerprotokolle werden nur ausgegeben, wenn die jeweilige Datei tatsächlich fehlschlägt. Dadurch werden die CI-Logs nicht von zahlreichen Erfolgsmeldungen überflutet.
Nicht direkt in das Quellverzeichnis kompilieren
Eine .storyboardc-Ausgabe ist tatsächlich ein Verzeichnis, und auch eine .nib-Ausgabe kann mehrere kompilierte Ergebnisse enthalten. Werden diese Ausgaben in der Nähe der Quelldateien abgelegt, können sie den Git-Status, die Ressourcensuche und nachfolgende Paketierungsschritte beeinträchtigen. Sämtliche Produkte der Vorprüfung sollten deshalb in ein auftragsspezifisches temporäres Verzeichnis geschrieben und beim Beenden entfernt werden.
Lokalisierungsressourcen ebenfalls prüfen
Projekte mit Base Localization enthalten üblicherweise ein Basis-Storyboard und separate .strings-Dateien für jede Sprache. Die Oberflächendatei kann sich erfolgreich kompilieren lassen, während eine strings-Datei weiterhin durch Anführungszeichen, Escape-Sequenzen oder Konfliktmarkierungen beschädigt ist. Prüfen Sie das Format zunächst mit plutil:
find "$PWD" -type f \
\( -name '*.strings' -o -name '*.stringsdict' \) \
-not -path '*/Pods/*' \
-print0 |
while IFS= read -r -d '' file; do
plutil -lint "$file"
done
Um die übersetzbaren Schlüssel der Basisoberfläche zu kontrollieren, können Sie eine temporäre Liste erzeugen:
xcrun ibtool \
--generate-strings-file /tmp/Main.generated.strings \
App/Base.lproj/Main.storyboard
plutil -lint /tmp/Main.generated.strings
Die generierte Datei sollte nicht direkt zum Überschreiben manuell gepflegter Übersetzungen verwendet werden. Reihenfolge und Kommentare der Ausgabe können sich zwischen Xcode-Versionen ändern. Zuverlässiger ist es, die Schlüsselmenge auszuwerten und zu prüfen, ob neue Schlüssel in den Übersetzungsprozess aufgenommen wurden und veraltete Schlüssel noch unnötig vorhanden sind.
Diagnosen in ein wartbares CI-Gate überführen
Schlägt die Vorprüfung fehl, sollte die aktuelle Stufe sofort beendet werden. Warnungen müssen dagegen nach Schweregrad behandelt werden. Hinweise zur Layout-Kompatibilität, fehlende Barrierefreiheitsbeschriftungen und Warnungen zu veralteten Eigenschaften sollten erfasst werden. Neue Diagnosen einer anderen Xcode-Version dürfen jedoch nicht ohne vorherige Bewertung plötzlich sämtliche Branches blockieren.
| Symptom | Häufige Ursache | Vorgehensweise |
|---|---|---|
| XML-Parsing schlägt fehl | Merge-Konfliktmarkierungen oder abgeschnittene Datei | Zum konfliktverursachenden Commit zurückkehren und den Fehler beheben; unbekannte Knoten nicht manuell löschen |
| Ausgabe wird überschrieben | Mehrere Module enthalten gleichnamige Oberflächendateien | Den Ausgabenamen aus einem Hash des relativen Pfads erzeugen |
| Lokalisierungsdatei kann nicht geparst werden | Fehler bei Anführungszeichen, Semikolons oder Escape-Sequenzen | plutil -lint für alle strings- und stringsdict-Dateien ausführen |
| Lokal erfolgreich, in CI fehlgeschlagen | Xcode oder DEVELOPER_DIR stimmen nicht überein |
Versionen im Log festhalten und die Auftragsumgebung vereinheitlichen |
| Anzahl der Warnungen schwankt ständig | Geänderte Werkzeugversion oder instabiler Prüfbereich | Ausgeschlossene Verzeichnisse fest vorgeben und neue Warnungen per Differenzprüfung kontrollieren |
Bei kleinen Änderungen kann die Prüfung auf die in der aktuellen Branch geänderten Oberflächendateien beschränkt werden. Für die Haupt-Branch oder zeitgesteuerte Aufträge sollte dagegen das gesamte Repository untersucht werden. Inkrementelle Prüfungen liefern schnelleres Feedback, während vollständige Prüfungen Auslassungen durch Umbenennungen, Löschungen und modulübergreifende Änderungen erkennen. Beide Verfahren ergänzen einander und sollten sich nicht gegenseitig ersetzen.
Abschließende Abnahme mit einem vollständigen Build
Nach erfolgreicher ibtool-Prüfung sollte mindestens ein Simulator-Build ohne Signierungsabhängigkeit ausgeführt werden. Damit wird überprüft, ob Oberflächenressourcen, Code, Target-Zugehörigkeiten und weitere Ressourcen gemeinsam funktionieren:
: "${WORKSPACE:?Set WORKSPACE to the workspace path}"
: "${SCHEME:?Set SCHEME to the shared scheme}"
xcodebuild \
-workspace "$WORKSPACE" \
-scheme "$SCHEME" \
-destination 'generic/platform=iOS Simulator' \
CODE_SIGNING_ALLOWED=NO \
build
Das abschließende Gate sollte sicherstellen, dass Vorprüfung und vollständiger Build dieselbe Xcode-Version verwenden, die vom Skript ausgeschlossenen Verzeichnisse mit den Abhängigkeitsverzeichnissen des Projekts übereinstimmen, temporäre Produkte nicht in das Repository gelangen und Fehlerprotokolle die ursprünglichen relativen Pfade enthalten. Auf diese Weise werden Probleme mit Oberflächenressourcen bereits innerhalb weniger Sekunden sichtbar. Fehler, die den vollständigen Projektkontext benötigen, gelangen anschließend in den kompletten Build, wodurch auch die Grenzen der Fehlersuche klarer bleiben.
Häufig gestellte Fragen
Kann die ibtool-Prüfung einen vollständigen Xcode-Build ersetzen?
Nein. ibtool prüft die Oberflächendateien isoliert. Typen im Quellcode, Build-Einstellungen, Verknüpfung und das endgültige Bundle müssen weiterhin mit xcodebuild geprüft werden.
Warum sollte der Ausgabepfad nicht nur aus dem Dateinamen bestehen?
Mehrere Module können gleichnamige Main.storyboard- oder View.xib-Dateien enthalten. Ein Hash des relativen Pfads verhindert, dass sich Ergebnisse gegenseitig überschreiben.
Soll jede ibtool-Warnung den CI-Lauf abbrechen?
Sinnvoller ist eine geprüfte Ausgangsbasis, gegen die nur neue Warnungen verglichen werden. Xcode-Aktualisierungen können bestehende Diagnosetexte verändern.
Wählen Sie für Ihren nächsten Build einen exklusiven physischen Apple-Silicon-Knoten
Mieten Sie ArmVMS M4 und ArmVMS M4 Pro tage-, wochen-, monats- oder quartalsweise. Konfiguration, Knoten und Zusatzoptionen werden vor der Bestellung einzeln bestätigt.