tur*_*ted 129 modal-dialog swift swiftui
我有这个 ContentView 有两个不同的模式视图,所以我sheet(isPresented:)同时使用这两个视图,但似乎只有最后一个被呈现。我怎么能解决这个问题?或者无法在 SwiftUI 的视图上使用多个工作表?
struct ContentView: View {
@State private var firstIsPresented = false
@State private var secondIsPresented = false
var body: some View {
NavigationView {
VStack(spacing: 20) {
Button("First modal view") {
self.firstIsPresented.toggle()
}
Button ("Second modal view") {
self.secondIsPresented.toggle()
}
}
.navigationBarTitle(Text("Multiple modal view problem"), displayMode: .inline)
.sheet(isPresented: $firstIsPresented) {
Text("First modal view")
}
.sheet(isPresented: $secondIsPresented) {
Text("Only the second modal view works!")
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
上面的代码编译时没有警告(Xcode 11.2.1)。
ram*_*nok 153
从Xcode 12.5.0 Beta 3(2021 年 3 月 3 日)开始,这个问题不再有意义,因为现在可以有多个.sheet(isPresented:)或.fullScreenCover(isPresented:)连续,并且问题中提供的代码可以正常工作。
尽管如此,我发现这个答案仍然有效,因为它很好地组织了工作表并使代码干净且更具可读性 - 你有一个事实来源而不是几个独立的布尔值
最好的方法,这也适用于iOS 14:
enum ActiveSheet: Identifiable {
case first, second
var id: Int {
hashValue
}
}
struct YourView: View {
@State var activeSheet: ActiveSheet?
var body: some View {
VStack {
Button {
activeSheet = .first
} label: {
Text("Activate first sheet")
}
Button {
activeSheet = .second
} label: {
Text("Activate second sheet")
}
}
.sheet(item: $activeSheet) { item in
switch item {
case .first:
FirstView()
case .second:
SecondView()
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
在此处阅读更多信息:https : //developer.apple.com/documentation/swiftui/view/sheet(item : ondismiss : content:)
隐藏刚刚设置的工作表 activeSheet = nil
奖励:
如果您希望您的工作表全屏显示,请使用完全相同的代码,而不是.sheet编写.fullScreenCover
Roh*_*ana 76
请尝试以下代码
更新答案(iOS 14、Xcode 12)
enum ActiveSheet {
case first, second
var id: Int {
hashValue
}
}
struct ContentView: View {
@State private var showSheet = false
@State private var activeSheet: ActiveSheet? = .first
var body: some View {
NavigationView {
VStack(spacing: 20) {
Button("First modal view") {
self.showSheet = true
self.activeSheet = .first
}
Button ("Second modal view") {
self.showSheet = true
self.activeSheet = .second
}
}
.navigationBarTitle(Text("Multiple modal view problem"), displayMode: .inline)
.sheet(isPresented: $showSheet) {
if self.activeSheet == .first {
Text("First modal view")
}
else {
Text("Only the second modal view works!")
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
Tyl*_*230 43
还可以将工作表添加到放置在视图背景中的 EmptyView。这可以多次执行:
.background(EmptyView()
.sheet(isPresented: isPresented, content: content))
Run Code Online (Sandbox Code Playgroud)
Asp*_*eri 40
您的情况可以通过以下方式解决(使用 Xcode 11.2 测试)
var body: some View {
NavigationView {
VStack(spacing: 20) {
Button("First modal view") {
self.firstIsPresented.toggle()
}
.sheet(isPresented: $firstIsPresented) {
Text("First modal view")
}
Button ("Second modal view") {
self.secondIsPresented.toggle()
}
.sheet(isPresented: $secondIsPresented) {
Text("Only the second modal view works!")
}
}
.navigationBarTitle(Text("Multiple modal view problem"), displayMode: .inline)
}
}
Run Code Online (Sandbox Code Playgroud)
您只需将按钮和 .sheet 调用组合在一起即可完成此操作。如果您有一个前导和一个尾随,那就很简单了。但是,如果您在前导或尾随中有多个导航栏项,则需要将它们包装在 HStack 中,并将每个按钮及其表单调用包装在 VStack 中。
这是两个尾随按钮的示例:
trailing:
HStack {
VStack {
Button(
action: {
self.showOne.toggle()
}
) {
Image(systemName: "camera")
}
.sheet(isPresented: self.$showOne) {
OneView().environment(\.managedObjectContext, self.managedObjectContext)
}
}//showOne vstack
VStack {
Button(
action: {
self.showTwo.toggle()
}
) {
Image(systemName: "film")
}
.sheet(isPresented: self.$showTwo) {
TwoView().environment(\.managedObjectContext, self.managedObjectContext)
}
}//show two vstack
}//nav bar button hstack
Run Code Online (Sandbox Code Playgroud)
在其中创建自定义按钮视图和调用表解决了这个问题。
struct SheetButton<Content>: View where Content : View {
var text: String
var content: Content
@State var isPresented = false
init(_ text: String, @ViewBuilder content: () -> Content) {
self.text = text
self.content = content()
}
var body: some View {
Button(text) {
self.isPresented.toggle()
}
.sheet(isPresented: $isPresented) {
self.content
}
}
}
Run Code Online (Sandbox Code Playgroud)
ContentView 会更干净。
struct ContentView: View {
var body: some View {
NavigationView {
VStack(spacing: 20) {
SheetButton("First modal view") {
Text("First modal view")
}
SheetButton ("Second modal view") {
Text("Only the second modal view works!")
}
}
.navigationBarTitle(Text("Multiple modal view problem"), displayMode: .inline)
}
}
}
Run Code Online (Sandbox Code Playgroud)
当打开工作表取决于列表行内容时,此方法也可以正常工作。
struct ContentView: View {
var body: some View {
NavigationView {
List(1...10, id: \.self) { row in
SheetButton("\(row) Row") {
Text("\(row) modal view")
}
}
.navigationBarTitle(Text("Multiple modal view problem"), displayMode: .inline)
}
}
}
Run Code Online (Sandbox Code Playgroud)
从 iOS 和 iPadOS 14.5 Beta 3 开始,无论何时公开发布,多张工作表都会按预期工作,并且不需要其他答案中的任何解决方法。从发行说明:
用户界面
已在 iOS 和 iPadOS 14.5 Beta 3 中解决
您现在可以在同一视图层次结构中应用多个
sheet(isPresented:onDismiss:content:)和fullScreenCover(item:onDismiss:content:)修改器。(74246633)