SwiftUI sheet 当 isPresented 值从闭包更改时不解除
SwiftUI sheet not dismissing when isPresented value changes from a closure
我有一个 sheet 视图,当用户单击如下父视图所示的按钮时会显示该视图:
struct ViewWithSheet: View {
@State var showingSheetView: Bool = false
@EnvironmetObject var store: DataStore()
var body: some View {
NavigationView() {
ZStack {
Button(action: { self.showingSheetView = true }) {
Text("Show sheet view")
}
}
.navigationBarHidden(true)
.navigationBarTitle("")
.sheet(isPresented: $showingSheetView) {
SheetView(showingSheetView: self.$showingSheetView).environmentObject(self.dataStore)
}
}
}
}
在 sheet 视图中,当用户单击另一个按钮时,具有完成处理程序的商店会执行一个操作。完成处理程序 returns 一个对象值,如果该值存在,应该关闭 SheetView。
struct SheetView: View {
@Binding var showingSheetView: Bool
@EnvironmentObject var store: DataStore()
//@Environment(\.presentationMode) private var presentationMode
func create() {
store.createObject() { object, error in
if let _ = object {
self.showingSheetView = false
// self.presentationMode.wrappedValue.dismiss()
}
}
}
var body: some View {
VStack {
VStack {
HStack {
Button(action: { self.showingSheetView = false }) {
Text("Cancel")
}
Spacer()
Spacer()
Button(action: { self.create() }) {
Text("Add")
}
}
.padding()
}
}
}
}
但是,在 create() 函数中,一旦存储 returns 值和 showingSheetView 设置为 false,sheet 视图不会按预期关闭。我也尝试过使用 presentationMode 关闭 sheet,但这似乎也不起作用。
尝试在主队列上显式执行此操作
func create() {
store.createObject() { object, error in
if let _ = object {
DispatchQueue.main.async {
self.showingSheetView = false
}
}
// think also about feedback on else case as well !!
}
}
我发现了我的问题,sheet 并没有因为我的整体应用程序包装视图中的条件而被解雇,我有一个 if 语句会在应用程序启动时显示加载视图,但是,在我的DataStore 我在它执行的每个函数调用上设置它的获取变量。当该值更改时,我的 sheet 视图后面的视图堆栈将重新呈现 LoadingView,然后在获取变量再次更改后重新呈现我的 TabView。这使得 sheet 视图不可关闭。这是我的 AppView 的示例:
struct AppView: View {
@State private var fetchMessage: String = ""
@EnvironmentObject var store: DataStore()
func initializeApp() {
self.fetchMessage = "Getting App Data"
store.getData() { object, error in
if let error = error {
self.fetchMessage = error.localizedDescription
}
self.fetchMessage = ""
}
}
var body: some View {
Group {
ZStack {
//this is where my issue was occurring
if(!store.fetching) {
TabView {
Tab1().tabItem {
Image(systemName: "tab-1")
Text("Tab1")
}
Tab2().tabItem {
Image(systemName: "tab-2")
Text("Tab2")
}
//Tab 3 contained my ViewWithSheet() and SheetView()
Tab3().tabItem {
Image(systemName: "tab-3")
Text("Tab3")
}
}
} else {
LoadingView(loadingMessage: $fetchMessage)
}
}
}.onAppear(perform: initializeApp)
}
}
为了解决我的问题,我在 DataStore 中添加了另一个名为 initializing 的变量,我用它来呈现加载屏幕或应用程序中第一个 .onAppear 事件的实际应用程序视图。下面是我更新后的 AppView 的示例:
struct AppView: View {
@State private var fetchMessage: String = ""
@EnvironmentObject var store: DataStore()
func initializeApp() {
self.fetchMessage = "Getting App Data"
store.getData() { object, error in
if let error = error {
self.fetchMessage = error.localizedDescription
}
self.fetchMessage = ""
//set the value to false once I'm done getting my app's initial data.
self.store.initializing = false
}
}
var body: some View {
Group {
ZStack {
//now using initializing instead
if(!store.initializing) {
TabView {
Tab1().tabItem {
Image(systemName: "tab-1")
Text("Tab1")
}
Tab2().tabItem {
Image(systemName: "tab-2")
Text("Tab2")
}
//Tab 3 contained my ViewWithSheet() and SheetView()
Tab3().tabItem {
Image(systemName: "tab-3")
Text("Tab3")
}
}
} else {
LoadingView(loadingMessage: $fetchMessage)
}
}
}.onAppear(perform: initializeApp)
}
}
想看看对我有用的骇人听闻的东西吗?免责声明:可能不适合你,我不一定推荐它。但也许它会在紧要关头帮助某人。
如果您添加 NavigationLink
并保留 fullScreenCover
,那么全屏封面将能够像您预期的那样自行关闭。
为什么将 NavigationLink 添加到视图时会发生这种情况?我不知道。我的猜测是它在某处创建了一个额外的引用。
将此添加到您的 body
,并保持您的 sheet 不变:
NavigationLink(destination: YOURVIEW().environmentObjects(), isActive: $showingSheetView) {}
我有一个 sheet 视图,当用户单击如下父视图所示的按钮时会显示该视图:
struct ViewWithSheet: View {
@State var showingSheetView: Bool = false
@EnvironmetObject var store: DataStore()
var body: some View {
NavigationView() {
ZStack {
Button(action: { self.showingSheetView = true }) {
Text("Show sheet view")
}
}
.navigationBarHidden(true)
.navigationBarTitle("")
.sheet(isPresented: $showingSheetView) {
SheetView(showingSheetView: self.$showingSheetView).environmentObject(self.dataStore)
}
}
}
}
在 sheet 视图中,当用户单击另一个按钮时,具有完成处理程序的商店会执行一个操作。完成处理程序 returns 一个对象值,如果该值存在,应该关闭 SheetView。
struct SheetView: View {
@Binding var showingSheetView: Bool
@EnvironmentObject var store: DataStore()
//@Environment(\.presentationMode) private var presentationMode
func create() {
store.createObject() { object, error in
if let _ = object {
self.showingSheetView = false
// self.presentationMode.wrappedValue.dismiss()
}
}
}
var body: some View {
VStack {
VStack {
HStack {
Button(action: { self.showingSheetView = false }) {
Text("Cancel")
}
Spacer()
Spacer()
Button(action: { self.create() }) {
Text("Add")
}
}
.padding()
}
}
}
}
但是,在 create() 函数中,一旦存储 returns 值和 showingSheetView 设置为 false,sheet 视图不会按预期关闭。我也尝试过使用 presentationMode 关闭 sheet,但这似乎也不起作用。
尝试在主队列上显式执行此操作
func create() {
store.createObject() { object, error in
if let _ = object {
DispatchQueue.main.async {
self.showingSheetView = false
}
}
// think also about feedback on else case as well !!
}
}
我发现了我的问题,sheet 并没有因为我的整体应用程序包装视图中的条件而被解雇,我有一个 if 语句会在应用程序启动时显示加载视图,但是,在我的DataStore 我在它执行的每个函数调用上设置它的获取变量。当该值更改时,我的 sheet 视图后面的视图堆栈将重新呈现 LoadingView,然后在获取变量再次更改后重新呈现我的 TabView。这使得 sheet 视图不可关闭。这是我的 AppView 的示例:
struct AppView: View {
@State private var fetchMessage: String = ""
@EnvironmentObject var store: DataStore()
func initializeApp() {
self.fetchMessage = "Getting App Data"
store.getData() { object, error in
if let error = error {
self.fetchMessage = error.localizedDescription
}
self.fetchMessage = ""
}
}
var body: some View {
Group {
ZStack {
//this is where my issue was occurring
if(!store.fetching) {
TabView {
Tab1().tabItem {
Image(systemName: "tab-1")
Text("Tab1")
}
Tab2().tabItem {
Image(systemName: "tab-2")
Text("Tab2")
}
//Tab 3 contained my ViewWithSheet() and SheetView()
Tab3().tabItem {
Image(systemName: "tab-3")
Text("Tab3")
}
}
} else {
LoadingView(loadingMessage: $fetchMessage)
}
}
}.onAppear(perform: initializeApp)
}
}
为了解决我的问题,我在 DataStore 中添加了另一个名为 initializing 的变量,我用它来呈现加载屏幕或应用程序中第一个 .onAppear 事件的实际应用程序视图。下面是我更新后的 AppView 的示例:
struct AppView: View {
@State private var fetchMessage: String = ""
@EnvironmentObject var store: DataStore()
func initializeApp() {
self.fetchMessage = "Getting App Data"
store.getData() { object, error in
if let error = error {
self.fetchMessage = error.localizedDescription
}
self.fetchMessage = ""
//set the value to false once I'm done getting my app's initial data.
self.store.initializing = false
}
}
var body: some View {
Group {
ZStack {
//now using initializing instead
if(!store.initializing) {
TabView {
Tab1().tabItem {
Image(systemName: "tab-1")
Text("Tab1")
}
Tab2().tabItem {
Image(systemName: "tab-2")
Text("Tab2")
}
//Tab 3 contained my ViewWithSheet() and SheetView()
Tab3().tabItem {
Image(systemName: "tab-3")
Text("Tab3")
}
}
} else {
LoadingView(loadingMessage: $fetchMessage)
}
}
}.onAppear(perform: initializeApp)
}
}
想看看对我有用的骇人听闻的东西吗?免责声明:可能不适合你,我不一定推荐它。但也许它会在紧要关头帮助某人。
如果您添加 NavigationLink
并保留 fullScreenCover
,那么全屏封面将能够像您预期的那样自行关闭。
为什么将 NavigationLink 添加到视图时会发生这种情况?我不知道。我的猜测是它在某处创建了一个额外的引用。
将此添加到您的 body
,并保持您的 sheet 不变:
NavigationLink(destination: YOURVIEW().environmentObjects(), isActive: $showingSheetView) {}