73 lines
4.5 KiB
Markdown
73 lines
4.5 KiB
Markdown
# iOS Widget Extension — Xcode Setup
|
||
|
||
Die Swift-Quellen unter `ios/TimetableWidgetExtension/` müssen einmalig in Xcode als **Widget Extension Target** verdrahtet werden — ohne diesen Schritt bleibt der Code unkompiliert.
|
||
|
||
## Schritt 1 — Widget-Extension-Target anlegen
|
||
|
||
1. `ios/Runner.xcworkspace` in Xcode öffnen.
|
||
2. Projekt-Sidebar → `Runner` (Projekt-Root) → **+ Add Target** unten links.
|
||
3. **iOS → Widget Extension** wählen.
|
||
4. Eigenschaften:
|
||
- Product Name: `TimetableWidgetExtension`
|
||
- Bundle Identifier: `eu.mhsl.marianum.mobile.client.TimetableWidgetExtension`
|
||
- Language: Swift
|
||
- Include Configuration Intent: **OFF** (StaticConfiguration reicht)
|
||
- Embed in: Runner
|
||
5. Beim Activate-Scheme-Dialog auf **Cancel** klicken.
|
||
|
||
## Schritt 2 — Vorhandene Quelldateien ins Target ziehen
|
||
|
||
Xcode hat zunächst Dummy-Dateien (`TimetableWidgetExtension.swift`, `TimetableWidgetExtensionBundle.swift`) angelegt. Diese **löschen** (Move to Trash). Dann:
|
||
|
||
1. Sidebar → Rechtsklick auf den Ordner `TimetableWidgetExtension` → **Add Files to "Runner"…**
|
||
2. Im File-Picker zu `ios/TimetableWidgetExtension/` navigieren und alle `.swift`-Dateien, die `Info.plist`, `TimetableWidgetExtension.entitlements` **und den `Assets.xcassets`-Ordner** selektieren (mit `marianum_m`-Asset darin — gleicher Asset-Name wie auf Android-Seite).
|
||
3. **Wichtig**: bei „Add to targets" nur `TimetableWidgetExtension` ankreuzen, **nicht** Runner.
|
||
|
||
## Schritt 3 — App Group aktivieren
|
||
|
||
Beide Targets brauchen die App-Group-Berechtigung, damit Hauptapp und Widget über `UserDefaults(suiteName:)` schreiben/lesen können.
|
||
|
||
1. **Runner**-Target → **Signing & Capabilities** → **+ Capability** → **App Groups**.
|
||
- Group-ID hinzufügen: `group.eu.mhsl.marianum.mobile.client.widget`
|
||
2. Dasselbe für **TimetableWidgetExtension** — mit derselben Group-ID.
|
||
|
||
Im Apple-Developer-Portal muss die App-Group bei beiden App-IDs eingetragen sein, sonst schlägt das Provisioning fehl.
|
||
|
||
## Schritt 4 — Entitlements verlinken
|
||
|
||
1. **Runner** → Build Settings → `CODE_SIGN_ENTITLEMENTS` sollte bereits auf `Runner/Runner.entitlements` zeigen.
|
||
2. **TimetableWidgetExtension** → Build Settings → `CODE_SIGN_ENTITLEMENTS` → auf `TimetableWidgetExtension/TimetableWidgetExtension.entitlements` setzen.
|
||
|
||
## Schritt 5 — Info.plist + Deployment Target
|
||
|
||
1. **TimetableWidgetExtension** → Build Settings → `INFOPLIST_FILE` → auf `TimetableWidgetExtension/Info.plist` setzen.
|
||
2. Build Settings → `IPHONEOS_DEPLOYMENT_TARGET` ≥ 16.0 (Code gated `.containerBackground` mit `if #available(iOS 17, *)`, läuft also auch auf 16).
|
||
|
||
## Schritt 6 — Build & Run
|
||
|
||
- Scheme `Runner` (nicht das Widget-Scheme) wählen → Run.
|
||
- Auf Home-Screen langes Drücken → Widget hinzufügen → "Marianum · Heute" / "Marianum · Woche".
|
||
- Widget-Tap öffnet die App im zuletzt sichtbaren Tab. Eine Tab-Navigation auf den Stundenplan ist bewusst nicht implementiert (Android nutzt Intent-Extras, iOS würde dafür ein URL-Scheme oder AppIntent brauchen — beides bewusst ausgespart).
|
||
|
||
## Troubleshooting
|
||
|
||
- **Widget zeigt „Lade…"** auch nach Refresh: App-Group greift nicht. Prüfen, ob beide Targets dieselbe Group-ID haben und das Provisioning aktualisiert wurde.
|
||
- **Stale-Daten nach Logout**: `WidgetSync.clear()` schreibt `widget_data_logged_in_v1 = false`; Widget zeigt dann den Login-Placeholder.
|
||
- **Lessons um 1–2 Stunden verschoben**: Date-Parser-Bug. Sollte gefixt sein in `WidgetData.swift::parseDartDate` — verifizieren, dass die ISO-8601-Strings ohne Z-Suffix als `TimeZone.current` geparsed werden.
|
||
- **App-Store-Submit später**: `Runner.entitlements` `aps-environment` von `development` auf `production` umbiegen.
|
||
|
||
## Was bereits im Repo erledigt ist
|
||
|
||
- Alle Swift-Quellen, Info.plist, Entitlements liegen unter `ios/TimetableWidgetExtension/`.
|
||
- App-Group-ID konsistent zwischen Dart (`WidgetSync.iosAppGroupId`), Swift (`WidgetDataKey.appGroupId`) und der Entitlements-Datei.
|
||
- `home_widget`-Plugin auf der Dart-Seite konfiguriert; ruft `HomeWidget.setAppGroupId` beim ersten Sync.
|
||
- `containerBackground` für iOS 17+ gegated, fällt auf iOS 16 sauber zurück.
|
||
- Date-Parser fixt das fehlende Z-Suffix (Dart schreibt lokale Zeit ohne TZ-Marker).
|
||
|
||
## Was am Mac noch zu tun ist
|
||
|
||
- Schritte 1–5 oben in Xcode durchklicken (10–15 Min).
|
||
- `flutter pub get` + `cd ios && pod install`.
|
||
- Auf physischem Gerät oder iOS-Simulator (≥ 16.0) bauen.
|
||
- Widget aufs Home-Screen ziehen, prüfen dass Lesson-Zeiten korrekt rendern.
|