SwiftUI:シートを閉じて、ContentViewから別のシートを起動するにはどうすればよいですか?

Aug 22 2020

私のアプリには、アプリの機能を紹介し、ユーザーが最初のアイテムを作成できるようにするウェルカム画面があります。ユーザーがボタンをクリックしたら、「welcomeScreen」シートを閉じてから「newRemindr」シートを起動します。

'addNewTrigger'ブール値をfalseに設定して、監視可能なオブジェクトを作成することで、これを実現しようとしました。welcomeScreenのAddNew Reminderボタンをクリックすると、ボタンのアクションによりwelcomeScreenが閉じられ、「addNewTrigger」ブール値がTrueに切り替わります。(これがPrintStatementsで機能していることを確認しました)。ただし、コンテンツビューは、同じ監視対象オブジェクトをリッスンして「newRemindr」シートを起動していますが、そのアクションは機能していないようです。

誰かがコードを見て、どこが間違っているのか見てください。または、機能のタイプを提供できる代替案を提案します。

私は本当にすべての助けに感謝します。ありがとう!

以下のコード...

welcomeScreen:

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

ContentView:

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

回答

1 Asperi Aug 22 2020 at 10:42

最初に私が見ているのは、両方のビューで異なる監視可能なオブジェクトを使用していることですが、同じものを使用する必要があるため、1つのビューで行われた変更を2番目のビューでも使用できます。

ここのSeはこれを解決する方法です

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

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

// ... other code

とで ContentView

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

代替:ウェルカムシートの却下をアクティブにすることによってのみ、削除addNewReminderして操作できます。welcomeScreenContentView

}  .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()
}