SwiftUI: come si chiude un foglio e si avvia un foglio diverso da ContentView?

Aug 22 2020

Per la mia app, ho una schermata di benvenuto che introduce ciò che fa l'app e consente all'utente di creare il suo primo elemento. Quando l'utente fa clic sul pulsante, vorrei chiudere il foglio "welcomeScreen" e quindi avviare il foglio "newRemindr".

Ho provato a raggiungere questo obiettivo creando un oggetto osservabile con un valore booleano 'addNewTrigger' impostato su false. Quando faccio clic sul pulsante Aggiungi nuovo promemoria sulla schermata di benvenuto, l'azione del pulsante provoca la chiusura della schermata di benvenuto e attiva il valore booleano "addNewTrigger" su True. (Ho verificato che funzioni con Print Statements). Tuttavia, la visualizzazione del contenuto sta ascoltando lo stesso oggetto osservato per avviare il foglio "newRemindr" ma tale azione non sembra funzionare.

Qualcuno può dare un'occhiata al codice e vedere dove sbaglio? Oppure suggerire un'alternativa in grado di fornire il tipo di funzionalità.

Apprezzo davvero tutto l'aiuto. Grazie!

Codice sotto...

Schermata di benvenuto:

import SwiftUI
import Combine

struct welcomeScreen: View {
@Environment(\.presentationMode) var mode: Binding<PresentationMode>

@ObservedObject var addNewReminder = showAddScreen()

var body: some View {
    NavigationView {
        ZStack (alignment: .center) {

            LinearGradient(gradient: Gradient(colors: [Color.white, Color.white, Color.gray]), startPoint: .top, endPoint: .bottom)
                .edgesIgnoringSafeArea(.all)

            Image("Ellipse2")
                .offset(y: -475)

            VStack {
                Spacer()
                Text("Welcome to")
                    .foregroundColor(.white)
                    .fontWeight(.bold)
                Image("RemindrLogoWhite")
                Spacer()
                Text("What is remindr?")
                    .font(.title)
                    .fontWeight(.bold)
                    .padding(.bottom, 25)
                Text("Remindr is a simple app designed to help you schedule random reminders with the goal of clearing your mind.\n\nRemind yourself to check in with your body, set up positive affirmations, set your intentions; Whatever it is, the power is up to you.")
                    .padding(.horizontal, 25)
                    .padding(.bottom, 25)
                Text("Click below to get started:")
                    .fontWeight(.bold)

                // Add New Reminder Button
                Button(action: {
                    self.mode.wrappedValue.dismiss()
                    print("Add Reminder Button from Welcome Screen is Tapped")
                    self.addNewReminder.addNewTrigger.toggle()
                    print("var addNewTrigger has been changed to \(self.addNewReminder.addNewTrigger)")
                }) {
                    Image("addButton")
                        .renderingMode(.original)
                }.padding(.bottom, 25)

                Spacer()

            } .frame(maxWidth: UIScreen.main.bounds.width,
                     maxHeight: UIScreen.main.bounds.height)
        }
        .navigationBarTitle(Text(""), displayMode: .automatic)
        .navigationBarItems(trailing: Button(action: {
            self.mode.wrappedValue.dismiss()

        }, label: {
            Image(systemName: "xmark")
                .foregroundColor(.white)
        }))
    }
  }
}

Visualizzazione contenuto:

import SwiftUI
import CoreData

class showAddScreen: ObservableObject {
@Published var addNewTrigger = false
}

struct ContentView: View {


@Environment(\.managedObjectContext) var moc
@FetchRequest(entity: ReminderEntity.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \ReminderEntity.dateCreated, ascending: false)])
var reminder: FetchedResults<ReminderEntity>

// Sheet Control
@ObservedObject var addNewReminder = showAddScreen()
//@State private var showingAddScreen = false
@State var showWelcomeScreen = false
    
let emojiList = EmojiList()

//Toggle Control
@State var notifyOn = true

// Save Items Function
func saveItems() {
    do {
        try moc.save()
    } catch {
        print(error)
    }
}

// Delete Item Function
func deleteItem(indexSet: IndexSet) {
    let source = indexSet.first!
    let listItem = reminder[source]
    moc.delete(listItem)
}

// View Controller
var body: some View {
    VStack {
        NavigationView {
            ZStack (alignment: .top) {
                
                // List View
                List {
                    ForEach(reminder, id: \.self) { notification in
                        NavigationLink(destination: editRemindr(reminder: notification,
                                                                notifyOn: notification.notifyOn,
                                                                emojiChoice: Int(notification.emojiChoice),
                                                                notification: notification.notification ?? "unknown",
                                                                notes: notification.notes ?? "unknown")) {
                            // Text within List View
                            HStack {
                                // MARK: TODO
                                //Toggle("NotifyOn", isOn: self.$notifyOn)
                                //    .labelsHidden() // Hides the label/title
                                Text("\(self.emojiList.emojis[Int(notification.emojiChoice)]) \(notification.notification!)")
                            } 
                        }
                    } 
                    .onDelete(perform: deleteItem)
                    }.lineLimit(1)
                    
                    // Navigation Items
                    .navigationBarTitle("", displayMode: .inline)
                    .navigationBarItems(
                        leading:
                        HStack {
                            
                            Button(action: {
                                self.showWelcomeScreen.toggle()
                            }) {
                                Image(systemName: "info.circle.fill")
                                    .font(.system(size: 24, weight: .regular))
                            }.foregroundColor(.gray)
                            
                            // Positioning Remindr Logo on Navigation
                            Image("remindrLogoSmall")
                                .resizable()
                                .aspectRatio(contentMode: .fit)
                                //.frame(width: 60, height: 60, alignment: .center)
                                .padding(.leading, 83)
                                .padding(.top, -10)
                        },
                        
                        // Global Settings Navigation Item
                        trailing: NavigationLink(destination: globalSettings()){
                            Image("settings")
                                .font(Font.title.weight(.ultraLight))
                        }.foregroundColor(.gray)
                )
                
                // Add New Reminder Button
                VStack {
                    Spacer()
                    Button(action: { self.addNewReminder.addNewTrigger.toggle()
                    }) {
                        Image("addButton")
                            .renderingMode(.original)
                    }
                    .sheet(isPresented: $addNewReminder.addNewTrigger) {
                        
                        newRemindr().environment(\.managedObjectContext, self.moc)
                        
                    }
                }
            }
        }  .sheet(isPresented: $showWelcomeScreen) {
            welcomeScreen()
        }
    }
}
}

Risposte

1 Asperi Aug 22 2020 at 10:42

Innanzitutto quello che vedo è che usi diversi oggetti osservabili in entrambe le viste, ma dovresti usare lo stesso, quindi le modifiche apportate in una vista saranno disponibili anche per la seconda vista.

Ecco un modo per risolvere questo problema

struct welcomeScreen: View {
@Environment(\.presentationMode) var mode: Binding<PresentationMode>

@ObservedObject var addNewReminder: showAddScreen // << declare to be injected

// ... other code

e dentroContentView

}  .sheet(isPresented: $showWelcomeScreen) {
    welcomeScreen(addNewReminder: self.addNewReminder)    // << inject !!
}

Alternativo: puoi rimuovere addNewReminderda welcomeScreene lavorare con esso solo in ContentViewattivando sul foglio di benvenuto dismiss, come

}  .sheet(isPresented: $showWelcomeScreen, onDismiss: {
              // it is better to show second sheet with delay to give chance
              // for first one to animate closing to the end
              DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
                 self.addNewReminder.addNewTrigger.toggle()
              }
          }
   ) {
    welcomeScreen()
}