Engineering-Praxis

Storyboards und XIBs auf einem Cloud Mac mit ibtool vorprüfen

Storyboards und XIBs auf einem Cloud Mac mit ibtool vorprüfen

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.

ArmVMS Cloud-Mac

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.

Konfiguration auswählen und Bestellung erstellen