对于我的应用程序,我有一个欢迎屏幕,介绍应用程序的功能并允许用户创建他们的第一个项目。当用户单击按钮时,我想关闭“welcomeScreen”工作表,然后启动“newRemindr”工作表。
我尝试通过创建一个可观察对象并将“addNewTrigger”布尔值设置为 false 来实现此目的。当我单击welcomeScreen 上的“添加新提醒”按钮时,该按钮的操作会导致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()
}
}
}
}
首先我看到的是,您在两个视图中使用不同可观察对象,但应该使用相同的对象,因此在一个视图中所做的更改也可用于第二个视图。
这里有一个解决这个问题的方法
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
中删除welcomeScreen
,并仅在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()
}
DispatchQueue.main.asyncAfter
来允许两个工作表屏幕之间的事务。
.sheet(isPresented: $showWelcomeScreen, onDismiss: {
// change toggle to open another sheet screen
self.addNewReminder.addNewTrigger.toggle()
})
这样更干净。