【问题标题】:SwiftUI: How do you dismiss a sheet and launch a different sheet from ContentView?SwiftUI:您如何关闭工作表并从 ContentView 启动不同的工作表?
【发布时间】:2020-08-21 22:28:50
【问题描述】:

对于我的应用,我有一个欢迎屏幕,用于介绍应用的功能并允许用户创建他们的第一个项目。当用户单击按钮时,我想关闭“welcomeScreen”表,然后启动“newRemindr”表。

我试图通过创建一个将“addNewTrigger”布尔值设置为 false 的可观察对象来实现这一点。当我单击welcomeScreen 上的Add New Reminder 按钮时,该按钮的操作会导致welcomeScreen 关闭并将“addNewTrigger”布尔值切换为True。 (我已经验证这与打印语句一起使用)。然而,内容视图正在侦听相同的观察对象以启动“newRemindr”工作表,但该操作似乎不起作用。

有人可以看看代码,看看我哪里出错了吗?或者建议可以提供该类型功能的替代方案。

我非常感谢所有的帮助。谢谢!

下面的代码...

欢迎屏幕:

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

内容视图:

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

【问题讨论】:

  • 你在哪里定义了你的 .sheet 修饰符。您不能在一个视图之上声明 2 个 .sheet 修饰符,它们应该在两个不同视图之上。 (按钮、文本……也是视图)
  • 您的床单仍然放得不好。这是一个自去年以来一直没有解决的错误,所以这不是你的错。将.sheet(isPresented: $showWelcomeScreen) { welcomeScreen() }移到评论// Add New Reminder Button上方

标签: ios swift xcode swiftui


【解决方案1】:

首先我看到的是你在两个视图中都使用了不同的可观察对象,但应该使用相同的,所以在一个视图中所做的更改也可以用于第二个视图。

这里是解决这个问题的方法

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

替代方案:您可以从welcomeScreen 中删除addNewReminder,并仅在ContentView 中使用它,方法是在欢迎表关闭时激活,例如

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

【讨论】:

  • 太棒了!很高兴看到我走在正确的轨道上。非常感谢您的帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-06-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多