iOS 스위프트UI: 프로그래밍 방식으로 보기 열기 또는 끄기
Swift에서 제시한 뷰의 팝 또는 해제를 프로그래밍 방식으로 만드는 방법에 대한 참조를 찾을 수 없었습니다.UI.
내가 보기에 유일한 방법은 이미 통합된 슬라이드 다우 액션을 모달에 사용하고(이 기능을 비활성화하려면 어떻게 해야 하는가), 뒤로 버튼을 네비게이션 스택에 사용하는 것입니다.
해결책을 아는 사람이 있나요?이게 버그인지 아니면 이대로 있는지 아세요?
이 예에서는 값 속성을 사용하고 있던 베타 5 릴리스 노트에 기재된 새로운 환경 변수를 사용합니다.이후 베타에서 wrapedValue 속성을 사용하도록 변경되었습니다.이 예는 현재 GM 버전에 대해 최신입니다.이 개념은 .sheet 수식자와 함께 표시되는 Modal 뷰를 해제하는 데 사용됩니다.
import SwiftUI
struct DetailView: View {
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
var body: some View {
Button(
"Here is Detail View. Tap to go back.",
action: { self.presentationMode.wrappedValue.dismiss() }
)
}
}
struct RootView: View {
var body: some View {
VStack {
NavigationLink(destination: DetailView())
{ Text("I am Root. Tap for Detail View.") }
}
}
}
struct ContentView: View {
var body: some View {
NavigationView {
RootView()
}
}
}
SwiftUI Xcode 베타 5
먼저 뷰를 해제하기 위해 어디서나 사용할 수 있는 해제 메서드가 있는 @Environment를 선언합니다.
import SwiftUI
struct GameView: View {
@Environment(\.presentationMode) var presentation
var body: some View {
Button("Done") {
self.presentation.wrappedValue.dismiss()
}
}
}
iOS 15 이상
iOS 15부터 새로운 기능을 사용할 수 있습니다.@Environment(\.dismiss)
:
struct SheetView: View {
@Environment(\.dismiss) var dismiss
var body: some View {
NavigationView {
Text("Sheet")
.toolbar {
Button("Done") {
dismiss()
}
}
}
}
}
(더 이상 사용할 필요가 없음)presentationMode.wrappedValue.dismiss()
.)
유용한 링크:
Navigation View에서 프로그래밍 방식으로 팝업을 수행할 수 있습니다.이건 베타 5입니다.뒤로 버튼은 필요 없습니다.원하는 방식으로 DetailView에서 showSelf 속성을 프로그래밍 방식으로 트리거할 수 있습니다.또한 마스터에 "Push" 텍스트를 표시할 필요가 없습니다.EmptyView()일 수 있습니다.그 결과, 보이지 않는 segue가 작성됩니다.
import SwiftUI
struct ContentView: View {
var body: some View {
NavigationView {
MasterView()
}
}
}
struct MasterView: View {
@State private var showDetail = false
var body: some View {
VStack {
NavigationLink(destination: DetailView(showSelf: $showDetail), isActive: $showDetail) {
Text("Push")
}
}
}
}
struct DetailView: View {
@Binding var showSelf: Bool
var body: some View {
Button(action: {
self.showSelf = false
}) {
Text("Pop")
}
}
}
#if DEBUG
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
#endif
저는 최근에 오픈 소스 프로젝트인swiftui-navigation-stack
( https://github.com/biobeats/swiftui-navigation-stack) 에는,NavigationStackView
, Swift용 대체 내비게이션스택UI. Repo의 readme에 설명된 몇 가지 기능을 제공합니다.예를 들어, 프로그래밍 방식으로 보기를 쉽게 푸시하고 팝할 수 있습니다.간단한 예를 들어 그 방법을 설명하겠습니다.
우선 계층 구조를NavigationStackVew
:
struct RootView: View {
var body: some View {
NavigationStackView {
View1()
}
}
}
NavigationStackView
계층은 다음과 같은 유용한 환경 개체에 액세스할 수 있습니다.NavigationStack
예를 들어 위의 질문에 따라 프로그래밍 방식으로 보기를 팝업할 수 있습니다.
struct View1: View {
var body: some View {
ZStack {
Color.yellow.edgesIgnoringSafeArea(.all)
VStack {
Text("VIEW 1")
Spacer()
PushView(destination: View2()) {
Text("PUSH TO VIEW 2")
}
}
}
}
}
struct View2: View {
@EnvironmentObject var navStack: NavigationStack
var body: some View {
ZStack {
Color.green.edgesIgnoringSafeArea(.all)
VStack {
Text("VIEW 2")
Spacer()
Button(action: {
self.navStack.pop()
}, label: {
Text("PROGRAMMATICALLY POP TO VIEW 1")
})
}
}
}
}
이 예에서는,PushView
탭으로 푸시 내비게이션을 트리거합니다.그리고 나서View2
환경 오브젝트를 사용하여 프로그래밍 방식으로 복귀합니다.
다음으로 완전한 예를 제시하겠습니다.
import SwiftUI
import NavigationStack
struct RootView: View {
var body: some View {
NavigationStackView {
View1()
}
}
}
struct View1: View {
var body: some View {
ZStack {
Color.yellow.edgesIgnoringSafeArea(.all)
VStack {
Text("VIEW 1")
Spacer()
PushView(destination: View2()) {
Text("PUSH TO VIEW 2")
}
}
}
}
}
struct View2: View {
@EnvironmentObject var navStack: NavigationStack
var body: some View {
ZStack {
Color.green.edgesIgnoringSafeArea(.all)
VStack {
Text("VIEW 2")
Spacer()
Button(action: {
self.navStack.pop()
}, label: {
Text("PROGRAMMATICALLY POP TO VIEW 1")
})
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
RootView()
}
}
결과는 다음과 같습니다.
또는 버튼에서 프로그래밍 방식으로 수행하지 않으려면 팝업해야 할 때마다 뷰 모델에서 내보낼 수 있습니다.저장될 때마다 값을 변경하는 @Published 에 등록합니다.
struct ContentView: View {
@ObservedObject var viewModel: ContentViewModel
@Environment(\.presentationMode) var presentationMode
init(viewModel: ContentViewModel) {
self.viewModel = viewModel
}
var body: some View {
Form {
TextField("Name", text: $viewModel.name)
.textContentType(.name)
}
.onAppear {
self.viewModel.cancellable = self.viewModel
.$saved
.sink(receiveValue: { saved in
guard saved else { return }
self.presentationMode.wrappedValue.dismiss()
}
)
}
}
}
class ContentViewModel: ObservableObject {
@Published var saved = false // This can store any value.
@Published var name = ""
var cancellable: AnyCancellable? // You can use a cancellable set if you have multiple observers.
func onSave() {
// Do the save.
// Emit the new value.
saved = true
}
}
매우 간단하므로 팔로우 코드를 확인하십시오.
첫 번째 표시
struct StartUpVC: View {
@State var selection: Int? = nil
var body: some View {
NavigationView{
NavigationLink(destination: LoginView().hiddenNavigationBarStyle(), tag: 1, selection: $selection) {
Button(action: {
print("Signup tapped")
self.selection = 1
}) {
HStack {
Spacer()
Text("Sign up")
Spacer()
}
}
}
}
}
세컨드 뷰
struct LoginView: View {
@Environment(\.presentationMode) var presentationMode
var body: some View {
NavigationView{
Button(action: {
print("Login tapped")
self.presentationMode.wrappedValue.dismiss()
}) {
HStack {
Image("Back")
.resizable()
.frame(width: 20, height: 20)
.padding(.leading, 20)
}
}
}
}
}
와 「 」를 .Transition
.
여기 커스텀 모달입니다.
struct ModalView<Content>: View where Content: View {
@Binding var isShowing: Bool
var content: () -> Content
var body: some View {
GeometryReader { geometry in
ZStack(alignment: .center) {
if (!self.isShowing) {
self.content()
}
if (self.isShowing) {
self.content()
.disabled(true)
.blur(radius: 3)
VStack {
Text("Modal")
}
.frame(width: geometry.size.width / 2,
height: geometry.size.height / 5)
.background(Color.secondary.colorInvert())
.foregroundColor(Color.primary)
.cornerRadius(20)
.transition(.moveAndFade) // associated transition to the modal view
}
}
}
}
}
재이 the the the the the the 를 재사용했다.Transition.moveAndFade
애니메이션 보기 및 전환 튜토리얼
이것은 다음과 같이 정의됩니다.
extension AnyTransition {
static var moveAndFade: AnyTransition {
let insertion = AnyTransition.move(edge: .trailing)
.combined(with: .opacity)
let removal = AnyTransition.scale()
.combined(with: .opacity)
return .asymmetric(insertion: insertion, removal: removal)
}
}
미리 보기가 아닌 시뮬레이터에서 다음과 같이 테스트할 수 있습니다.
struct ContentView: View {
@State var isShowingModal: Bool = false
func toggleModal() {
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
withAnimation {
self.isShowingModal = true
}
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
withAnimation {
self.isShowingModal = false
}
}
}
}
var body: some View {
ModalView(isShowing: $isShowingModal) {
NavigationView {
List(["1", "2", "3", "4", "5"].identified(by: \.self)) { row in
Text(row)
}.navigationBarTitle(Text("A List"), displayMode: .large)
}.onAppear { self.toggleModal() }
}
}
}
은 모달로 되어 .sliding in from the trailing edge
은 「」, 「」라고 합니다.zoom and fade out when it is dismissed
.
Swift의 핵심 컨셉UI는 데이터 흐름을 감시하는 것입니다.
하다를 요.@State
변수 및 변수 값을 변환하여 팝핑 및 해제를 제어합니다.
struct MyView: View {
@State
var showsUp = false
var body: some View {
Button(action: { self.showsUp.toggle() }) {
Text("Pop")
}
.presentation(
showsUp ? Modal(
Button(action: { self.showsUp.toggle() }) {
Text("Dismiss")
}
) : nil
)
}
}
issue가가가가가가가가가가가가가가가가가가 i i i i i i i i i i를 하려고 하는데 컴파일러에 했습니다.value
bindingpresentationMode로 합니다.을 " "로 변경"wrappedValue
저를 위해 문제를 해결해주셨어요.value
->wrappedValue
언어 업데이트입니다.Chuck H의 답변에 대한 코멘트로 이 노트가 더 적절할 것 같은데, 코멘트를 하기에는 충분한 rep 포인트가 없기 때문에, 이 변경과 편집을 제안했지만, 제 편집이 코멘트나 답변으로 더 적절하다고 거절당했습니다.
이렇게 하면 뷰도 해제됩니다.
let scenes = UIApplication.shared.connectedScenes
let windowScene = scenes.first as? UIWindowScene
let window = windowScene?.windows.first
window?.rootViewController?.dismiss(animated: true, completion: {
print("dismissed")
})
언급URL : https://stackoverflow.com/questions/56513568/ios-swiftui-pop-or-dismiss-view-programmatically
'programing' 카테고리의 다른 글
Rails raw SQL (0) | 2023.04.18 |
---|---|
Swift에서 네임스페이스를 사용하는 방법 (0) | 2023.04.18 |
bash 기본값 할당 (0) | 2023.04.18 |
WPF DataTemplate에서 DataType 속성을 사용하려면 어떻게 해야 합니까? (0) | 2023.04.18 |
Swift에서 Int를 문자열로 변환 (0) | 2023.04.18 |