SwiftUI View 4 (Alert, ConfirmationDialog, PresentationStyle)
Updated:
🔷Alert, ActionSheet
각각 알림창 및 액션 시트를 화면에 출력하는 컨테이너 객체 로써 UIkit 의 UIAlertController 를 그대로 활용하는데, 기존에는 UIAlertController 에서 parameter 로 UIAlertController.Style.action.Sheet 와 UIAlertController.Style.alert 이 각각 분리되서 사옫 됩니다.
👉 Alert
// Alert 출력 예시
struct AlertExample: View {
@State private var showingAlert = false
var body: some View {
VStack(spacing: 20) {
// Aler 버튼 1개
Button(action: { self.showingAlert.toggle() }) {
Text("버튼 1개 Alert").font(.title)
}
.alert("제목", isPresented: $showingAlert) {
Button("확인", role: .none) {}
} message: {
Text("내용")
}
// Alert 버튼 2개
Button(action: { self.showingAlert.toggle() }) {
Text("버튼 2개 Alert").font(.title)
}
.alert("제목", isPresented: $showingAlert) {
Button("삭제", role: .destructive) {}
Button("취소", role: .cancel) {}
} message: {
Text("내용")
}
}
}
}
👉 ConfirmationDialog
- iOS 14 이전에는
.actionSheet(...)
으로 사용되었지만, iOS 15 부터는.confirmationDialog()
라고 이름도 바뀌도 명렁어가 바뀌었습니다
// ios14 이전: .ActionSheet
// iOS15 부터 .confrmationDialog() 로 명칭이 바뀜
Button(action: { self.showingAlert.toggle()}) {
Text("Show Action Sheet").font(.title)
}
.confirmationDialog(
"Select",
isPresented: $showingAlert,
// title 은 기본적으로 .hidden 이라 .visible 로 해줘야 "Select" 라는 타이틀이 나타남
titleVisibility: .visible,
actions: {
Button("1") {}
Button("2") {}
Button("Cancel", role: .cancel) {}
}
) // ios14 이전: .ActionSheet
// iOS15 부터 .confrmationDialog() 로 명칭이 바뀜
Button(action: { self.showingAlert.toggle()}) {
Text("Show Action Sheet").font(.title)
}
.confirmationDialog(
"Select",
isPresented: $showingAlert,
// title 은 기본적으로 .hidden 이라 .visible 로 해줘야 "Select" 라는 타이틀이 나타남
titleVisibility: .visible,
actions: {
Button("1") {}
Button("2") {}
Button("Cancel", role: .cancel) {}
}
)
🔷 PresentationStyle
UIKit 에서는 present(_:animated:completion:) 매서드를 사용해 새로운 뷰 컨트롤러로 전화하는 것과 더불어 프리젠테이션 스타일을 변경하여 화면에 표시되는 방식을 다르게 지정할 수 도 있습니다
// iOS 12 이하
modalPresentationStyle = .fullscreen // iOS 12 이하일 때 기본값
// iOS 13 이상
modalPresentationStyle = .automatic // iOS 13 이상일때 기본값
modalPresentationStyle = .pageSheet // automatic 일때 대부분 pageSheet 로 동작
SwiftUI 에서는 pageSheet 의 Sheet, popover 스타일 2가지의 스타일을 제공합니다
modalPresentationStyle = .pageSheet // Sheet
modalPresentationStyle = .popover // Popover
👉 Sheet
-
pageSheet 스타일로 새로운 뷰를 출력합니다.
-
Alert, ActionSheet 와 사용법이 비슷한데, isPresented / item 은 출력 조건을 전달하고 content 매개 변수에는 출력될 뷰를 정의며, onDismiss 매개 변수에는 화면이 닫히기 직전에 수행할 작업을 정의하면 됩니다
EnvironmentMode
// presentationMode를 이용한 dismiss 예시
struct PresentationMode: View {
@State private var shoeingSheet = false
var body: some View {
Button(action: { self.shoeingSheet.toggle() }) {
Text("Present").font(.title).foregroundColor(.blue)
}
.sheet(
isPresented: $shoeingSheet,
onDismiss: { print("Dismissed") }, // 화면이 닫히기 전 수행할 작업
content: { Ch05_1_DataFlow.PresentedView() }) // 새로 출력될 화면
}
}
struct PresentedView: View {
// presentationMode 는 해당 뷰가 띄워져 있는 상태인지를 알려주는 isPresented 프로퍼티와
// 화면을 닫는 dismiss 메서드 이렇게 2가지를 제공하는 환경 변수 입니다
@Environment (\.presentationMode) var presentationMode
var body: some View {
Button(action: {
// isPresented의 값을 가져와 현재 뷰의 출력 상태를 확인합니다
if self.presentationMode.wrappedValue.isPresented {
// Sheet 스타일을 사용하는 경우는 버튼을 눌러서 dismiss 메서드를 호출하는 방법뿐만 아니라,
// 화면상단 부분을 잡아 아래 방향으로 끌어내리는 방법으로도 현재 화면을 닫을 수 있습니다
// 화면이 닫히고 나면 sheet 수식어에 onDismiss 매개 변수에 정의했던 클로저가 불리게 됩니다
self.presentationMode.wrappedValue.dismiss()
}
}) {
Text("Tap to Dismiss").font(.title).foregroundColor(.red)
}
}
}
BindingMode
- 위와 같이 presentationMode 환경 변수를 사용하지 않고 바인딩 프로퍼티를 사용하여 화면 닫기를 구현할 수 있습니다
// Binding 을 이용한 dismiss 예시
struct BindingMode: View {
@State private var showingSheet = false
var body: some View {
Button(action: { self.showingSheet.toggle() }) {
Text("BindingMode").font(.title).foregroundColor(.blue)
}
.sheet(isPresented: $showingSheet,
onDismiss: { print("Dismissed") },
content: {Ch05_1_DataFlow.PresentedViewWithBinding(isPresented: self.$showingSheet)
})
}
}
struct PresentedViewWithBinding: View {
@Binding var isPresented: Bool
var body: some View {
Button(action: { self.isPresented.toggle() }) {
Text("Tap to Dismiss").font(.title).foregroundColor(.red)
}
}
}
- 바인딩 프로퍼티에 화면 출력 여부를 관장하는 프포퍼티와 연동하여, 버튼을 눌렀을 때 그 값을 비활성화시켜 주면 dismiss() 메서드를 호출한 것과 같은 효과가 나타압니다
👉 Popover
-
Popover 는 콘텐츠와 관련된 추가적인 정보를 제공하거나 설정을 변경할 수 있도록 현제 화면 위로 일시적인 뷰를 표시하는 방식으로 상대적으로 큰화면인 아이패드에 사용될때 만들어진 스타일 입니다.
-
Popover 는 HIG(Human Interface Guidelines) 에서도 아이패드에서 사용되길 권장되지만 아이폰에서 사용되면 자동으로 PageSheet 스타일로 적용됩니다
// Popover 구현 예시
struct popverExample: View {
@State var showingPopover = false
var body: some View {
VStack {
Button(action: { self.showingPopover.toggle() }) {
Text("Popover Button").font(.largeTitle)
}
}
.popover(isPresented: $showingPopover,
// Popover 의 앵커로 사용할 영역 또는 위치를 결정 합니다
attachmentAnchor: .point(.bottomTrailing),
// popover 의 화살표가 어느 방향을 향할지 결정 합니다 기본값은 .top
arrowEdge: .top,
content: popoverContents)
}
// popover 에 표시될 콘텐츠
private func popoverContents() -> some View {
VStack(alignment: .leading) {
HStack {
Button(action: { self.showingPopover = false }) { // 팝오버 제거
Text("Cancel").foregroundColor(.red)
}
Spacer()
Text("New Event").font(.headline)
Spacer()
Button("Add(+)") {}
}
Divider().padding(.bottom, 8) // 구분선 추가
Text("Title")
TextField("제목", text: .constant(""))
Text("Contents")
TextField("내용", text: .constant(""))
Spacer()
}
.padding()
}
}
🔶 🔷 📌 🔑 👉
🗃 Reference
Apple developer official docs - https://developer.apple.com/documentation/swiftui/view/alert(_:ispresented:presenting:actions:message:)-8584l
SwiftUI로 액션시트 띄우기 (iOS 15, macOS Monterey) - https://seorenn.tistory.com/207
스윗한 SwiftUI - https://book.jacobko.info/#/book/1190014815
Leave a comment