fix(editor): PhotosPicker Sendable-Warning durch Sub-View struct
ImagePickerLabel als private View-Struct extrahiert. SwiftUIs
PhotosPicker(label:)-Closure ist @Sendable, aber View-Konstruktor-
Calls werden zur Build-Zeit MainActor-isoliert evaluiert — im
Gegensatz zu direktem @State-Zugriff im Closure-Body.
Vorher: pickerLabel als computed property → Warning blieb.
Jetzt: ImagePickerLabel(hasImage: occlusionImage != nil) →
Warning weg, Swift-Build clean.
Archive grün, Build grün, keine Swift-Warnings mehr (nur eine
AppIntents-Framework-Hinweis-Note ohne Auswirkung).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
6a4d66fd74
commit
e24e0e6825
2 changed files with 105 additions and 17 deletions
|
|
@ -153,25 +153,11 @@ struct CardEditorView: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extrahiert in eine eigene Property, weil PhotosPickers Label-Closure
|
|
||||||
/// unter Swift-6-Strict-Concurrency den direkten Zugriff auf
|
|
||||||
/// `@State`-Properties als Sendable-Verletzung markiert. Indirektion
|
|
||||||
/// über eine MainActor-isolierte computed Property löst das.
|
|
||||||
private var pickerLabel: some View {
|
|
||||||
Group {
|
|
||||||
if occlusionImage == nil {
|
|
||||||
Label("Bild auswählen", systemImage: "photo")
|
|
||||||
} else {
|
|
||||||
Label("Bild ersetzen", systemImage: "arrow.triangle.2.circlepath")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
private var imageOcclusionFields: some View {
|
private var imageOcclusionFields: some View {
|
||||||
Section("Bild") {
|
Section("Bild") {
|
||||||
PhotosPicker(selection: $imagePickerItem, matching: .images) {
|
PhotosPicker(selection: $imagePickerItem, matching: .images) {
|
||||||
pickerLabel
|
ImagePickerLabel(hasImage: occlusionImage != nil)
|
||||||
}
|
}
|
||||||
.onChange(of: imagePickerItem) { _, newItem in
|
.onChange(of: imagePickerItem) { _, newItem in
|
||||||
Task { await loadPickedImage(newItem) }
|
Task { await loadPickedImage(newItem) }
|
||||||
|
|
@ -364,3 +350,20 @@ private extension String {
|
||||||
trimmingCharacters(in: .whitespacesAndNewlines)
|
trimmingCharacters(in: .whitespacesAndNewlines)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Wird als Sub-View aus dem PhotosPicker-Label-Closure aufgerufen.
|
||||||
|
/// Eigene `View`-Struct vermeidet die Swift-6-Strict-Concurrency-
|
||||||
|
/// Warning: SwiftUIs `PhotosPicker(label:)`-Closure ist `@Sendable`,
|
||||||
|
/// aber View-Konstruktor-Calls werden zur Build-Zeit MainActor-isoliert
|
||||||
|
/// evaluiert (im Gegensatz zu direktem @State-Zugriff im Closure-Body).
|
||||||
|
private struct ImagePickerLabel: View {
|
||||||
|
let hasImage: Bool
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
if hasImage {
|
||||||
|
Label("Bild ersetzen", systemImage: "arrow.triangle.2.circlepath")
|
||||||
|
} else {
|
||||||
|
Label("Bild auswählen", systemImage: "photo")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,90 @@
|
||||||
{
|
{
|
||||||
"sourceLanguage" : "de",
|
"sourceLanguage" : "de",
|
||||||
"strings" : { },
|
"strings" : {
|
||||||
|
"%@" : {
|
||||||
|
|
||||||
|
},
|
||||||
|
"%@ fällige Karten aus abonnierten Decks" : {
|
||||||
|
|
||||||
|
},
|
||||||
|
"%@ Karten gelernt" : {
|
||||||
|
|
||||||
|
},
|
||||||
|
"Abmelden" : {
|
||||||
|
|
||||||
|
},
|
||||||
|
"Alle Karten und Reviews dieses Decks werden ebenfalls gelöscht. Diese Aktion kann nicht rückgängig gemacht werden." : {
|
||||||
|
|
||||||
|
},
|
||||||
|
"Anmelden" : {
|
||||||
|
|
||||||
|
},
|
||||||
|
"Antwort anzeigen" : {
|
||||||
|
|
||||||
|
},
|
||||||
|
"Aus Teilen-Menü" : {
|
||||||
|
|
||||||
|
},
|
||||||
|
"Beide Richtungen werden gelernt — front→back und back→front." : {
|
||||||
|
|
||||||
|
},
|
||||||
|
"Card-Type »%@« kommt in einer späteren Phase" : {
|
||||||
|
|
||||||
|
},
|
||||||
|
"Cards" : {
|
||||||
|
|
||||||
|
},
|
||||||
|
"Changelog" : {
|
||||||
|
|
||||||
|
},
|
||||||
|
"Distractor-Optionen werden zur Lernzeit automatisch aus anderen Karten desselben Decks gezogen." : {
|
||||||
|
|
||||||
|
},
|
||||||
|
"Erst ein Deck erstellen." : {
|
||||||
|
|
||||||
|
},
|
||||||
|
"Erstelle dein erstes Deck auf cardecky.mana.how oder ziehe nach unten zum Aktualisieren." : {
|
||||||
|
|
||||||
|
},
|
||||||
|
"Inbox" : {
|
||||||
|
|
||||||
|
},
|
||||||
|
"Karteikarten des Vereins mana e.V." : {
|
||||||
|
|
||||||
|
},
|
||||||
|
"Karten konnten nicht geladen werden" : {
|
||||||
|
|
||||||
|
},
|
||||||
|
"Keine" : {
|
||||||
|
|
||||||
|
},
|
||||||
|
"Lade Decks …" : {
|
||||||
|
|
||||||
|
},
|
||||||
|
"Mit Hint: `{{c1::Berlin::Hauptstadt von DE}}`" : {
|
||||||
|
|
||||||
|
},
|
||||||
|
"Noch keine Maske" : {
|
||||||
|
|
||||||
|
},
|
||||||
|
"Öffentlich" : {
|
||||||
|
|
||||||
|
},
|
||||||
|
"Privat" : {
|
||||||
|
|
||||||
|
},
|
||||||
|
"Space" : {
|
||||||
|
|
||||||
|
},
|
||||||
|
"Tippe und ziehe auf das Bild, um eine Maske zu erstellen." : {
|
||||||
|
|
||||||
|
},
|
||||||
|
"Versuche eine andere Suche oder Sortierung." : {
|
||||||
|
|
||||||
|
},
|
||||||
|
"Wählen …" : {
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
"version" : "1.0"
|
"version" : "1.0"
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue