SwiftUI @State i .sheet () ios13 vs ios14

Sep 17 2020

Witam Mam tutaj problem i nie mam spójnego zachowania między moim widokiem .sheet () podczas pracy na ios13 lub ios14

Mam taki widok:

@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)
       }
 }

Na iOS 13 działa to zgodnie z oczekiwaniami btn kliknij -> ustaw etykietę -> call sheet -> wyświetl "Etykietę" w widoku tekstowym.

Na ios14 otrzymałem pusty ciąg w self.label, gdy w zamknięciu arkusza, więc nic nie wyświetla.

Czy coś przegapiłem? Czy to błąd iOS 14, czy też źle to zrobiłem na ios13 i to zostało poprawione.

PS: Mam kilka innych zmiennych, które są przekazywane w zamknięciu, uprościłem to.

Odpowiedzi

4 Asperi Sep 18 2020 at 03:15

Twój kod oczekuje kolejności aktualizacji / tworzenia widoku, ale generalnie jest on niezdefiniowany (i prawdopodobnie zmienił się w iOS 14).

Istnieje wyraźny sposób przekazywania informacji w arkuszu - użyj innego kreatora arkusza, tj. .sheet(item:...

Oto działający niezawodny przykład. Testowane z 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)
        }
    }
}
2 Othyn Oct 04 2020 at 21:59

To naprawdę dziwne zachowanie w iOS 14, które nie wydaje się być udokumentowane.

Korzystając z innej odpowiedzi tutaj i komentarza do tego wątku , @Bindingrozwiązałem problem, ponieważ wydawało się to najczystszym i najbardziej SwiftUI-esq rozwiązaniem.

Nie mam pojęcia, dlaczego to zachowanie się zmieniło i wydaje się mniej intuicyjne niż wcześniej, więc zakładam, że to błąd!

Przykład:

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)
    }
}
valexa Nov 19 2020 at 11:06

Zachowanie zmieniło się w SwiftUI 2.0, więc wpływa również na MacOS 11, samo dodanie powiązania do widoku rozwiązuje problem, nawet jeśli to powiązanie nigdy nie jest używane, co sprawia, że ​​myślę, że jest to błąd implementacji. Dodatkowo samo użycie zmiennej stanu szczegółów w Text () w treści widoku również rozwiązuje ten problem.

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 ?? "") }
        }
    }
}