7
votes

SwiftUI @State et .sheet () ios13 vs ios14

Bonjour, je rencontre un problème ici et je n'ai pas de comportement cohérent entre ma vue .sheet () lors de l'exécution sur ios13 ou ios14

J'ai une vue comme celle-ci:

@State private var label: String = "" 
@State private var sheetDisplayed = false
///Some code
var body: some View {
   VStack {
      Button(action: {
         self.label = "A label"
         self.isDisplayed = true
      }) {
           Text("test")
       }
   }.sheet(isPresented: $sheetDisplayed, onDismiss: {
        self.label = ""
    }) {
        Text(self.label)
       }
 }

Sur iOS 13, ce travail comme prévu btn cliquez -> définir l'étiquette -> feuille d'appel -> afficher "une étiquette" dans une vue texte.

Sur ios14, j'ai une chaîne vide dans self.label lors de la fermeture de la feuille, donc il n'affiche rien.

Ai-je manqué quelque chose? Est-ce un bogue iOS 14 ou est-ce que je me suis trompé sur ios13 et que cela a été corrigé.

PS: J'ai quelques autres variables qui sont passées dans la fermeture, je l'ai simplifiée.


1 commentaires

Il semble que la feuille a été créée avant que vous ne définissiez l'étiquette. Vous ne devriez pas vous fier à l'ordre dans lequel SwiftUI crée des vues, mais dans ce cas, je pense que c'est un bogue qui vaut la peine d'être soumis à Apple.


3 Réponses :


4
votes

Votre code s'attend à un ordre de mise à jour / création de vue, mais en général, il n'est pas défini (et probablement changé dans iOS 14).

Il existe un moyen explicite de transmettre des informations à l'intérieur de la feuille - utilisez un créateur de feuille différent, c'est-à-dire. .sheet(item:...

Voici un exemple fiable de travail. Testé avec Xcode 12 / iOS 14

struct ContentView: View {
    @State private var item: Item?

    struct Item: Identifiable {
        let id = UUID()
        var label: String = ""
    }

    var body: some View {
        VStack {
            Button(action: {
                self.item = Item(label: "A label")
            }) {
                Text("test")
            }
        }.sheet(item: $item, onDismiss: {
            self.item = nil
        }) {
            Text($0.label)
        }
    }
}


1 commentaires

J'ai pu le faire fonctionner en utilisant votre solution Merci. Mais il est toujours étrange que lors de l'ajout d'observateurs d'accessoires didSet et de l'impression des valeurs (ou lors du débogage), ma valeur change avant d'entrer dans la fermeture du contenu de la feuille et qu'elle ait toujours zéro dans la feuille.



2
votes

C'est un comportement vraiment étrange dans iOS 14, qui ne semble pas être documenté.

En utilisant l' autre réponse ici et le commentaire sur ce fil , j'ai utilisé @Binding pour résoudre le problème car il semblait la solution la plus propre et la plus SwiftUI-esq.

Je n'ai aucune idée de pourquoi ce comportement a changé, et il semble moins intuitif qu'avant, donc je suppose que c'est un bogue!

Un exemple:

struct MainView: View {
    @State private var message = ""
    @State private var showSheet = false

    var body: some View {
        Button(action: {
            self.message = "This will display the correct message"
            self.showSheet = true
        }, label: {
            Text("Test Button")
        })
        .sheet(isPresented: self.$showSheet) {
            SheetView(message: self.$message)
        }
    }
}

struct SheetView: View {
    @Binding var message: Int

    var body: some View {
        Text(self.message)
    }
}


3 commentaires

Merci pour la mise à jour, cela fait quelques jours que je n'ai pas regardé ce fil mais je me souviens avoir essayé cela sans succès (du moins dans mon cas, j'ai trop simplifié mon problème ici) Mais je détiens un optionnel qui était nul dans la fermeture de ma feuille, ce qui a fait planter l'application.


Pouvez-vous s'il vous plaît m'expliquer, pourquoi avez-vous besoin de passer Binding ? Pourquoi ne transmettre qu'une valeur encapsulée ne fonctionne pas? J'ai testé la solution dans mon code et l'ajout de magic $ et le déballage de la valeur plus tard fonctionne simplement ...


Je suppose que parce que la feuille est capable de modifier la valeur qui est liée, elle doit donc être une liaison car une valeur normale / un objet de référence sera perdu dans la vue parent. De plus, il est requis par le constructeur de sheet () (eather a isPresented: Binding <Bool> ou l'élément: Binding <Item?> Voir ici pour référence developer.apple.com/documentation/swiftui/view/...



0
votes

Le comportement a changé avec SwiftUI 2.0, il affecte donc également MacOS 11, le simple fait d'ajouter une liaison à la vue le corrige même lorsque cette liaison n'est jamais utilisée, ce qui me fait penser qu'il s'agit d'un bogue d'implémentation. De plus, le simple fait d'utiliser la variable d'état des détails dans un Text () dans le corps de la vue le corrige également.

struct MyViewController : View {

    @State var details: String?
    @State var showDetails = false

    //    @Binding var havingAbindingFixesIt: String?

    var body: some View {
        VStack {
            //            Text(details ?? "")
            Text("Tap here for details")
                .onTapGesture {
                    self.details = "These are the details"
                    self.showDetails.toggle()
                }
                .sheet(isPresented: $showDetails) { Text(details ?? "") }
        }
    }
}


0 commentaires