Demo-Modus auch in Release-/TestFlight-Builds verfügbar machen

Der Einstellungen-Schalter für den Demo-Modus war in #if DEBUG
eingeschlossen und damit in Archiven (Release-Konfiguration, wie sie
Product → Archive und damit jeder TestFlight-Build verwendet) komplett
herauskompiliert. TestFlight-Tester konnten den Demo-Modus dadurch nicht
nutzen.

DemoData.isEnabled und der Schalter in SettingsView sind jetzt
konfigurationsunabhängig; nur die CAMPER_DEMO-Umgebungsvariable bleibt
auf Debug-Builds beschränkt, da sie ohnehin nur über Xcode/simctl
gesetzt werden kann.

Build (Debug + Release) und Tests grün; per strings(1) im
Release-Binary verifiziert, dass der Demo-Modus-Code tatsächlich
mitkompiliert wird.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
fototeddy
2026-09-06 22:33:11 +02:00
co-authored by Claude Sonnet 5
parent 8e5ee6927e
commit 35f4e6fbcb
4 changed files with 27 additions and 33 deletions
+10 -8
View File
@@ -430,16 +430,18 @@ eingerichtet wurden, wandern beim Update automatisch ins erste Profil.
## Ohne Fahrzeug ansehen
Ein Demo-Modus füllt die App mit erfundenen Fahrzeugen und Messwerten, damit
sich die Ansichten ohne Bluetooth prüfen lassen. Nur in Debug-Builds, auf zwei
Wegen einzuschalten:
sich die Ansichten ohne Bluetooth prüfen lassen auch ohne die Hardware zur
Hand zu haben. Auf zwei Wegen einzuschalten:
* **Schalter in den Einstellungen** (*Einstellungen → Entwicklung →
Demo-Modus*) der Weg für einen lokal installierten Build ohne
Xcode-Verbindung, etwa auf dem eigenen iPhone. Wirkt erst nach einem
Neustart der App (im App-Umschalter nach oben wischen, dann neu öffnen),
weil `DeviceStore` und `BluetoothManager` den Stand nur beim Start lesen.
* **Umgebungsvariable** `CAMPER_DEMO=1` in Xcode unter *Product → Scheme →
Edit Scheme → Run → Arguments*, oder im Simulator direkt:
Demo-Modus*) in jeder Build-Konfiguration verfügbar, auch in TestFlight-
und App-Store-Builds. Der Weg für jeden lokal installierten Build ohne
Xcode-Verbindung. Wirkt erst nach einem Neustart der App (im
App-Umschalter nach oben wischen, dann neu öffnen), weil `DeviceStore` und
`BluetoothManager` den Stand nur beim Start lesen.
* **Umgebungsvariable** `CAMPER_DEMO=1` nur in Debug-Builds, in Xcode unter
*Product → Scheme → Edit Scheme → Run → Arguments*, oder im Simulator
direkt:
```bash
xcrun simctl launch --terminate-running-process booted <deine-bundle-id>
+8 -8
View File
@@ -516,7 +516,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0;
MARKETING_VERSION = 0.1;
PRODUCT_BUNDLE_IDENTIFIER = de.s0.fototeddy.VanControl;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
@@ -548,7 +548,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0;
MARKETING_VERSION = 0.1;
PRODUCT_BUNDLE_IDENTIFIER = de.s0.fototeddy.VanControl;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
@@ -574,7 +574,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0;
MARKETING_VERSION = "0,1";
PRODUCT_BUNDLE_IDENTIFIER = de.s0.fototeddy.VanControl.watchkitapp;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = watchos;
@@ -606,7 +606,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0;
MARKETING_VERSION = "0,1";
PRODUCT_BUNDLE_IDENTIFIER = de.s0.fototeddy.VanControl.watchkitapp;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = watchos;
@@ -635,7 +635,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.0;
MARKETING_VERSION = 0.1;
PRODUCT_BUNDLE_IDENTIFIER = de.s0.fototeddy.VanControl.watchkitapp.levelwidget;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = watchos;
@@ -664,7 +664,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.0;
MARKETING_VERSION = 0.1;
PRODUCT_BUNDLE_IDENTIFIER = de.s0.fototeddy.VanControl.watchkitapp.levelwidget;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = watchos;
@@ -696,7 +696,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.0;
MARKETING_VERSION = 0.1;
PRODUCT_BUNDLE_IDENTIFIER = de.s0.fototeddy.VanControl.VanControlLiveActivity;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
@@ -725,7 +725,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.0;
MARKETING_VERSION = 0.1;
PRODUCT_BUNDLE_IDENTIFIER = de.s0.fototeddy.VanControl.VanControlLiveActivity;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
+9 -13
View File
@@ -3,21 +3,19 @@ import Foundation
/// Füllt die App mit erfundenen Messwerten, damit sich die Ansichten ohne
/// Fahrzeug und ohne Bluetooth prüfen lassen.
///
/// Nur in Debug-Builds, auf zwei Wegen einzuschalten:
/// Auf zwei Wegen einzuschalten:
///
/// * Umgebungsvariable `CAMPER_DEMO=1` beim Start praktisch im Simulator:
/// * Schalter in den Einstellungen (`SettingsView`) in jeder
/// Build-Konfiguration verfügbar, auch in TestFlight- und
/// App-Store-Builds. Der Weg für jeden lokal installierten Build ohne
/// Xcode-Verbindung. Wirkt erst nach einem Neustart der App, weil
/// `DeviceStore` und `BluetoothManager` den Stand nur beim Start lesen.
/// * Umgebungsvariable `CAMPER_DEMO=1` beim Start nur in Debug-Builds,
/// praktisch im Simulator:
///
/// xcrun simctl launch --terminate-running-process \
/// booted de.fritob.VanControl
/// # mit: SIMCTL_CHILD_CAMPER_DEMO=1 davor
///
/// * Schalter in den Einstellungen (`SettingsView`) der einzige Weg auf
/// einem lokal installierten Build ohne Xcode-Verbindung, da sich dort
/// keine Umgebungsvariable setzen lässt. Wirkt erst nach einem Neustart der
/// App, weil `DeviceStore` und `BluetoothManager` den Stand nur beim Start
/// lesen.
///
/// Im normalen Betrieb wird hiervon nichts ausgeführt.
enum DemoData {
/// Schlüssel für den Einstellungen-Schalter, siehe `SettingsView`.
@@ -26,10 +24,8 @@ enum DemoData {
static var isEnabled: Bool {
#if DEBUG
if ProcessInfo.processInfo.environment["CAMPER_DEMO"] == "1" { return true }
return UserDefaults.standard.bool(forKey: enabledKey)
#else
return false
#endif
return UserDefaults.standard.bool(forKey: enabledKey)
}
static let mainProfile = Profile(id: Profile.defaultID, name: "Kastenwagen",
-4
View File
@@ -4,16 +4,13 @@ import SwiftUI
/// betrifft, steht bei diesem Gerät.
struct SettingsView: View {
@AppStorage(AppSettings.showDiagnosticsKey) private var showDiagnostics = false
#if DEBUG
@AppStorage(DemoData.enabledKey) private var demoModeEnabled = false
#endif
@Environment(PhoneWatchLink.self) private var watch
@Environment(\.dismiss) private var dismiss
var body: some View {
NavigationStack {
List {
#if DEBUG
Section {
Toggle("Demo-Modus", isOn: $demoModeEnabled)
} header: {
@@ -24,7 +21,6 @@ struct SettingsView: View {
+ "einem Neustart der App einmal beenden (im App-Umschalter "
+ "nach oben wischen) und wieder öffnen.")
}
#endif
Section {
Toggle("Diagnose anzeigen", isOn: $showDiagnostics)