여러 시트(isPresented:)가 Swift에서 작동하지 않음UI
2개의 모드를 하고 있습니다.sheet(isPresented:)
두 분 다요. 마지막 한 분만 발표되는 것 같아서요.어떻게 하면 이 문제를 해결할 수 있을까요?또는 Swift에서는 한 뷰에 여러 시트를 사용할 수 없는가? UI?
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!")
}
}
}
}
위의 코드는 경고 없이 컴파일됩니다(X코드 11.2.1).
업데이트
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()
}
}
}
}
자세한 내용은 이쪽:https://developer.apple.com/documentation/swiftui/view/sheet(item:ondismiss:content:)
, 「 」를 설정해 주세요.activeSheet = nil
보너스: 시트를 전체 화면으로 만들려면 동일한 코드를 사용합니다..sheet
를 쓰다.fullScreenCover
아래 코드를 입력해 주세요.
응답 업데이트(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!")
}
}
}
}
}
뷰의 배경에 배치된 EmptyView에 시트를 추가할 수도 있습니다.이 작업은 여러 번 수행할 수 있습니다.
.background(EmptyView()
.sheet(isPresented: isPresented, content: content))
고객의 케이스는 다음 방법으로 해결할 수 있습니다(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)
}
}
버튼과 .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
커스텀 버튼뷰와 콜시트를 작성하면 이 문제가 해결됩니다.
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
}
}
}
Content View가 더 깨끗해집니다.
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)
}
}
}
이 방법은 List 행 내용에 따라 시트를 여는 경우에도 정상적으로 작동합니다.
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)
}
}
}
iOS 및 iPad의 경우OS 14.5 베타 3 및 공개될 때마다 예상대로 여러 시트가 작동하며 다른 답변의 회피책은 필요하지 않습니다.릴리스 노트:
SwiftUI
iOS 및 iPad로 해결OS 14.5 베타 3
해서 여러 개의 기한을 적용할 수 되었습니다.
sheet(isPresented:onDismiss:content:)
★★★★★★★★★★★★★★★★★」fullScreenCover(item:onDismiss:content:)
)
Rohit Makwana의 답변과 더불어, 저는 컴파일러가 제 거인의 활자를 확인하는 데 어려움을 겪고 있었기 때문에 시트의 내용을 함수로 추출하는 방법을 찾았습니다.View
.
extension YourView {
enum Sheet {
case a, b
}
@ViewBuilder func sheetContent() -> some View {
if activeSheet == .a {
A()
} else if activeSheet == .b {
B()
}
}
}
다음과 같이 사용할 수 있습니다.
.sheet(isPresented: $isSheetPresented, content: sheetContent)
코드를 깔끔하게 하고 컴파일러의 스트레스도 해소합니다.
이 질문에는 이미 많은 답이 있다는 것을 알지만, 저는 이 문제에 대해 매우 유용한 다른 가능한 해결책을 찾았습니다.이런 문구가 있으면 안에 포장하는 거예요.액션 시트의 경우, iPad의 스크롤 뷰에 있는 다른 솔루션(그룹 내에서 각 시트와 버튼을 감는 것 등)을 사용하면 액션 시트가 이상한 곳으로 이동하는 경우가 많기 때문에, 이 답변으로 iPad의 스크롤 뷰에 있는 액션 시트의 문제를 해결할 수 있습니다.
struct ContentView: View{
@State var sheet1 = false
@State var sheet2 = false
var body: some View{
VStack{
Button(action: {
self.sheet1.toggle()
},label: {
Text("Sheet 1")
}).padding()
Button(action: {
self.sheet2.toggle()
},label: {
Text("Sheet 2")
}).padding()
}
if self.sheet1{
Text("")
.sheet(isPresented: self.$sheet1, content: {
Text("Some content here presenting sheet 1")
})
}
if self.sheet2{
Text("")
.sheet(isPresented: self.$sheet2, content: {
Text("Some content here presenting sheet 2")
})
}
}
}
이 솔루션은 iOS 14.0에서 작동합니다.
이 솔루션은 .sheet(항목:, 내용:) 구성을 사용하고 있습니다.
struct ContentView: View {
enum ActiveSheet: Identifiable {
case First, Second
var id: ActiveSheet { self }
}
@State private var activeSheet: ActiveSheet?
var body: some View {
NavigationView {
VStack(spacing: 20) {
Button("First modal view") {
activeSheet = .First
}
Button ("Second modal view") {
activeSheet = .Second
}
}
.navigationBarTitle(Text("Multiple modal view problem"), displayMode: .inline)
.sheet(item: $activeSheet) { sheet in
switch sheet {
case .First:
Text("First modal view")
case .Second:
Text("Only the second modal view works!")
}
}
}
}
}
및 4장, 1장 이상의 경보의 를 나타냅니다. 시트 ★★★★★★★★★★★★★★」ContentView
13에서는 , 에서는 OK, 13에서는 , iOS 14에서는 OK, OK
에서 : (으)는 게 목적입니다.sheet(item:onDismiss:content:)
을 ★★★★★★★★★★★★★★★★★★★로@State
및 var에 된 값. 「는 모두 「비즈니스」에.ContentView
이와 같이 시트 수나 경고 수에 제한이 없습니다.
아래 코드의 출력을 다음에 나타냅니다.
import SwiftUI
// exemple which show use of 4 sheets,
// 1 (or more) alerts,
// and an actionSheet in the same ContentView
// OK in iOS 13, iOS 14
// OK in Preview
// Any number of sheets, displayed as Views
// can be used for sheets in other views (with unique case values, of course)
enum SheetState {
case none
case AddItem
case PickPhoto
case DocPicker
case ActivityController
}
// Make Identifiable
extension SheetState: Identifiable {
var id: SheetState { self }
}
// the same for Alerts (who are not View, but Alert)
enum AlertState {
case none
case Delete
}
extension AlertState: Identifiable {
var id: AlertState { self }
}
struct ContentView: View {
// Initialized with nil value
@State private var sheetState: SheetState?
@State private var alertState: AlertState?
var body: some View {
NavigationView {
Form {
Text("Hello, world!")
Section(header: Text("sheets")) {
addItemButton
pickDocumentButton
pickPhoto
buttonExportView
}
Section(header: Text("alert")) {
confirmDeleteButton
}
Section(header: Text("Action sheet")) {
showActionSheetButton
}
}
.navigationTitle("Sheets & Alerts")
// ONLY ONE call .sheet(item: ... with required value in enum
// if item become not nil => display sheet
// when dismiss sheet (drag the modal view, or use presentationMode.wrappedValue.dismiss in Buttons) => item = nil
// in other way : if you set item to nil => dismiss sheet
// in closure, look for which item value display which view
// the "item" returned value contains the value passed in .sheet(item: ...
.sheet(item: self.$sheetState) { item in
if item == SheetState.AddItem {
addItemView // SwiftUI view
} else if item == SheetState.DocPicker {
documentPickerView // UIViewControllerRepresentable
} else if item == SheetState.PickPhoto {
imagePickerView // UIViewControllerRepresentable
} else if item == SheetState.ActivityController {
activityControllerView // UIViewControllerRepresentable
}
}
.alert(item: self.$alertState) { item in
if item == AlertState.Delete {
return deleteAlert
} else {
// Not used, but seem to be required
// .alert(item: ... MUST return an Alert
return noneAlert
}
}
}
}
// For cleaner contents : controls, alerts and sheet views are "stocked" in private var
// MARK: - Sheet Views
private var addItemView: some View {
Text("Add item").font(.largeTitle).foregroundColor(.blue)
// drag the modal view set self.sheetState to nil
}
private var documentPickerView: some View {
DocumentPicker() { url in
if url != nil {
DispatchQueue.main.async {
print("url")
}
}
self.sheetState = nil
// make the documentPicker view dismissed
}
}
private var imagePickerView: some View {
ImagePicker() { image in
if image != nil {
DispatchQueue.main.async {
self.logo = Image(uiImage: image!)
}
}
self.sheetState = nil
}
}
private var activityControllerView: some View {
ActivityViewController(activityItems: ["Message to export"], applicationActivities: [], excludedActivityTypes: [])
}
// MARK: - Alert Views
private var deleteAlert: Alert {
Alert(title: Text("Delete?"),
message: Text("That cant be undone."),
primaryButton: .destructive(Text("Delete"), action: { print("delete!") }),
secondaryButton: .cancel())
}
private var noneAlert: Alert {
Alert(title: Text("None ?"),
message: Text("No action."),
primaryButton: .destructive(Text("OK"), action: { print("none!") }),
secondaryButton: .cancel())
}
// In buttons, action set value in item for .sheet(item: ...
// Set self.sheetState value make sheet displayed
// MARK: - Buttons
private var addItemButton: some View {
Button(action: { self.sheetState = SheetState.AddItem }) {
HStack {
Image(systemName: "plus")
Text("Add an Item")
}
}
}
private var pickDocumentButton: some View {
Button(action: { self.sheetState = SheetState.DocPicker }) {
HStack {
Image(systemName: "doc")
Text("Choose Document")
}
}
}
@State private var logo: Image = Image(systemName: "photo")
private var pickPhoto: some View {
ZStack {
HStack {
Text("Pick Photo ->")
Spacer()
}
HStack {
Spacer()
logo.resizable().scaledToFit().frame(height: 36.0)
Spacer()
}
}
.onTapGesture { self.sheetState = SheetState.PickPhoto }
}
private var buttonExportView: some View {
Button(action: { self.sheetState = SheetState.ActivityController }) {
HStack {
Image(systemName: "square.and.arrow.up").imageScale(.large)
Text("Export")
}
}
}
private var confirmDeleteButton: some View {
Button(action: { self.alertState = AlertState.Delete}) {
HStack {
Image(systemName: "trash")
Text("Delete!")
}.foregroundColor(.red)
}
}
@State private var showingActionSheet = false
@State private var foregroundColor = Color.blue
private var showActionSheetButton: some View {
Button(action: { self.showingActionSheet = true }) {
HStack {
Image(systemName: "line.horizontal.3")
Text("Show Action Sheet")
}.foregroundColor(foregroundColor)
}
.actionSheet(isPresented: $showingActionSheet) {
ActionSheet(title: Text("Change foreground"), message: Text("Select a new color"), buttons: [
.default(Text("Red")) { self.foregroundColor = .red },
.default(Text("Green")) { self.foregroundColor = .green },
.default(Text("Blue")) { self.foregroundColor = .blue },
.cancel()
])
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
이것은 iOS 13.x에서 3장의 시트를 표시할 수 있는 앱에서 잘 작동했습니다.재미있는 행동은 iOS 14에서 시작되었다.앱 부팅 시 어떤 이유에서인지 표시할 시트를 선택하면 상태 변수가 설정되지 않고 빈 화면으로 나타납니다.첫 번째 선택지를 계속 선택하면 공백 시트가 계속 표시됩니다.두 번째 선택지(첫 번째 선택지와 다름)를 선택하면 변수가 설정되고 적절한 시트가 표시됩니다.어느 시트를 먼저 선택해도 같은 바하비어가 발생합니다.
벌레요? 아니면 제가 뭘 놓치고 있는 건가요?제 코드는 3개의 시트 옵션을 제외하고 위와 거의 동일하며, 버튼을 눌렀을 때 실행되는 () -> Void라는 인수를 사용하는 커스텀 버튼이 있습니다.iOS 13.x에서는 정상적으로 동작하지만 iOS 14에서는 동작하지 않습니다.
데이브
Edit 2: 최신 iOS 16.4에서 시트, confirmationDialog, popover all이 서로 충돌하는 주요 버그가 있습니다.예를 들어, 팝오버가 표시되어 있고 시트를 표시하려고 하면 시트가 파손되어 다시 표시할 수 없습니다.
편집: iOS 14.5 베타 3에서 이 문제는 해결되었습니다.
SwiftUI iOS 및 iPad로 해결OS 14.5 베타 3
- 해서 여러 개의 기한을 적용할 수 되었습니다.
sheet(isPresented:onDismiss:content:)
★★★★★★★★★★★★★★★★★」fullScreenCover(item:onDismiss:content:)
)
수정 전에는 각 버튼에 시트 수식자를 적용하는 것이 회피책이었습니다.
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()
}
.sheet(isPresented: $firstIsPresented) {
Text("First modal view")
}
Button ("Second modal view") {
self.secondIsPresented.toggle()
}
.sheet(isPresented: $secondIsPresented) {
Text("Second modal view")
}
}
.navigationBarTitle(Text("Multiple modal view problem"), displayMode: .inline)
}
}
}
두 시트 모두 동일한 작업을 수행하므로 중복된 기능을 하위 보기로 추출할 수 있습니다.
struct ContentView: View {
var body: some View {
NavigationView {
VStack(spacing: 20) {
ShowSheet(title:"First modal view")
ShowSheet(title:"Second modal view")
}
.navigationBarTitle(Text("Multiple modal view no problem!"), displayMode: .inline)
}
}
}
struct ShowSheet: View {
@State private var isPresented = false
let title: String
var body: some View {
Button(title) {
isPresented.toggle()
}
.sheet(isPresented: $isPresented) {
Text(title)
}
}
}
인정된 솔루션은 훌륭하게 동작합니다만, 다른 사람이 같은 문제에 직면했을 경우에 대비해, 추가의 증강을 공유하고 싶다고 생각하고 있습니다.
나의 고민
두 개의 버튼이 하나로 작동하는 문제가 있었습니다.조합하여 2개의 버튼을 했습니다.VStack
★★★★★★★★★★★★★★★★★」HStack
을 사용하다 한 사람만을 하고 있었다..sheet
총격을 가할 수 있는 방법을 가리지 않고요.
솔루션
여기서의 답은 나에게 퍼즐의 잃어버린 조각처럼 작용했다.
중 하나를 .buttonStyle(BorderlessButtonStyle())
★★★★★★★★★★★★★★★★★」.buttonStyle(PlainButtonStyle())
각 버튼에 대해 예상대로 단일 버튼처럼 작동하도록 합니다.
여기에 이것을 추가함으로써 가짜 패스를 범했다면 죄송합니다만, StackOverlflow에 글을 올리는 것은 이번이 처음입니다.
" " " " " " ]sheet(isPresented)
는 뷰 수식자입니다.
뷰 또는 다른 뷰 수식자에 적용하여 원래 값의 다른 버전을 생성하는 수식자입니다.
Apple Documentation(애플 문서
즉, 동일한 보기를 두 번 수정합니다.SwfitUI 에서는 순서가 중요하기 때문에 마지막 순서만 표시됩니다.
필요한 것은 수정자를 다른 보기에 적용하거나 필요에 따라 시트를 다르게 표시하는 것입니다.
여러 시트를 하나의 뷰에 표시하는 또 다른 간단한 방법은 다음과 같습니다.
각 뷰의 프라이빗 var에는 독자적인 Bool @State 값과 .sheet(isPresented: ...콜)이 있습니다.
구현이 간단하며 모두 한 곳에서 필요합니다.iOS 13, iOS 14, 프리뷰로 OK
import SwiftUI
struct OtherContentView: View {
var body: some View {
Form {
Section {
button1
}
Section {
button2
}
Section {
button3
}
Section {
button4
}
}
}
@State private var showSheet1 = false
private var button1: some View {
Text("Sheet 1")
.onTapGesture { showSheet1 = true }
.sheet(isPresented: $showSheet1) { Text("Modal Sheet 1") }
}
@State private var showSheet2 = false
private var button2: some View {
Text("Sheet 2")
.onTapGesture { showSheet2 = true }
.sheet(isPresented: $showSheet2) { Text("Modal Sheet 2") }
}
@State private var showSheet3 = false
private var button3: some View {
Text("Sheet 3")
.onTapGesture { showSheet3 = true }
.sheet(isPresented: $showSheet3) { Text("Modal Sheet 3") }
}
@State private var showSheet4 = false
private var button4: some View {
Text("Sheet 4")
.onTapGesture { showSheet4 = true }
.sheet(isPresented: $showSheet4) { Text("Modal Sheet 4") }
}
}
struct OtherContentView_Previews: PreviewProvider {
static var previews: some View {
OtherContentView()
}
}
the i 잡 i를 해결했다.@State
관찰 한 것을 을 만들 수 있습니다.SheetContext
저를 위해 국가를 관리하고 있습니다.그런 다음 단일 컨텍스트 인스턴스만 필요하며 뷰를 시트로 표시하도록 지시할 수 있습니다.
상세한 것에 대하여는, 다음의 블로그 투고를 참조해 주세요.https://danielsaidi.com/blog/2020/06/06/swiftui-sheets
그건 스위프트가 할 수 있는 방법이 아닌 것 같아요.UI를 통해 모든 종류의 뷰를 표시할 수 있습니다.
이 패러다임은 화면에 일부 콘텐츠를 표시하는 특정 보기를 만드는 방식으로 작동하기 때문에 무언가를 표시해야 하는 슈퍼뷰 본문 내에서 여러 보기를 볼 수 있습니다.그래서 스위프트iOS 14의 UI 2는 이를 수락하지 않으며 개발자는 경우에 따라 수락할 수 있는 슈퍼뷰의 모든 프레젠테이션을 호출해야 하지만 특정 보기가 내용을 표시하면 더 나은 순간이 있습니다.
이를 위한 솔루션을 구현하고 iOS 14.1에서 Xcode 12.1을 사용하는 Swift 5.3에서 테스트했습니다.
struct Presentation<Content>: View where Content: View {
enum Style {
case sheet
case popover
case fullScreenCover
}
@State private var isTrulyPresented: Bool = false
@State private var willPresent: Bool = false
@Binding private var isPresented: Bool
let content: () -> Content
let dismissHandler: (() -> Void)?
let style: Style
init(_ style: Style, _ isPresented: Binding<Bool>, onDismiss: (() -> Void)?, content: @escaping () -> Content) {
self._isPresented = isPresented
self.content = content
self.dismissHandler = onDismiss
self.style = style
}
@ViewBuilder
var body: some View {
if !isPresented && !willPresent {
EmptyView()
} else {
switch style {
case .sheet:
EmptyView()
.sheet(isPresented: $isTrulyPresented, onDismiss: dismissHandler, content: dynamicContent)
case .popover:
EmptyView()
.popover(isPresented: $isTrulyPresented, content: dynamicContent)
case .fullScreenCover:
EmptyView()
.fullScreenCover(isPresented: $isTrulyPresented, onDismiss: dismissHandler, content: dynamicContent)
}
}
}
}
extension Presentation {
var dynamicContent: () -> Content {
if isPresented && !isTrulyPresented {
OperationQueue.main.addOperation {
willPresent = true
OperationQueue.main.addOperation {
isTrulyPresented = true
}
}
} else if isTrulyPresented && !isPresented {
OperationQueue.main.addOperation {
isTrulyPresented = false
OperationQueue.main.addOperation {
willPresent = false
}
}
}
return content
}
}
그 후 Swift의 모든 뷰에 대해 이러한 메서드를 구현할 수 있습니다.UI
public extension View {
func _sheet<Content>(
isPresented: Binding<Bool>,
content: @escaping () -> Content
) -> some View where Content: View {
self.background(
Presentation(
.sheet,
isPresented,
onDismiss: nil,
content: content
)
)
}
func _sheet<Content>(
isPresented: Binding<Bool>,
onDismiss: @escaping () -> Void,
content: @escaping () -> Content
) -> some View where Content: View {
self.background(
Presentation(
.sheet,
isPresented,
onDismiss: onDismiss,
content: content
)
)
}
}
public extension View {
func _popover<Content>(
isPresented: Binding<Bool>,
content: @escaping () -> Content
) -> some View where Content: View {
self.background(
Presentation(
.popover,
isPresented,
onDismiss: nil,
content: content
)
)
}
}
public extension View {
func _fullScreenCover<Content>(
isPresented: Binding<Bool>,
content: @escaping () -> Content
) -> some View where Content: View {
self.background(
Presentation(
.fullScreenCover,
isPresented,
onDismiss: nil,
content: content
)
)
}
func _fullScreenCover<Content>(
isPresented: Binding<Bool>,
onDismiss: @escaping () -> Void,
content: @escaping () -> Content
) -> some View where Content: View {
self.background(
Presentation(
.fullScreenCover,
isPresented,
onDismiss: onDismiss,
content: content
)
)
}
}
상기의 회답변
- 두 시트의 순차적 관계가 있는 경우 이전 시트를 교체할 수 있습니다.
import SwiftUI
struct Sheet1: View {
@Environment(\.dismiss) private var dismiss
@State var text: String = "Text"
var body: some View {
Text(self.text)
if self.text == "Modified Text" {
Button {
dismiss()
} label: {
Text("Close sheet")
}
} else {
Button {
self.text = "Modified Text"
} label: {
Text("Modify Text")
}
}
}
}
struct SheetTester: View {
@State private var isShowingSheet1 = false
var body: some View {
Button(action: {
isShowingSheet1.toggle()
}) {
Text("Show Sheet1")
}
.sheet(isPresented: $isShowingSheet1) {
Sheet1()
}
}
}
또는 2. 두 장의 시트를 병렬로 사용합니다.
struct SheetTester: View {
@State private var isShowingSheet1 = false
var body: some View {
Button(action: {
isShowingSheet1.toggle()
}) {
Text("Show Sheet1")
}
.sheet(isPresented: $isShowingSheet1) {
Text("Sheet1")
Button {
isShowingSheet1.toggle()
isShowingSheet2.toggle()
} label: {
Text("Show Sheet2")
}
}
.sheet(isPresented: $isShowingSheet2) {
Text("Sheet2")
}
}
}
}
저는 당신에게 솔직하게 말할 것이고 그렇게 쉬운 해결책을 상상합니다.지금까지와 같이 시트를 넣은 후 이 시트 안에 텍스트를 넣고(필수 없음) 그 안에 다른 시트를 작성한 후 두 번째 부울을 사용하여 다른 시트를 엽니다.마트리오스카처럼요
이 파티에는 조금 늦었지만, 지금까지의 답변 중 View Model이 작업을 수행할 가능성에 대해서는 언급하지 않았습니다.나는 스위프트의 전문가가 아니기 때문에UI(매우 새로운 UI)는 더 나은 방법이 있을 수 있지만, 제가 도달한 솔루션은 다음과 같습니다.
enum ActiveSheet: Identifiable {
case first
case second
var id: ActiveSheet { self }
}
struct MyView: View {
@ObservedObject private var viewModel: MyViewModel
private var activeSheet: Binding<ActiveSheet?> {
Binding<ActiveSheet?>(
get: { viewModel.activeSheet },
set: { viewModel.activeSheet = $0 }
)
}
init(viewModel: MyViewModel) {
self.viewModel = viewModel
}
var body: some View {
HStack {
/// some views
}
.onTapGesture {
viewModel.doSomething()
}
.sheet(item: activeSheet) { _ in
viewModel.activeSheetView()
}
}
}
...viewModel에서 -
@Published var activeSheet: ActiveSheet?
func activeSheetView() -> AnyView {
switch activeSheet {
case .first:
return AnyView(firstSheetView())
case .second:
return AnyView(secondSheetView())
default:
return AnyView(EmptyView())
}
}
// call this from the view, eg, when the user taps a button
func doSomething() {
activeSheet = .first // this will cause the sheet to be presented
}
여기서 firstSheetView()와 secondSheetView()는 필요한 액션을 제공합니다.시트 내용
모든 비즈니스 로직이 시야에 들어오지 않게 하기 때문에 저는 이 접근방식이 마음에 듭니다.
언급URL : https://stackoverflow.com/questions/58837007/multiple-sheetispresented-doesnt-work-in-swiftui
'programing' 카테고리의 다른 글
파라미터가 있는 Invoke-WebRequest, POST (0) | 2023.04.15 |
---|---|
SQL의 날짜 비교 쿼리 (0) | 2023.04.15 |
항목 사전을 다른 사전에 추가하려면 어떻게 해야 합니까? (0) | 2023.04.15 |
list append() 메서드가 새 목록을 반환하도록 허용하는 방법 (0) | 2023.04.15 |
vba의 셀 주소에서 Excel의 병합된 셀 값을 가져옵니다. (0) | 2023.04.15 |